📈 Ruckig · gĂ©nĂ©ration de trajectoire en ligne

Chapitre 05
Step 1 — la solution temps-optimale

Objectifs du chapitre

1. Ce que calcule le Step 1

Le Step 1 traite un seul axe Ă  la fois. Son objectif est net : trouver la trajectoire qui atteint la cible (p_f, v_f, a_f) depuis l'Ă©tat courant (p₀, v₀, a₀) dans la durĂ©e minimale t_min, tout en respectant les bornes vₘₐₓ, aₘₐₓ et jₘₐₓ. C'est le sens de « temps-optimale » : aucune trajectoire admissible ne va plus vite.

💡 Intuition. Chaque axe court d'abord « sa » course la plus rapide, sans se soucier des autres. Le Step 1 rĂ©pond Ă  la question « en combien de temps, au mieux, cet axe peut-il arriver ? ». La coordination entre axes viendra ensuite (chapitre 7) ; ici, on cherche le record de vitesse individuel.

2. Des durées de phase à une équation polynomiale

On sait dĂ©jĂ  (chapitres 3 et 4) que la trajectoire est un profil Ă  sept segments, dĂ©crit par une famille et une direction. Ce qui reste inconnu, ce sont les durĂ©es de phase t₁ 
 t₇. Pour chaque candidat (famille × direction), la continuitĂ© entre segments et les conditions Ă  la cible (position, vitesse et accĂ©lĂ©ration finales imposĂ©es) fournissent juste assez d'Ă©quations pour fixer ces durĂ©es.

En reportant les intĂ©grations Ă  jerk constant dans ces conditions, le systĂšme se rĂ©duit Ă  une Ă©quation polynomiale en une durĂ©e inconnue — le plus souvent une cubique ou une quartique, selon la famille.

∑ Le calcul. Prenons le cas le plus simple : un profil « NONE » rest-to-rest (dĂ©part et arrivĂ©e Ă  l'arrĂȘt), oĂč l'accĂ©lĂ©ration ne fait qu'un aller-retour triangulaire — le jerk seul sculpte le mouvement, sans plateau d'accĂ©lĂ©ration ni de vitesse. Chaque phase de jerk dure t_j, avec j = ±jₘₐₓ. Sur une phase Ă  jerk constant partant de l'arrĂȘt :

a(t_j) = jₘₐₓ·t_j  Â·  v(t_j) = œ·jₘₐₓ·t_jÂČ  Â·  p(t_j) = ⅙·jₘₐₓ·t_jÂł

Par symétrie du triangle d'accélération (4 phases de jerk égales pour repartir et revenir à a = 0 et v = 0), le déplacement total s'écrit

Δp = jₘₐₓ·t_jÂł

Isoler t_j revient donc Ă  rĂ©soudre une Ă©quation cubique en t_j : t_j = (Δp / jₘₐₓ)^{1/3}. VoilĂ  d'oĂč sort le polynĂŽme — et dĂšs que v₀, a₀ ou un plateau entrent en jeu, il monte au degrĂ© 4.

3. La forme fermée : Cardano et Ferrari

Ces polynĂŽmes, Ruckig ne les rĂ©sout pas par itĂ©ration. Il applique les formules exactes : mĂ©thode de Cardano pour les cubiques, mĂ©thode de Ferrari pour les quartiques. Ces mĂ©thodes donnent toutes les racines en un nombre bornĂ© d'opĂ©rations arithmĂ©tiques — quelques racines carrĂ©es et cubiques, pas de boucle.

⏱ Temps de cycle. Une rĂ©solution itĂ©rative (Newton-Raphson, dichotomie) converge en un nombre de pas variable selon le point de dĂ©part et la tolĂ©rance : son pire temps d'exĂ©cution (WCET) est difficile Ă  garantir. La forme fermĂ©e, elle, coĂ»te toujours le mĂȘme nombre d'opĂ©rations : le WCET est connu d'avance. Sur un automate qui doit boucler Ă  chaque cycle, c'est cette prĂ©visibilitĂ© qui rend l'algorithme utilisable.

4. Sélectionner le meilleur candidat

Le Step 1 Ă©value toutes les combinaisons famille × direction. Chaque candidat livre un jeu de durĂ©es t₁ 
 t₇. On Ă©carte aussitĂŽt les candidats infaisables : durĂ©e nĂ©gative, ou profil qui violerait une borne (vₘₐₓ, aₘₐₓ). Parmi les candidats faisables restants, on retient celui de durĂ©e totale la plus courte : c'est lui qui dĂ©finit t_min.

⚠ PiĂšge. « Faisable » ne se dĂ©cide pas Ă  l'Ɠil. Un candidat peut donner des durĂ©es positives et sembler valide, tout en dĂ©passant une limite en cours de route. C'est pourquoi chaque profil retenu est re-vĂ©rifiĂ© par intĂ©gration avant d'ĂȘtre acceptĂ© (voir l'encart ruckig-scl).

