Site ELEC344/ELEC381

Partie interactive du site pédagogique ELEC344/ELEC381 de Télécom ParisTech (occurrence 2010).

Catégories

Un protocole générique

Semaine du Vacances

Étant donné que on travaille avec le bluetooth ou avec le ZigBee pour établier la communication entre la PC et entre la carte du notre Heliokter ou avec l’IMU, donc j’ai commence à travailler sur un protocole de communication universel. Avec ce  protocole on aura la possibilité soit de recevoir ou envoyer des données au Heliokter en utilisant les mêmes fonctions quand on fait use de la communication par ZigBee ou par Bluetooh. Le protocole doit être générique du côte PC et du côte carte .

Au début de la semaine j’ai commencé à faire le protocole en utilisant la carte interface ZigBee. Cette carte à un module ZigBee et est relié à la PC directement. Après la remarque du Samuel sur la configuration de la carte j’ai réussi faire la communication avec la carte du TP.

Après j’ai commence à faire le codage des fonctions génériques dans les fichiers protocol.c et protocol.h et j’ai testé sur la carte su TP.

Vendredi et jeudi,  j’ai lu code de Fernando sur le i2c et on a travaille ensemble, surtout le vendredi,  pour trouver les erreurs de la communication i2c. Au début les fonctions de i2c bloquaient tout le système quand ils n’avaient pas de moteurs sur le bus. Après de regarder, en utilisant l’oscilloscope, les trames qui ont était envoyés  au ISL pour lire la température ou autres registres du ISL , on a trouvé que il avait des cas que n’ont était pas traités dans les interruptions.

Lundi 25  et Mardi 26

J’ai porté la communication par Bluetooth sur le protocole générique. Aussi avec Fernando on a réfléchi  sur les possibles erreurs du protocole du communication.

Nous avons pris comme référence le protocole de Mikrocopter pou faire la notre. Mais, on avait des problèmes quand le byte de fin de trame était présent en milieu de la trame.  La solution qu’on a pris est de utiliser le caratère de échappe ( ‘\’ ) pour identifier les données qui ont le même valeur qui le caractère du fin du trame et le même caractère du échappe.

J’ai fait les fonctions génériques pour le protocole, mais il fallait aussi modifier les fonctions du ZigBee et du Bluetooth, toujours des deux côtes : PC et carte.  Maintenait ça marche bien avec le bluetooth, pour le zigbee , avec Fernando, on a finit de faire le codage mais il  maque faire les test.

Heliokter bourdonne

J’ai passé la fin des vacances sur le filtre de Kalman, pour l’affiner/le corriger. Je me suis rendu compte avec la carte IMU que je ne prenais en fait pas en compte les gyroscopes et que je me basais seulement sur l’accéléromètre/magnétomètre (l’accéléromètre étant excentré par rapport au centre de rotation de la carte IMU, on s’en aperçoit mieux). Le modèle cinématique de mise à jour de létat en fonction des gyros était en fait légèrement erroné (une petite matrice par-ci …).

Bon bref j’ai réussi à regler tout ça et avoir des resultats corrects et sans lag.

Hier, on a commencé à intégrer tout le code et à contrôler les moteurs correctement avec l’I2C, mais je laisse les autres détailler, je n’etais pas là l’après-midi …

Et aujourd’hui, c’etait au tour de l’asservissement d’être integré dans le code et testé. Il a fallu évidemment faire face aux éternels problème d’orientation  (argh, la carte est à 45° par rapport à l’avant de l’Helico !) et d’angles, en passe d’être résolu ce soir.

Fernando et Miguel s’occupent d’un protocole de communcation par ZigBee ou Bluetooth (compatible avec celui de Mikrkopter) qui nous permettra de régler les coefficients du PID de manière dynamique (sans avoir à reflasher à chaque fois). Je leur laisse le soin de détailler.

Voilà une petite vidéo du rodéo actuel, avec un asservissement inexact et trop fort.

Wheely apprend à tenir debout

Jeudi et Vendredi, nous avons travaillé avec l’aide d’Alexis à faire tenir le robot debout.

Jeudi, la journée a été consacrée à corriger et à améliorer le code des capteurs et des filtres dont on déduit l’angle d’inclinaison du robot. Désormais, l’angle renvoyé lorsque la carte est en translation est cohérent, bien qu’on puisse affiner un chouilla encore.

