Un robot qui se répére sur le sol
Table des matières
Pré-requis
Ce tutoriel est composé d’un partie théorique et d’une partie pratique. La première partie nécessite juste quelques acquis du collège et mettront peu de gens en difficulté. La deuxième partie nécessite des connaissances de programmation en NXC. Je propose donc à ceux qui ne connaissent pas NXC de vous diriger vers le tutoriel Mon premier programme en NXC qui vous apprendra les rudiments à connaître.
Préambule
Avoir un robot qui avance, recule et qui tourne c’est bien mais nombreux d’entre vous auront pu remarquer qu’un robot évolue dans un monde réel et là, ça ne se passe jamais bien comme on voudrait : le robot dévie de sa trajectoire, il tourne plus ou pas assez, … Pour régler ce problème, des petits malins ont inventé ce qu’on appelle l’odométrie.
« L’odométrie est une technique permettant d’estimer la position d’un véhicule en mouvement. Le terme vient du grec hodos (voyage) et metron (mesure). » (Wikipédia)
Le principe
Pour éviter toute confusion, définissons ce que nous appellerons la position d’un robot. A moins d’avoir un hélicoptère qui évolue dans un environnement en trois dimension (et là je ne pourrais hélas pas vous aider), la position d’un robot aura trois composantes : son abscisse, son ordonnée et son cap. Voici un petit schéma pour mieux vous expliquer tout ça :
Revenons sur l’odométrie. Le principe est simple, on part du fait que la position initiale est connue. A partir de cette position connue, dès que le robot effectue un mouvement, on modifie la position à partir des données du mouvement pour obtenir la nouvelle position. Le mouvement le plus simple et le plus exploitable est le segment, d’un point de vue absolu, n’importe quel mouvement est composé d’une infinité de segments infiniment petits. Mais déterminer de tels segments est impossible dans le monde réel, donc on en fait une approximation en découpant le mouvement en petits mouvements (aussi petits que possible) qui se résument en un segment possédant un angle et une longueur. Encore un petit schéma pour expliquer la décomposition des mouvements :
En fait, chaque segment représente l’état du robot à un instant donné, l’intervalle de temps entre chaque mesure de l’état du robot défini la qualité de l’approximation : plus l’intervalle est grand et plus l’approximation est mauvaise, au contraire, plus l’intervalle est petit et plus l’approximation s’approche du mouvement réel. La longueur du segment est définie par la distance parcourue pendant l’intervalle de temps (considérable comme une vitesse) et l’angle du segment est défini par le cap du robot. Un peu de trigonométrie et nous pouvons exprimer chaque segment comme étant un vecteur à deux composantes : un déplacement selon l’axe des abscisses et un déplacement selon l’axe des ordonnées. A chaque nouveau segment, ses composantes viennent s’ajouter à celles de la position du robot : la nouvelle position est calculée !
Dans la pratique
Toutes ces explications c’est bien joli me direz vous, mais comment faire pour mesurer les déplacements d’un robot ? C’est ici que j’y viens. Peut être les avez vous déjà vu, LEGO a fabriqué ce qu’ils appellent des capteurs de rotation qui dans un langage un peu plus technique s’appellent des odomètres ou bien des roues codeuses. Leur objectif est simple : compter la distance parcourue par une roue. Voici le fameux capteur de rotation LEGO associé à une roue :
Maintenant qu’on a de quoi mesurer une distance, il suffit de mettre deux capteurs de rotation de part et d’autre du robot pour pouvoir mesurer, en plus de la distance, les rotations.
Côté programmation
Nous avons à peu près tout : les différents calculs à effectuer pour déterminer sa position ainsi qu’un moyen d’obtenir les mouvements du robot. Il ne nous reste plus qu’à coder tout ca ! Alors, c’est parti, on ouvre dans notre éditeur préféré BrixCC un nouveau fichier. Nous allons réaliser dans un premier temps les déclarations nécessaires :
// Declaration des capteurs de rotation #define rotGauche SENSOR_1 #define rotDroite SENSOR_2 // Tache principale task main() { // Definition des capteurs de rotation SetSensor(IN_1, SENSOR_ROTATION); SetSensor(IN_2, SENSOR_ROTATION); }
A présent, la tâche qui calculera en permanence la position du robot :
// Différents paramètres #define CcalculCap 165 // Paramètre permettant le calcul du cap actuel #define CcalculPos 384 // Paramètre permettant le calcul de position (Xcm = X / CcalculPos) #define CsensCapteurs 1 // Sens des capteurs, 1 ou -1 // Variables globales pour informer l'ensemble des autres taches de la position du robot int capActuel = 0; // Cap actuel du robot en degré int capDepart = 0; // Cap de départ du robot en degré long X = 0; // Position actuelle en x sans unité long Y = 0; // Position actuelle en y sans unité int Xcm = 0; // Position actuelle en x en cm int Ycm = 0; // Position actuelle en y en cm // Calcul de la position actuelle du robot task positionActuelle() { // Declaration des variables int L, LPrecedent = capDepart; int vitesse; int deltaX, deltaY; // Reset des capteurs de rotation ClearSensor(IN_1); ClearSensor(IN_2); while(true) { // Calcul du nouveau cap L = rotGauche + rotDroite; capActuel = capDepart + ( (rotGauche - rotDroite) * CcalculCap / 100 ); vitesse = L - LPrecedent; LPrecedent = L; // Définir les composantes du vecteur deltaX = CsensCapteurs * vitesse * Cos(capActuel); deltaY = CsensCapteurs * vitesse * Sin(capActuel); // Calcul de la nouvelle position X = X + deltaX; Y = Y + deltaY; Xcm = X / CcalculPos; Ycm = Y / CcalculPos; // Attendre 10ms Wait(10); } }
Cette tâche n’est pas directement exploitable, vous aurez surement remarqué qu’il faut donner quelques paramètres. Le paramètre CsensCapteurs est simple à définir, c’est 1 si les capteurs comptent en positif quand le robot « avance », sinon c’est -1. Ce que je vous propose pour les deux autres, c’est de faire une tâche d’affichage qui indique à l’écran la position (Xcm, Ycm et capActuel) de votre robot. Faites le avancer, si la distance affichée est trop petite/grande, ajustez CcalculPos. Puis faites le tourner, si le cap affiché est trop petit/grand, ajustez CcalculCap. Et comme je ne suis pas méchant, voici la petite tâche d’affichage :
// Afficher les coordonnées du robot task afficher() { while(true) { ClearScreen (); TextOut(0,LCD_LINE1,"X :" ); NumOut(65,LCD_LINE1,Xcm); TextOut(0,LCD_LINE2,"Y :" ); NumOut(65,LCD_LINE2,Ycm); TextOut(0,LCD_LINE3,"Cap :" ); NumOut(65,LCD_LINE3,capActuel); Wait(200); } }
Je vous rappelle que pour lancer une tâche il suffit d’utiliser le mot clef start et que les tâches ne sont pas bloquantes à l’appel c’est à dire qu’on peut faire fonctionner deux tâches en parallèle. Il faut donc penser à rajouter le code ci dessous dans la tâche main :
start positionActuelle; start afficher;
Le mot de la fin
J’espère que vous avez apprécié ce tutoriel. Surtout, n’hésitez pas à me poser des questions dans les commentaires de cet article, je suis à votre écoute.