5. Le « Block » et les intervalles bloqués

Le Step 1 ne produit pas seulement t_min. Il renvoie un Block : une description de toutes les durĂ©es rĂ©alisables pour cet axe. Et c'est lĂ  qu'apparaĂźt un fait contre-intuitif : au-delĂ  de t_min, toutes les durĂ©es ne sont pas atteignables. Il existe des intervalles bloquĂ©s — des plages de durĂ©es pour lesquelles aucun profil valide n'existe.

Axe des durĂ©es possibles t_f : une zone impossible avant t_min, le marqueur t_min, des rĂ©gions rĂ©alisables en vert, et un intervalle bloquĂ© en rouge oĂč aucun profil valide n'existe
Figure 5.1. L'axe des durĂ©es finales t_f pour un axe. À gauche de t_min, la zone est impossible (on ne peut pas aller plus vite que l'optimum). À partir de t_min, les durĂ©es sont rĂ©alisables (vert) — sauf dans un intervalle bloquĂ© (rouge) oĂč aucun profil admissible ne recolle l'Ă©tat initial Ă  la cible. Le Block est prĂ©cisĂ©ment cette carte : t_min + la liste des trous.

Pourquoi ces trous ? Parce que ralentir un profil n'est pas continu : passer d'un profil Ă  un autre peut exiger de changer de famille, et entre les deux, certaines durĂ©es ne correspondent Ă  aucune solution respectant les bornes. Cette information est cruciale pour la suite : lors de la synchronisation multi-axes (chapitre 7), Ruckig doit choisir une durĂ©e commune Ă  tous les axes. Cette durĂ©e commune devra Ă©viter les intervalles bloquĂ©s de chaque axe — sans quoi la trajectoire synchronisĂ©e serait tout simplement infaisable.

6. Les familles de repli « two-step »

Les trois familles principales couvrent l'immense majoritĂ© des cas. Mais certains Ă©tats initiaux pathologiques — par exemple une accĂ©lĂ©ration de dĂ©part dĂ©jĂ  au-delĂ  de ce qu'un profil standard peut absorber — les font toutes Ă©chouer. Ruckig dispose alors de familles de repli « two-step » (TwoStepNone, TwoStepAcc0, TwoStepVel, TwoStepAcc1Vel) qui dĂ©composent le problĂšme autrement et garantissent qu'une solution est toujours trouvĂ©e.

🔧 Dans ruckig-scl. Le Step 1 est rĂ©alisĂ© par ComputeBlock1Axis, qui remplit un UDT typeBlock : la durĂ©e minimale t_min et les Ă©ventuels intervalles bloquĂ©s. Les racines des Ă©quations de phase sont obtenues en forme fermĂ©e par SolveCubic (Cardano) et SolveQuartic (Ferrari) — coĂ»t dĂ©terministe, pas d'itĂ©ration non bornĂ©e. Chaque profil candidat est validĂ© par CheckProfile, qui le rĂ©-intĂšgre pour confirmer qu'il respecte les bornes et atteint bien la cible. Les familles TwoStep* servent de repli. L'implĂ©mentation est validĂ©e contre le vrai Ruckig Ă  ≈ 1e-15 (cas statique 1-DoF).

// SCL — principe du Step 1 pour un axe
ComputeBlock1Axis(input, block);   // -> typeBlock : t_min + intervalles bloqués
// en interne : pour chaque candidat famille × direction
//   racines via SolveCubic / SolveQuartic (forme fermée)
//   CheckProfile(profil) valide par intégration
//   on garde le profil valide de durée minimale

Récapitulatif