Accueil

Programmation / utilisation de la FoxBoard :

Je ne me considère pas comme un utilisateur avancé. Je programme en C, tout simplement. Pas de C++, je n’ai jamais réellement assimilé les concepts « avancés » de ce langage. Pour compiler les programmes que j’écris, j’utilise le « webcompiler » sur le site d’Acmesystems. Il me faut donc impérativement une connexion internet. Je n’utilise donc pas le SDK de la Fox. D’ailleurs, c’est assez difficile à utiliser sur un PC moyen sous Windows, vu la puissance nécessaire. Pour tout vous avouer, je ne sais même pas écrire un makefile. Donc je ne fais qu’un fichier .c qui regroupe toutes les fonctions du programme (~2000 lignes). Je ne peux donc pas importer de bibliothèques additionnelles lors de la compilation. Mais ça me convient très bien ! Quand je développe, je suis relié en Ethernet ou en WiFi au robot, selon que j’ai à faire rouler le robot ou non. Pour le WiFi, c’est le PC qui fait passerelle entre le robot et Internet, pour pouvoir développer depuis n’importe quel endroit disposant d’une connexion Ethernet, sans avoir à tout reconfigurer. Sur le PC, j’ai toujours une fenêtre telnet pour commander la Fox et avoir un retour texte, Internet explorer pour compiler, et l’éditeur (notepad++).

Quelques astuces:

Utiliser massivement le disque dur virtuel stocké en RAM. Je l’utilise pour stocker les fichiers de log, les programmes en cours de développement, tous les fichiers temporaires (carte 2D, fichier d’ordres…).

Ecrire un petit script sur la Fox récupère le programme compilé sur le site d’Acmesystems, et l’exécute dans la foulée.

IHM - Interface Homme Machine:

L’Interface Homme Machine est un aspect intéressant du projet. Il se décompose en plusieurs parties. Il était peut-être possible de faire plus simple, mais l’essentiel est que la chose fonctionne.

L’IHM est réalisée par une page web (HTML) sur le serveur web de la FoxBoard. Voici une vue de cette page.
Tout d’abord, le programme principal génère une image 2D de l’environnement juste après avoir reçu un ordre, et juste après avoir terminé d’exécuter un ordre. Y sont représentés plusieurs choses :
  • Le robot avec sa direction
  • Les points bleus représentent la trajectoire réalisée par le robot.
  • Les points noirs représentent les obstacles détectés.
  • Les cases vertes sont les endroits explorés et considérés comme libre d’obstacles
  • Les cases roses sont les endroits explorés et considérés comme interdits (obstacle proche)
L’image est une image BMP de résolution 600x600, en 256 couleurs, donc assez volumineuse (350ko). Elle est générée directement par le programme, sans librairie extérieure, vu la simplicité du format bmp.

Ensuite, les ordres sont récupérés de la manière suivante : sur la page web (HTML contenant du javascript), on clique sur la carte pour sélectionner les coordonnées cible. Du javascript permet de récupérer ces coordonnées de ce clic, et d’afficher un objet (une croix) sur la position sélectionnée, et de renseigner (de manière invisible) la partie coordonnée x,y du formulaire de la page html. On sélectionne ensuite l’ordre grâce à des « boutons radio » remplissant également le formulaire.

Une fois ce « formulaire » rempli, le bouton « exécuter » renvoie vers un script cgi. Ce script, très simple, va créer un fichier texte contenant (en ASCII) les coordonnées et un code représentatif de l’ordre sélectionné, le tout ayant été passé par le formulaire. Le fichier en question est créé en RAM, avec des temps d’accès très courts. Le script renvoie ensuite le client web, par une redirection, à nouveau vers la page HTML.

Ensuite, 5 fois par seconde, le programme principal surveille l’existence d’un fichier d’ordre. Si ce fichier existe, il le lit et interprète l’ordre, puis supprime le fichier. La réception d’un nouveau fichier fait également sortir le programme d’un éventuel ordre en cours d’exécution.

Intellingence - Algorithmes :

Repérage odométrique :
L’odométrie est la source principale d’information du robot. 40 fois par seconde, à partir de l’avancement mesuré de chaque roue, je recalcule la position et l’orientation du robot.

Asservissement :
Contrairement à une pratique répandue, je n’asservis pas l’avancement de chaque roue. J’asservis 2 choses : l’orientation du robot, et l’avancement du robot. Pour ces 2 parties, je réalise un simple PI (proportionnel – intégral). Pas de terme dérivé, car c’est trop compliqué à gérer, surtout avec des codeurs de résolution faible comme les miens. De plus, je n’attends pas de performances exceptionnelles qui justifieraient la présence d’un terme dérivé.

Gestion des capteurs :
La gestion des sonars est simple : l’objectif est de calculer les coordonnées 2D de l’obstacle qui vient d’être détecté. Tout d’abord, on élimine les mesures trop proches (peu fiables) ou trop lointaines (cône d’imprécision trop grand). Ensuite, à l’aide des coordonnées et de l’orientation du robot, on replace les obstacles calculés en coordonnées 2d (x, y). Il n’y a rien de compliqué là dedans. Il y a environ 8 mesures sonar par seconde, ce qui est peu.

