Tutoriel · Intermédiaire · 30 min de lecture
Poursuite pure : suivre une trajectoire avec un seul réglage
Le contrôleur qui transforme des waypoints en braquage. Géométrie d'anticipation, pourquoi la valeur change avec la vitesse, et son coût en virage.
L’échelon qu’on n’enseigne jamais
Un planificateur donne une trajectoire. A* donne une liste de cases de grille ; un relevé donne une liste de points de passage ; une mission donne une ligne sur une carte. Aucun ne dit aux roues quoi faire.
C’est là que vit la poursuite pure, en un paragraphe de géométrie :
Trouvez le point sur la trajectoire à distance fixe devant vous. Roulez l’arc de cercle qui y passe. Répétez.
Il n’y a aucun signal d’erreur, aucun terme intégral, aucune table de gains. Il y a un seul nombre — la distance d’anticipation — et il décide de tout.
La géométrie
Placez le point but dans le repère propre du robot : x en avant, y à gauche, à distance L_d. Un arc de cercle de la position courante du robot via ce point a pour courbure
κ = 2y / L_d²
à lire deux fois, car tout en découle. Le décalage latéral y est au numérateur, donc l’arc se courbe plus fort quand le but est loin de l’axe. L’anticipation est au carré au dénominateur, donc la doubler divise la courbure par quatre.
Convertie en rayon, et en angle de braquage pour un véhicule d’empattement b :
R = L_d² / 2y δ = atan(2 b sin α / L_d)
Pour une propulsion différentielle, pas d’angle de braquage — vous commandez directement une vitesse de rotation, ω = v κ. Même courbure, autre actionneur.
Le seul réglage, et pourquoi il se bat avec lui-même
Anticipation courte. Le point but est proche, donc un petit décalage latéral produit une grande courbure. Le robot suit la trajectoire de près — et réagit violemment à chaque oscillation, y compris celles que son propre braquage vient de causer.
Anticipation longue. Le point but est loin, la courbure est douce, le braquage est lisse — et dans un virage le point but a déjà tourné pendant que le robot non, donc le robot coupe le virage.
Cela tire en sens opposés et rien dans l’algorithme ne les équilibre. Vous choisissez un nombre.
Le piège de toute dérivation de manuel
Écrivez la poursuite pure sur papier, avec un robot qui braque instantanément, et plus court est toujours meilleur. L’erreur chute de façon monotone quand l’anticipation diminue. Il n’y a aucun optimum, et la forme en U ci-dessus n’existe pas.
Les vrais robots ont du retard. Le braquage met du temps à atteindre l’angle commandé ; la pose sur laquelle vous agissez est vieille de quelques dizaines de millisecondes quand les roues répondent. Le simulateur modélise une constante de temps de braquage de 0,25 s et 0,15 s de retard de détection et calcul — 0,4 s de retard total, banal pour un rover amateur.
Ce retard est toute la raison de l’optimum. Une anticipation courte commande une correction, la correction arrive en retard, le robot a déjà dépassé l’erreur, et la commande suivante surcorrige dans l’autre sens. Un contrôleur plus rapide que son propre actionneur oscille. C’est le même fait qui régit le gain dérivé PID et celui derrière la distance d’arrêt : la latence n’est pas un détail, c’est elle qui fixe le réglage.
Comment la choisir alors ?
Les optimums mesurés, et ce qu’ils valent en unités transférables :
| Vitesse | Meilleure anticipation | En temps | Contre v × retard |
|---|---|---|---|
| 1,0 m/s | 0,9 m | 0,90 s | 2,25× |
| 1,5 m/s | 1,1 m | 0,73 s | 1,83× |
| 2,0 m/s | 1,3 m | 0,65 s | 1,62× |
| 3,0 m/s | 1,4 m | 0,47 s | 1,17× |
Deux lectures honnêtes de ce tableau.
L’anticipation croît avec la vitesse, mais moins que proportionnellement. Le conseil courant « mettez un nombre fixe de secondes de parcours » est proche mais faux — le temps chute de 0,90 s à 0,47 s sur cette plage.
Elle se situe à une à deux fois la distance parcourue pendant votre propre retard de commande. C’est la règle utile, car mesurable : trouvez votre retard, multipliez par votre vitesse, et partez de là. Sur ce robot, v × retard va de 0,4 m à 1,2 m et les optimums de 0,9 m à 1,4 m.
En pratique, embarquez-la comme petite loi linéaire et bornez-la :
float lookahead = constrain(K_LOOK * speed + L_MIN, L_MIN, L_MAX);
L_MIN compte plus que K_LOOK. À l’arrêt, la loi veut une anticipation nulle, soit une division par zéro déguisée.
L’implémenter
// Pure pursuit over a waypoint list. Returns the curvature to command.
float pursue(float x, float y, float heading, float lookahead) {
// 1. Where am I on the path? Search only near the arc length I last reached —
// a global search latches onto whichever segment happens to be nearest, and a
// path that doubles back will teleport your progress to a corner you passed
// twenty seconds ago.
float s = projectOntoPath(x, y, lastS);
lastS = max(lastS, s);
// 2. The goal point, one lookahead further along.
Point goal = pointAtArcLength(lastS + lookahead);
// 3. Into the robot frame, then straight into the curvature formula.
float dx = goal.x - x, dy = goal.y - y;
float lateral = -sin(heading) * dx + cos(heading) * dy;
float ld = max(0.3f, hypotf(dx, dy));
return 2.0f * lateral / (ld * ld);
}
Trois points en douze lignes valent plus que le reste :
lastSest un état, et n’avance que. Sans lui, tout parcours qui se croise échoue le contrôleur.- Bornez
ld. Quand le point but approche, la courbure tend vers l’infini. - Le point but est sur la trajectoire, pas le point de passage le plus proche. Viser des points de passage fait zigzaguer le robot entre eux ; viser un point sur le segment rend le mouvement lisse.
Ce qu’elle fera et ne fera pas
Elle ne s’arrêtera pas pour se tourner face à la trajectoire. La poursuite pure ne connaît pas l’arrêt — la courbure est une forme, et une forme exige d’avancer. Démarrez le robot à peu près aligné, ou roulez d’abord un court arc d’ouverture.
Elle a un rayon de braquage minimal que la trajectoire peut ignorer. Si un virage est plus serré que b / tan(δ_max), le robot ne peut pas le suivre quel que soit le réglage. Soit adoucissez la trajectoire, soit ralentissez pour le virage — objet d’un profil de mouvement.
Elle coupe toujours les virages, par conception. Dans l’essai mesuré à 2 m/s, elle a roulé 0,8 % de moins que la trajectoire commandée. Si c’est inacceptable, prenez un autre contrôleur — Stanley braque sur l’erreur transversale et passe au large plutôt que couper.
Elle ne corrige pas une mauvaise estimation de position. Tout ci-dessus suppose que le robot sait où il est. Nourrissez-la d’une position GPS à 1 Hz et l’erreur RMS passe de 0,09 m à 1,25 m — voyez navigation GPS par points de passage.
Quand ça tourne mal
| Symptôme | Généralement |
|---|---|
| Ondule en ligne droite | Anticipation trop courte pour le retard ; allongez-la ou mesurez le retard |
| Arrondit chaque virage | Anticipation trop longue — c’est le compromis, pas un bogue |
| Traverse vers une partie bien plus tardive de la trajectoire | Projection globale au lieu d’une fenêtrée qui suit l’abscisse |
| Tourne sur place au départ | La loi d’anticipation est tombée à zéro à vitesse nulle ; bornez L_MIN |
| Suit bien lent, erre vite | L’optimum a bougé ; programmez l’anticipation en vitesse |
| Dépasse le dernier point de passage | Rien ne lui dit de s’arrêter — la poursuite pure ne fait que braquer |
| Parfaite en simulation, faible sur le robot | La simulation n’avait aucun retard de braquage. Ajoutez-le et réglez de nouveau |
Roulez les deux contrôleurs sur le même parcours dans le simulateur de suivi de trajectoire — tirez l’anticipation et tout l’essai se retrace. Puis construisez le rover GPS à points de passage, où l’estimation de position devient le point dur.
Explorer le graphe
Fait partie de ces réalisations
Les projets et parcours d'apprentissage qui incluent ce tutoriel.
Pour aller plus loin