Vendredi, nous avons joué avec le PID. J’ai programmé une interface qui permet d’ajuster tous les paramètres du PID dynamiquement via bluetooth, et de récupérer toutes les données de fonctionnement du robot en temps réel. Ainsi, nous avons réussi à faire tenir le robot debout pendant une dizaine de secondes. Nous avons perdu beaucoup de temps avec Alexis sur un plantage du au fait qu’un char truc[3] importé dans un autre fichier se déclare en extern char truc[3] et non en extern char* truc. Mais désormais, c’est clair et corrigé.

What’s next ? Continuer à jouer avec le PID pour améliorer les coefficients, et éventuellement affiner la fréquence de coupure du filtre complémentaire.

Résumé des épisodes précédents

Après avoir perdu sur la représentation des rotations de la carte en OpenGL, je me suis finalement mis à lire directement la DCM (matrice qui détermine l’attitude de la carte) pour savoir si l’algo FQA était bon. Ca permet surtout de vérifier pas mal de cas et de se convaincre que ça marche (quand la matrice n’a que des 0 et des +/- 1). Et le FQA a bien l’air de marcher !!

Sur la carte Heliokter, j’ai repris la méthode de Samuel pour déterminer comment les composants détectaient les axes et ça a presque tout de suite marché avec l’algorithme FQA. Vendredi soir j’ai juste eu le temps d’implémenter le FQA sur la carte et le filtre de Kalman sans pouvoir tout tester.

Aujourd’hui lundi, j’ai d’une part repris le code de visualisation OpenGL pour recevoir par Bluetooth directement les coefficients de la DCM calculés sur la carte et les représenter (sans se tromper ce coup-ci). C’est OK de ce point de vue là et ça marche bien. Il n’y a pas trop de singularité mais les changements d’attitude manquent de fluidité. C’etait prévu, mais ça permet aussi de voir que c’est effectivement très sensible aux vibrations. Après, peut-être que les vibrations faites avec la main sont différentes (notamment en terme de fréquence) de celles ressenties sur l’Heliokter.

D’autre part, j’ai regardé le comportement de mon filtre de Kalman  en fonction de différentes valeurs sur les incertitudes de mesures et de prédiction. J’ai surtout fait du cas extrême pour voir s’il n’y avait pas de grosses erreurs. C’est un peu le flou puisque je ne sais pas non plus si le modèle cinématique que j’ai implémenté dans le filtre est juste  mais j’ai observé des choses qui me semblaient cohérentes.

  1. Quand l’incertitude de prédiction est beaucoup plus faible (donc plus fiable !) que celle de mesure, j’ai mon état qui se décale lentement mais surement de l’état réel. C’est visiblement du au biais des gyroscopes, qui n’est pas corrigé dans l’état. C’est cohérent avec les incertitudes qu’on fixe.
  2. Quand l’incertitude de mesure est beaucoup plus faible que celle de prédiction, j’ai un filtre qui diverge très rapidement (en quelques itérations) sans que je puisse vraiment l’expliquer.
  3. Dans les autres cas (c’est à dire quand les incertitudes sont du même ordre de grandeur), mon état commence par se décaler de l’état réel puis le biais calculé dans l’état du filtre commence à se rapprocher du biais réél, ramenant l’état vers sa valeur réelle. Jusque là tout va bien. Mais le problème c’est que cela va de plus en plus vite et le biais calculé finit par dépasser rapidement la valeur du biais réel et s’écrase dans les choux (genre dépasement de capacité) quelques itérations plus tard.

Le jeu sur les valeurs de l’incertitude influe sur le temps que met le filtre à diverger. Ca va de jamais (cas extreme 1) à tout de suite (cas extreme 2). Je n’ai pas encore trouvé de valeurs qui marchent.

Voilà, après j’imagine qu’il faudra régler les incertitudes plus finement (c’est à dire avoir des coefficients différents pour chaque mesure et chaque prédiction, pour le moment) mais je ne sais pas si le comportement que j’observe présentement est typique d’un filtre de Kalman correct mal calibré ou d’un filtre complètement foireux …

Bluetooth

Hier jeudi j’ai fait une API pour la communication Bluetooth entre l’IMU et un ordinateur en linux. Ça me permettra faire de traces des capteurs qui seront envoyés au simulateur en temps réel. J’ai testé l’API et ça marche bien.

D’autre côte, apparentement  la cause du problème de la rotation sur le tangage a été parce que le vecteur mesure du magnétomètre n’a pas été projeté sur les axes X-Y de la base de référence  avant d’être passé au FQA .

Matrix reloaded ...

