🤖 Cinématique robotique · sur automate (PLC)

Chapitre 01
Introduction & contexte automate

Objectifs du chapitre

1. Cinématique : de quoi parle-t-on ?

Un robot manipulateur série est une chaîne de corps rigides (segments) reliés par des liaisons motorisées — le plus souvent rotoïdes (rotation) ou prismatiques (translation). La cinématique est l'étude du mouvement de cette chaîne sans se soucier des forces qui le produisent : elle relie les variables des liaisons à la position et à l'orientation de l'outil.

On distingue deux problèmes symétriques :

La cinématique directe est la brique de base de presque tout le reste : suivi de trajectoire, transformation d'un point outil, détection de collision, et surtout calibration (chapitre 7), qui identifie les paramètres géométriques réels du robot à partir de mesures. La maîtriser proprement, c'est se donner un socle fiable pour tout l'atelier logiciel du robot.

Périmètre du cours. On se concentre sur les robots série (chaîne ouverte : base → segment 1 → … → effecteur). Les robots parallèles (delta, hexapodes) ont une cinématique directe bien plus délicate — souvent numérique — et sortent du cadre. Les concepts de repères, de transformations homogènes et de Jacobien, eux, restent valables.

2. Repères, pose et espaces

À chaque corps du robot on attache un repère orthonormé direct. Le repère R0 est la base (le monde, fixe) ; le repère Rn est l'effecteur (l'outil). La pose d'un repère par rapport à un autre, c'est le couple :

pose = ( position t ∈ ℝ³,   orientation R ∈ SO(3) )

SO(3) est le groupe des matrices de rotation 3×3 (RTR = I, det R = +1), et l'ensemble des poses forme le groupe SE(3) des déplacements rigides. Une pose se code de façon compacte par une matrice homogène 4×4 (chapitre 2).

Deux espaces cohabitent en permanence, et tout le métier consiste à passer de l'un à l'autre :