Remplissage de la matrice d’obstacles :
Il s’agit d’un quadrillage de 5cm de côté. Ce quadrillage ne représente pas l’emplacement des obstacles, mais plutôt les endroits où le centre du robot est autorisé à aller ou non, ce qui est différent : si un obstacle est détecté, un certain nombre de cases autour seront considérées comme « interdites », puisque le robot n’est pas un simple point, mais un disque (en 2D). 2 informations sont renseignées. Tout d’abord, pour chaque obstacle détecté, on considère que les cases situées à moins de 10cm de l’obstacle sont interdites. Mais pour chaque mesure, on sait également que les cases situées entre le robot et l’obstacle sont libres. On remplit un triangle en vert, ce triangle représentant le cône de mesure du sonar (30°) jusqu’à 12cm avant l’obstacle détecté. On remplit en vert également les cases situées strictement à l’intérieur du périmètre du robot.


Amélioration de la carte:
L'amélioration de la carte consiste à remplire les trous au sein des zones vertes, c'est à dire les zones garanties libres d'obstacle. La probabilité d'avoir une zone interdite (rouge) d'épaisseur 1 ou 2 carreaux, et entourée par des zones vertes est nule, car une zone interdite mesure forcément plus de 2 carreaux.
Pour combler les trous, on réalise successivement des opérations de dilatation puis d'errosion. L'intérêt est d'améliorer la planification de trajectoire qui vient juste après, en évitant au robot de zigzaguer inutilement entre les zones inexplorées trop petites. Voir l'exemple ci dessous.


Planification de trajectoire :
L’algorithme est un algorithme 100% maison. On va se servir de la cartographie ci-dessus (le quadrillage avec des cases de 5cm de côté). La planification va se faire en 2 temps. Premier temps, trouver un chemin. A partir de la position de départ, on va numéroter les cases. La case 0 est la case où se trouve le robot. Si les cases à côté sont libres d’obstacle, on incrémente leur valeur de 2 par rapport à la position actuelle. Si la case adjacente est incertaine (blanche), on incrémente de 1 par rapport à la position actuelle. Si la case est interdite, on n’a pas le droit d’y aller. Ainsi, au fur et à mesure, on remplit l’espace 2D de toutes les positions où le robot peut aller, avec dans chaque case une « distance » par rapport à la position actuelle du robot. Regardez le schéma ci-dessous pour comprendre facilement. On s’arrête quand on a atteint la cible, ou alors si on est allé trop loin sans trouver de chemin.


Pour en déduire un chemin (carré et chaotique), il suffit de remonter les cases depuis la cible vers la position initiale.
Puis il faut simplifier la trajectoire. Pour cela, à partir de la position de départ, on essaye de tirer des segments les plus longs possibles depuis la position de départ jusqu’à une position de la trajectoire, sachant que le segment doit rester intégralement dans des zones vertes, voire dans des zones blanches… et ainsi de suite. La suite de segments ainsi trouvée constitue la trajectoire planifiée.


Exemple sur un cas concret:
Regardez la vidéo pour voir ce que ça donne.

Recalage de la position:
Non finalisé, à base de transformée de Hough. L’objectif est de détecter les murs à partir du nuage de points 2D représentant les obstacles. La transformée de Hough permet de détecter les droites parmi le nuage de points des 100 dernières mesures sonar. Le robot doit alors se recaler en orientation en considérant que tous les murs sont perpendiculaires ou parallèles 2 à 2. Il ne devrait se recaler que si le mur détecté est d’orientation crédible (+/-20° par rapport aux murs connus). Et s’il s’agit d’un mur déjà connu, on peut également se recaler en profondeur. Mais cette dernière partie n’est que théorique pour l’instant, je n’ai pas encore réussi à optimiser suffisamment l’algorithme pour le faire raisonnablement tenir (en temps de calcul) dans la Fox.

Le FOOT :

BOB3 est équipé d'une caméra CMU CAM. La caméra lui permet de repérer un objet de couleur dans l'image. La caméra envoie directement les coordonnées 2D de l'objet dans l'image. Gràce à ces coordonnè et à la position 2D de BOB sur le terrain, on estime la position de la balle sur le terrain. L'estimation de la position est surtout imprécise en profondeur. Il faut privilégier les objets bien contrastés avec le fond. J'utilise une balle verte, qui contraste avec le parquet marron. Des essais avec une balle orange étaient catastrophiques.

Voici comment BOB3 sait jouer au foot. Pour initialiser le jeu, il faut placer BOB3 en position de gardien, au centre des buts. On lui ordonne de mémoriser cette position.
De là on peut le déplacer où on veut. A partir d'une position choisie, on ordonne à BOB de jouer au foot. Il se met alors à tourner sur lui même à la recherche de la balle. Il tourne successivement de 10 degré en 10 degré en attendant d'avoir repéré la balle avec la CMUCAM. Une fois la balle repérée, il estime sa position.
Il va alors déterminer la position à partir de laquelle il faut tirer pour marquer un but. Cette position se situe dans l'alignement entre le centre du but et la balle, 35cm derriere la balle. Il faut que la balle soit dans un certain angle par rapport au but: 60degrés de part et d'autre de la ligne médiane. Il faut aussi que la position de tir soit dégagée de tout obstacle.


Si toutes ces conditions sont remplies, il se dirige vers la position de tir, en évitant les obstacles, grâce à l'algorithme décrit ci dessus. La balle est elle même considérée comme un obstacle temporaire, qui sera effacé de la carte après l'action.
Une fois arrivé à la position de tir, il s'oriente vers la position connue de la balle (et donc vers le but). Il rep&agave;re à nouveau la balle avec la CMUCAM, et estime à nouveau sa position. Si la balle n'est pas trop décentrée, alors il tire; sinon, il va vers la nouvelle position de tir.
Pour tirer le but, il se dirige d'abord vers la position connue de la balle, et sans s'arrêter, il fonce vers la direction du but.

Regardez la vidéo pour voir ce que ça donne.

Leon | 04/05/2008