Hier, fort de la lecture de différents articles et codes source, je me suis lancé dans le code du filtre de Kalman, sans pouvoir toutefois réellement le tester (mais il compile !). J’ai fait attention d’optimiser un peu les opérations sur les flottants même si on peut sûrement faire quelque chose de mieux ‘hardcore style’. J’espère aussi qu’une opération flottante avec 0 prend moins de temps qu’une autre !

Au total, une passe de mon filtre de Kalman prend environ 870 multiplciations, 950 additions et 9 divisions. Je n’ai pas encore relié ça rigoureusement aux temps d’execution qu’on a mesuré avec Etienne mais il semble me souvenir que ça devrait faire aux alentours de 5ms. Vu le temps de réaction et l’inertie de l’hélicoptère, je pense qu’on est bon de ce point de vue là.

L’objectif de la journée d’aujourd’hui était d’intégrer l’algo FQA (pour la résolution du problème de Wahba) et le filtre de Kalman pour pouvoir le tester. Seulement, pour faire ça, il fallait d’abord vérifier que l’algo FQA marchait bien, à l’aide du visualisateur 3D. Le protocole est simple: Le visualisateur récupère les valeurs du capteur sur la carte (envoyées par Bluetooth), execute l’algo en local  (pour eviter des problèmes supplémentaires …) et met à jour l’affichage.

Et là, ça a été trèèèèèèèèèèèèèèèès long (oui, une journée complète de 10h, je ne comprends toujours pas comment le temps a pu filer ainsi !) pour avoir le lien entre l’affichage et la matrice renvoyée par l’algo avec tous les problèmes de changements de base (carte->monde physique réél->monde openGL->représentation de la carte dans le monde OpenGL), de matrices transposées ou pas, bref !

Voyant que je pataugeais, Etienne D. m’a bien aidé pour essayer de voir les choses clairement et systématiquement et on est (visiblement !) arrivé à quelque chose de cohérent là-dessus.

Ce qui nous a permis de voir que l’algo FQA (ainsi qu’une version allégée que Miguel a codé en parallèle) ne marche pas très bien, vraisemblablement à cause d’un problème d’ordre de rotation. J’ai essayé aussi de reprendre l’algo TRIAD (qui n’utilise que des opérations vectorielles donc normalement exempt de ces problèmes d’angle) sans grand succès non plus…

Bref, c’est un peu une journée désespérante de ce côté là, heureusement qu’Etienne avait à côté des résultats positifs (et que Pulse aussi, derrière nous, on pouvait s’amuser à les pinger ou à les synflooder pour se détendre :P ).

Filtres complémentaires : mission accomplie

Bon, suite aux travaux d’aujourd’hui, j’ai réussi à obtenir de très bonnes courbes. Notre problème d’offset sur les valeurs et de temps de réponse du filtre a été résolu en choisissant une valeur beaucoup plus grande pour la fréquence de coupure.

J’ai ensuite mis en place un benchmark assez complet : oscillation rapide, oscillation lente avec plateau ou non, oscillations rapides de demi amplitudes.

J’ai ensuite calibré le coefficient relatif entre l’accéléromètre et le gyroscope en utilisant des oscillations de différentes fréquence, l’un et l’autre se manifestant ainsi différemment. Le bon coefficient relatif est celui qui permet d’avoir une même mesure de l’angle pour des oscillations de fréquence différente.

Voici le graphique obtenu, avec en haut la commande d’angle donnée aux servomoteurs, et en dessous, l’inclinaison, calculée en degré, en fonction des données recueillie par les capteurs lors du mouvement. Le seul défaut que l’on peut constater est un angle calculé un chouilla en dessous de 0 lorsque l’on vient de remonter la carte (aucun soucis lorsqu’elle vient de descendre). Cela est probablement du à un petit défaut des servo vis à vis de la gravité, et n’est donc a priori pas lié à notre travail.

J’ai ensuite implémenté le nouveau filtre en C, modifié le code du gyroscope pour intégrer après filtrage (et non avant comme c’était fait), et créé deux fonctions get_angle_degree et get_angle_radian qui intègrent les bons coefficients.

Enfin, j’ai testé l’execution sur la carte de tout ça, envoyant via bluetooth le résultat de la commande get_angle_degree*100 (pour avoir de la précision malgré le cast en entier pour l’itoa).

J’obtiens des résultats à l’image de la simulation MATLAB, plutôt satisfaisants. Hormis pour le troisième type d’impulsion, ou ça ne colle pas. Ca n’atteint pas les 10°, et surtout, ça fait deux oscillations au lieu d’une.