EspaceVariableDimensionExemple
Articulaireq = (q1, …, qn)n (nb. d'axes)angles codeurs, consignes moteur
Cartésien / opérationnelpose ∈ SE(3)6 (3 pos. + 3 orient.)position & orientation de l'outil
FK :  q ∈ ℝn0Tn(q) ∈ SE(3)

3. Conventions de notation du cours

Ces conventions sont tenues dans tous les chapitres. En cas de doute, revenez ici.

NotationSignification
iTjtransformation homogène 4×4 plaçant le repère j dans le repère i
iRj, itjpartie rotation (3×3) et translation (3×1) de iTj
qivariable de la liaison i (angle si rotoïde, longueur si prismatique)
θ, d, a, αles 4 paramètres de Denavit-Hartenberg (chapitre 3)
ci, siraccourcis pour cos qi et sin qi ; c12 = cos(q1+q2)
Jmatrice jacobienne (6×n), chapitre 6
zi, piaxe z et origine du repère i, exprimés dans la base

Toujours des unités SI, toujours des radians. Dans tout le cours les angles sont en radians et les longueurs en mètres. Les fonctions SIN/COS des automates (comme la libm du C) travaillent en radians. Les IHM et les codeurs, eux, parlent souvent en degrés ou en incréments : convertissez aux frontières du système (rad := deg * PI / 180.0) et raisonnez en SI au cœur du calcul. Un COS(90.0) qui vaut −0.448 au lieu de 0.0 trahit immédiatement l'oubli.

4. Pourquoi de la cinématique sur un automate ?

Historiquement, la cinématique vit dans la baie de commande propriétaire du robot (KUKA, ABB, Fanuc…). Mais de plus en plus de machines sont pilotées par un automate programmable industriel (PLC) — Beckhoff TwinCAT, CODESYS, Siemens, Omron… — qui orchestre déjà les convoyeurs, la sécurité et les E/S. Y intégrer la cinématique du robot (ou d'un axe cartésien « maison ») apporte :

La norme IEC 61131-3 définit les langages de programmation des automates. Cinq langages coexistent (LD à contacts, FBD blocs, SFC grafcet, IL liste d'instructions, et ST — Structured Text). Pour du calcul mathématique matriciel, Structured Text s'impose : c'est un langage textuel proche du Pascal, avec boucles FOR, tableaux, structures et flottants. Tout le code de ce cours est en ST.

REAL ou LREAL ? Un automate manipule REAL (flottant 32 bits, ~7 chiffres significatifs) et LREAL (64 bits, ~15 chiffres). En cinématique on chaîne des produits de matrices : les erreurs d'arrondi s'accumulent, et un écart de position de quelques dixièmes de millimètre peut naître d'un simple calcul en 32 bits. Utilisez LREAL partout pour la géométrie ; réservez REAL aux E/S où la précision importe peu. Ce cours suppose LREAL.

5. Structures de données Structured Text

Un automate n'a pas de tas (pas de malloc) : toute la mémoire est allouée statiquement. On travaille donc avec des tableaux de taille fixe, ce qui tombe bien pour la cinématique où les dimensions (3, 4, nombre d'axes) sont connues à la compilation. Voici les types réutilisés dans tout le cours ; placez-les dans une liste de types global (GVL de types / DUT).

// ---- Types de base réutilisés dans tout le cours ----

TYPE T_VEC3 : ARRAY[0..2] OF LREAL; END_TYPE            // vecteur 3×1  (m ou sans dim.)
TYPE T_MAT3 : ARRAY[0..2, 0..2] OF LREAL; END_TYPE      // rotation 3×3
TYPE T_MAT4 : ARRAY[0..3, 0..3] OF LREAL; END_TYPE      // transformation homogène 4×4

// Une pose = position + orientation. Deux représentations pratiques :
TYPE T_POSE :
STRUCT
    x   : LREAL;   // position (m)
    y   : LREAL;
    z   : LREAL;
    R   : T_MAT3;  // orientation (matrice de rotation)
END_STRUCT
END_TYPE

// Paramètres de Denavit-Hartenberg d'une liaison (voir chapitre 3).
// theta et d contiennent les OFFSETS constants ; la variable articulaire
// est ajoutée à part lors de la cinématique directe.
TYPE T_DH :
STRUCT
    theta       : LREAL;  // rad — offset (souvent 0)
    d           : LREAL;  // m
    a           : LREAL;  // m
    alpha       : LREAL;  // rad
    isPrismatic : BOOL;   // TRUE = liaison prismatique, FALSE = rotoïde
END_STRUCT
END_TYPE

Deux briques d'algèbre linéaire reviennent sans cesse : la matrice identité et le produit de deux matrices 4×4. On les code une fois pour toutes. Notez le passage par VAR_IN_OUT pour éviter toute copie inutile de la matrice résultat — un réflexe temps réel.

// Remplit M avec la matrice identité 4×4.
FUNCTION Mat4Identity : BOOL
VAR_IN_OUT
    M : T_MAT4;
END_VAR
VAR
    i, j : INT;
END_VAR
    FOR i := 0 TO 3 DO
        FOR j := 0 TO 3 DO
            IF i = j THEN M[i, j] := 1.0; ELSE M[i, j] := 0.0; END_IF
        END_FOR
    END_FOR
    Mat4Identity := TRUE;
END_FUNCTION

// Produit matriciel C := A * B  (4×4). C doit être DISTINCT de A et B.
FUNCTION Mat4Mul : BOOL
VAR_IN_OUT
    A : T_MAT4;
    B : T_MAT4;
    C : T_MAT4;   // résultat
END_VAR
VAR
    i, j, k : INT;
    acc     : LREAL;
END_VAR
    FOR i := 0 TO 3 DO
        FOR j := 0 TO 3 DO
            acc := 0.0;
            FOR k := 0 TO 3 DO
                acc := acc + A[i, k] * B[k, j];
            END_FOR
            C[i, j] := acc;
        END_FOR
    END_FOR
    Mat4Mul := TRUE;
END_FUNCTION

Ne jamais écrire le résultat sur une entrée. Dans Mat4Mul, si C est la même variable que A ou B, on écrase des coefficients encore nécessaires au calcul en cours → résultat faux. Utilisez toujours une matrice temporaire distincte, puis recopiez si besoin. C'est l'équivalent PLC du classique aliasing de pointeurs en C.

6. Le modèle mental temps réel du PLC

Un automate exécute son programme dans une tâche cyclique : à chaque période Tcycle (p. ex. 1 ms), il lit les entrées, exécute tout le code, écrit les sorties — puis attend la période suivante. Deux règles d'or en découlent pour notre calcul :

Ordre de grandeur. Une multiplication LREAL coûte quelques nanosecondes sur un CPU d'automate moderne. Un produit de matrices 4×4 = 64 multiplications + 48 additions ≈ 0,5 µs. Chaîner 6 liaisons ≈ 3 µs. Même avec le Jacobien (chapitre 6), on reste bien en-deçà de la milliseconde : la cinématique n'est pas le goulot d'étranglement d'une tâche PLC. Le vrai risque n'est pas la lenteur mais le non-déterminisme (branche imprévue, appel bloquant) — que nos tableaux fixes éliminent par construction.

Exercices

Exercice 1 — Conversion degrés → radians aux frontières

Écrivez une fonction DegToRad(deg : LREAL) : LREAL et son inverse RadToDeg. Vérifiez que DegToRad(180.0) vaut π.

Voir la solution
FUNCTION DegToRad : LREAL
VAR_INPUT
    deg : LREAL;
END_VAR
    DegToRad := deg * 3.14159265358979 / 180.0;
END_FUNCTION

FUNCTION RadToDeg : LREAL
VAR_INPUT
    rad : LREAL;
END_VAR
    RadToDeg := rad * 180.0 / 3.14159265358979;
END_FUNCTION

En pratique, définissez une constante globale PI : LREAL := 3.14159265358979; (ou utilisez la constante fournie par la librairie mathématique de votre runtime) plutôt que de recopier la valeur. Convertir aux frontières — juste après la lecture IHM, juste avant l'écriture — garde tout le cœur du calcul en radians.

Exercice 2 — Produit matriciel et test d'identité

En réutilisant Mat4Identity et Mat4Mul, vérifiez la propriété I · I = I : construisez l'identité, multipliez-la par elle-même, et contrôlez que le résultat vaut bien l'identité (aux erreurs d'arrondi près).

Voir la solution
PROGRAM P_TestIdentite
VAR
    I1, I2, R : T_MAT4;
    i, j      : INT;
    ok        : BOOL := TRUE;
    attendu   : LREAL;
END_VAR

// --- corps ---
Mat4Identity(M := I1);
Mat4Identity(M := I2);
Mat4Mul(A := I1, B := I2, C := R);   // R := I * I

FOR i := 0 TO 3 DO
    FOR j := 0 TO 3 DO
        IF i = j THEN attendu := 1.0; ELSE attendu := 0.0; END_IF
        IF ABS(R[i, j] - attendu) > 1E-12 THEN ok := FALSE; END_IF
    END_FOR
END_FOR
// ok = TRUE si I*I = I

On compare toujours des flottants avec une tolérance (ici 1E-12), jamais avec = strict : deux calculs mathématiquement identiques peuvent différer au dernier bit. Ce réflexe vaut pour tout le cours.

Exercice 3 — Un type pour un bras 6 axes

Déclarez un type T_ROBOT6 contenant la table DH (6 liaisons) et le vecteur des 6 variables articulaires. Ce type servira de « fiche d'identité » du robot dans les chapitres suivants.

Voir la solution
TYPE T_ROBOT6 :
STRUCT
    dh : ARRAY[0..5] OF T_DH;    // table Denavit-Hartenberg (6 liaisons)
    q  : ARRAY[0..5] OF LREAL;   // variables articulaires (rad ou m)
END_STRUCT
END_TYPE

Regrouper la géométrie constante (dh) et l'état variable (q) dans une même structure clarifie les interfaces : les fonctions de cinématique prendront un T_ROBOT6 en VAR_IN_OUT et resteront génériques. On généralisera à n axes au chapitre 5.

Récapitulatif