====== ODOMETRIE ====== L'odométrie est une technique de localisation relative d'un robot. En mesurant tous les déplacements du robot depuis son point d'origine, il est possible de calculer à chaque instant sa position et son orientation sur la table. ===== Principe ===== Un odomètre (roue codeuse placée au centre du robot) nous permet de connaître la distance parcourue par le robot. Cette seule information de distance ne permet pas de positionner le robot dans un système de coordonnées. Pour cela, il faut 2 odomètres (roues codeuses indépendantes ou montées directement sur les moteurs). A chaque intervalle de temps, on mesure la distance parcourue par les roues droite et gauche. ==== Approximation par segment de droite ==== On suppose que la trajectoire du robot est découpée en une série de segment. A chaque intervalle de temps, le robot effectue un déplacement rectiligne suivant son orientation précédente. \\ {{ :robotics:segment.png?400| }} === Distance moyenne du robot === La distance moyenne parcourue par le robot est la distance moyenne parcourue par les 2 roues du robot : Δdr = (Δdd + Δdg) / 2. === Orientation du robot === La différence entre les 2 roues nous donne l'orientation du robot : Δθ = atan[(Δdd - Δdg) / entraxe] On peut considérer que Δθ ne varie pas beaucoup entre 2 mesures donc grâce à l'approximation de Gauss, on peut écrire : Δθ = (Δdd - Δdg) / entraxe === Coordonnées du robot === On peut maintenant définir la nouvelle position du robot et son orientation. Δx = Δdr.cos θA Δy = Δdr.sin θA xB = xA + Δx yB = yA + Δy θB = θA + Δθ === Conclusion === Cette méthode est très simple à mettre en œuvre sur un petit microcontroleur. Par contre, l'approximation est assez grossière et peut engendrer une dérive assez importante sur un parcours long. ==== Approximation par arc de cercle ==== La trajectoire du robot est découpée en une série d'arc de cercle. A chaque intervalle de temps, le robot effectue un arc de cercle de rayon R et d'angle a. \\ {{ :robotics:arc.png?400| }} === Distance moyenne du robot === La distance moyenne parcourue par le robot est la distance moyenne parcourue par les 2 roues du robot : Δd = (Δdd + Δdg) / 2. === Orientation du robot === La différence entre les 2 roues est un arc de cercle qui a pour rayon l'entraxe des 2 roues. L'angle de l'arc nous donne l'orientation du robot : Δθ = (Δdd - Δdg) / entraxe === Rayon de courbure === En considérant le rayon R au milieu de l'entraxe e des 2 roues on a : R = Δd / Δθ === Coordonnées du centre de l'arc === A partir de la position du robot et de son orientation, on va pouvoir définir le centre de l'arc de cercle O. xO = xA - R.sin θA yO = yA + R.cos θA === Coordonnées du robot === On peut maintenant définir la nouvelle position du robot : θB = θA + Δθ xB = xO + R.sin θB yB = yO - R.cos θB Cas particulier où Δθ = 0, on a : xB = xA + Δd.cos θB yB = yA + Δd.sin θB === Conclusion === Cette approximation est plus précise que l'approximation par segment mais nécessite plus de calcul. ===== Implementation ===== typedef struct { double x; /* en pulse */ double y; double O; /* en rad */ } position; /* mise a jour la nouvelle position du robot (x, y, O) * par approximation de segment de droite */ void calcul_position_segment(position *p, double distance, double angle) { p->x += distance * cos(p->O); p->y += distance * sin(p->O); p->O += angle/entraxe; //atan2(angle, entraxe); } /* mise a jour de la nouvelle position du robot (x, y, O) * par approximation d'arc de cercle */ void calcul_position_arc(position *p, double distance, double angle) { /* rayon et angle de l'arc de cercle */ double r, a; /* coordonnées du centre de l'arc de cercle */ double xo, yo; if (angle == 0) { p->x += distance * cos(p->O); p->y += distance * sin(p->O); } else { /* calcul des caractéristiques de l'arc de cercle */ a = angle / entraxe; r = distance / a; /* centre de l'arc de cercle */ xo = p->x - r * sin(p->O); yo = p->y + r * cos(p->O); /* coordonnees du robot */ p->O += a; p->x = xo + r * sin(p->O); p->y = yo - r * cos(p->O); } } /* delta_roue_droite et delta_roue_gauche sont les distance en pulses * parcourue par les roues droite et gauche en un cycle */ void odometrie(position *p, signed short delta_roue_droite, signed short delta_roue_gauche) { double delta_distance = 0, delta_angle = 0; delta_distance = ((double) (delta_roue_droite + delta_roue_gauche)) / 2; delta_angle = (double) (delta_roue_droite - delta_roue_gauche); //calcul_position_segment(p, delta_distance, delta_angle); calcul_position_arc(p, delta_distance, delta_angle); } ===== Conclusion ===== Pour des mesures régulières et fréquentes dans un environnement restreint (table eurobot 2 x 3 m), les deux approximations sont sensiblement équivalentes. Nous avons effectué les calculs sur une ARDUINO UNO et tracé les deux courbes qui sont quasiment identiques. {{:robotics:mongraphe.png?400|}}