Compte tenu que j’ai bien vérifié que le filtre et les données traitées (vitesse donnée par le gyroscope et accélération donnée par l’accéléromètre) sont exactement les mêmes je ne comprends pas trop. Si quelqu’un à une piste je suis preneur, en attendant, je continue à chercher…

Quand Wheely devient iWheely

Alors, en parallèle du reste, ces derniers jours j’ai aussi finalisé l’application iPhone et le serveur relais en Python. Voici un petit résumé de la joyeuse situation : L’application iPhone fournit des boutons pratiques (pause et connexion) et une IHM sympa (du moins du point de vue de son créateur) pour visualiser la consigne de pilotage données par l’accéléromètre (avec filtrage passe bas pour lisser et une dead zone pour envoyer facilement une consigne « ne bouge pas). Le serveur TCP Python lui attend une connexion de la part de l’application iPhone, typiquement au travers d’un réseau Wifi (ad-hoc ou pas). Il ouvre ensuite une liaison bluetooth profil SPP (RFCOMM), via la fabuleuse bibliothèque lightblue, vers Wheely, et lui transmet les consignes perçues de la part de l’iPhone.

En bref, toute la partie pilotage via iPhone-Wifi-Laptop-Bluetooth du robot est a priori bouclée. Il reste à s’occuper du traitement des consignes coté robot. J’ai aussi fait des tests de portée du Bluetooth, qui sont largement concluants, puisque on obtient une portée de 15m à vue, 10m derrière un mur. Tout ça pour dire que la vie est belle, ou iBelle devrais-je dire.

Communication et harmonie...

Hier, j’ai harmonisé le code qui avait été codé par chacun d’entre nous et donc avec différentes conventions… ça a ainsi permis au groupe d’arriver à un concensus sur la structure du code.

Aujourd’hui, j’ai enfin réussi à faire marcher la communication par l’UART1, et j’ai donc pu afficher les données filtrés de l’accéléromêtre et du gyroscope, ayant ainsi la confirmation que le code global fonctionne bien.

Ensuite, j’ai fait une fonction qui teste l’identifiant de la carte, pour qu’on ne puisse pas faire fonctionner le code prévu pour la carte logique sur une carte IMU et inversement. Cette fonction focntionne bien.

A l’arrivée de Daniel, nous avons pu tester mon code sur une carte IMU, nous avons bien réussi à allumer les LEDs simplement en changeant le #define dans le fichier de configuration global.

Nous avons eu pas mal de problèmes avec le bluetooth qui ne fonctionnait même plus avec la carte IMU. Nous avons finalement réussi à le faire fonctionner sur la carte logique! Il nous a semblé que les coordonnées que l’on additionne n’étaient plus les bonnes (on additionne le x de l’accéléromêtre avec le y du gyroscope). Daniel fera plus de tests et corrigera les calculs demain.

Et moi, je vais pouvoir me lancer dans le codage du LQR!

Les PCB de Pâques

Non, ils ne sont pas enc chocolat mais ils sont arrivés aujourd’hui (pour nous en tout cas et pour plusieurs autres groupes aussi je crois). Cette après-midi, nous avons d’ailleurs (entre autres) aidé Alexis à souder les composants

Voici une petite photo du joujou :


Ce soir, j’ai converti tout ce que j’avais fit sur l’IMU sur cette carte et ça c’est fait plutôt sans douleur puisqu’il suffisait de changer les affectations des pins (et encore, le Bluetooth etait branché au même endroit et il y avait juste une permutation entre les ports SPI pour l’accéléromètre et le magnétomètre). Modulo le magnéto-résistor vertical, non encore soudé sur la carte pour des raisons de fragilité,  on a donc  pour le moment les mêmes fonctionnalités que sur la carte IMU.

Pour ce qui est du Wahba, le résultat n’est toujours pas très probant mais Fernando m’a parlé d’un algorithme qui pourrait mieux nous aider que le TRIAD. Pourtant les valeurs de base semblent bonnes puisqu’avec le magnétometre seul, je détecte bien le lacet et avec l’accéléromètre seul je détecte bien le roulis/tangage. C’est la combinaison des deux (avec les noeuds au cerveau qui viennent avec, dès qu’on pense ordre des rotations dans l’espace) qui n’est pas au point.

Le fait de se voir tous les quatres après les vacances de Pâques a été aussi l’occasion de mettre tout le monde à jour, de fixer les tâches de chacun et de préparer la soutenance de demain.