- 1 - L'environnement de développement
- 2 - Premier programme
- 3 - Les variables
- 4 - Les structures de contrôle
- 5 - Les attributs, les énumerations
- 6 - Les tableaux
- 7 - Les sous-programmes
- 8 - Les types
- 9 - Les packages
- 10 - Le multi-tache
- 11 - Ecrire un programme pour le robot
- 12 - Utilisation de la lib PNG_Interface
- 13 - Exercice : SimpleForth
- 14 - Exercice : Startup_Manager
- 15 - Exercice : Gestion des déplacements
Maintenant qu'on a un interpréteur Forth et une procédure de démarrage sous la main, il sera bon de faire quelque chose... Pour commencer, je propose donc de faire bouger le robot un peu :) Rappel sur l'architecture du robotArchitecture globalLa partie soft du robot repose sur 2 carte "shix". Ces cartes contiennent un processeur (un sh4) et un FPGA. Traditionnellement, une carte est dédiée au traitement de la vidéo alors que l'autre sert à tout le reste, soit la gestion du déplacement, des capteurs/effecteurs du robot et la "stratégie". La première carte est nommé "camera" alors que l'autre est souvent désigné sous le doux nom de "master" La carte masterHistoriqueIl y fort fort longtemps, un groupe d'élèves d'exception, encadré par un professeur tout aussi exceptionnel ont suivit un cours à Telecom nommé AMEN. Leur projet était un asservissement sur FPGA (un asservissement, parce que sans ca le robot n'est rien, sur FPGA parce qu'il fallait un projet sur FPGA). Ce projet fut un tel succès que nous en utilisons toujours le résultat. La gestion du déplacement est donc répartie entre le FPGA et le processeur. Dans ce tutorial, on va s'occuper uniquement de la partie processeur, en supposant que la partie FPGA existe déjà et fonctionne :). Pour info, rapidement, le FPGA se pilote en écrivant à des endroits spécifiques en mémoire. Heureusement, pas besoin de savoir où écrire quoi, on va utiliser un package tout fait Note sur les unitésLe FPGA est super puissant, mais bon faire des multiplications, il aime pas trop donc on s'arrange pour choisir des unités les plus facile à manipuler pour lui. Ces unités sont le "top" de roues codeuse pour les distances (et non des bon vieux mètres) et la période d'asservissement pour l'unité de temps Les vitesses s’expriment donc naturellement en tops de roue codeuse/période d'asservissement :) Les angles s’expriment aussi en top de roue codeuse : 360° sera représenté par la distance parcourue par une roue pour que le robot fasse un tour, en laissant l'autre roue fixe. Les trucs importantsNotre FPGA réalise un asservissement "polaire" (cf. les cours de RCVA), c'est à dire qu'il prend en entrée une distance à parcourir et un angle, ainsi que quelques paramètres, type vitesse et vitesse angulaire max. Ensuite, il se démerde pour parcourir cette distance et cet angle. Conclusion, pour avancer tout droit, il faut définir une distance, mettre l'angle à 0 et lancer le processus. Pour tourner, il y a une petite ruse : on pourrait mettre la distance à 0 et l'angle à autre chose, ce devrait marcher (à tester). Pour des raisons historiques, on ne fait pas comme ça : avant de réaliser notre asservissement, le FPGA multiplie la distance parcourue par la roue droite par un coefficient et celle parcourue par le roue gauche par un autre coefficient. Si on met les 2 coefficients à "1", tout est logique, si on en met un à "1" et l'autre à "-1", tout se passe comme si on avait "retourné" un roue : quand on veut avancer, une roue par à l'envers et on tourne ! Donc pour tourner, la méthode testé est de mettre un coefficient à "1", l'autre à "-1", mettre une distance à parcourir et l'angle à 0 SimulationComme tout le monde n'a pas un robot à la maison, ou qu'un #{[^|\^~\@@~@ de mécano est en train de tout démonter, il nous faut un moyen de tester notre code sans robot physique. Pour cela, il existe un petit simulateur codé à l'arrache et récupérable comme ceci : hg clone http://bitbucket.org/telrob/robotjavacc ensuite, il faut importer ce projet dans Eclispe et y'a plus qu'à le lancer. Note: Pour ceux qui aurait du temps : réécrire ce simulateur ne serait pas du luxe. Squelette de baseComme d'hab, on va déjà récupérer un peu de code histoire de pas tout refaire de zéro : hg clone http://bitbucket.org/telrob/move cd move hg update -r 0 après ça, on se retrouve avec un joyeux bordel. Il y a beaucoup de répertoire pour rester le plus proche possible de la structure du "vrai" code du robot (voir la page 'Ecrire un programme pour le robot').
Les répertoires shix/contest et shix/hwinterface ont un sous-répertoire "main" (et "camera" sur le "vrai" code) qui contient le code spécifique à la shix master. Une bonne lecture pour commencer est "shix/hwinterface/main/shix-engines_base.ads" qui contient toute les fonctions nécessaire pour parler au FPGA. 1ers mouvementsQuestion 1: Completer les fonctions de move.adb Indication: utiliser le package shix-units dont l'ads est dans shix/hwinterface/main Notre robot roule !! Maintenant, tentons un truc plus sympa : un bon vieux carré. On modifie donc test_move.adb pour y introduire: for I in 1 .. 4 loop Move.Forward (500); Move.Turn (90.0); end loop; on lance et, et ça marche pas :( En effet, Forward et Turn lance un mouvement mais n'attendent pas le fin de celui-ci. Lorsqu'on donne un nouvel ordre, le précédent est oublié (enfin pas tout à fait : le FPGA d'arrange pour limiter l'accélération du robot donc si on demande au robot de tourner à fond sur 360° et qu'au bout de 180° on lui dit d'aller tout droit, la trajectoire va être un peu bizarre puisqu'une roue va freiner doucement pendant que l'autre freine puis ré accélère dans l'autre sens)
On va donc introduire une nouvelle fonction : "Wait_Move_End" qui, comme son nom l'indique attend la fin d'un mouvement. Cette fonction va nous renvoyer la raison de la fin de se mouvement, ainsi que la distance qu'il reste à parcourir. Oui je sais, les boulets qui vont écrire la strategie ignoreront ces valeurs de retour, mais bon, c'est plus propre quand même. Pour commencer, on définie 3 raisons de fin de mouvement : le mouvement est vraiment fini, on est bloqué quelque part (c'est à dire que les roues codeuses ne tournent plus) ou le mouvement prend trop de temps. Question 2: Définir un type pour les raisons de fin de mouvement, et un autre pour la valeur de retour de Wait_Move_End Maintenant, on va écrire cette fonction Wait_Move_End. Pour le 1er cas d'arret, c'est facile : le FPGA nous donne un bit "Moving" qui dit qu'il est en train de travailler. Quand ce bit passe à 0 c'est que tout va bien. Question 3: Ecrire un premier "Wait_End_Move" Indication: On écrira une tache qui verifie périodiquement l'état du bit "Moving". On prendra soin de faire communiquer les 2 taches par des objets "protected" et ca va rouler. Théoriquement, c'est bon, on est les rois du monde, d'ailleurs en simulation, ca marche nickel. Maintenant, dans la vrai vie, ca devrait marcher souvent mais dans certain cas, le robot va taper dans un mur (ou un epis de mais, ou un robot adverse) et donc si on attend indéfiniement que le robot soit arrivé, on va rester planté dans le mur... Question 4: Ajouter une gestion de timeout pour qu'on laisse tomber un mouvement qui mettrait trop de temps. Indication: Pour aider l'utilisateur qui ne veut pas avoir à spécifier un temps maximal à chaque fois qu'il demande un mouvement, on va definir un vitesse minimale pour le robot. On en déduira un temps de parcourt maximal (on rajoutera un petit quelque chose par sécurité). Pour amélirorer notre robot, on va maintenant détecter les bloquages. Pour cela, on va regarder la valeur des roues codeuses, si ca change trop peu entre 2 coups d'oeils, c'est qu'on est bloqué. Les roues codeuses sont des compteurs 16bits qui font régulirement des overflows : apres 2^16 - 1 vient 0. Pour une fois, on va voir un désavantage d'Ada : il est trop pointilleux et on ne peut pas faire une bête soustraction des 2 valeurs pour avoir la différence. Par exemple, supposons qu'un compteur soit à 2^16 - 523, soit 65013. Ensuite, le robot avance de 742 tops le compteur va donc être 2^16 - 523 + 742 = 2^16 + 216. Le compteur étant sur 16 bits, il vaudra donc 216. Notre programme va lire 65013 puis 216 et il faudra qu'il en déduise 742. En Ada, on ne peut pas faire (216 - 65013) de façon simple : cette opération provoque un overflow que gentiement le programme nous remonte via une exception. La solution ? A vous de voir... Question 5: Ajouter une tache qui verifie périodiquement la valeur des compteurs
|
|||




