Zum Inhalt springen

Koordinatensysteme und Rotationen ​

Jede Zahl, die ein Roboter für Position oder Orientierung verwendet, bezieht sich auf ein Koordinatensystem (Frame). Diese Seite behandelt Frames, Rotationsmatrizen, Roll-Nick-Gier-Winkel und Gimbal Lock, Quaternionen und homogene Transformationen und zeigt dann, wie sie im Transformationsbaum (tf) von Strido zusammenspielen.

In Strido

  • Basis-Frame: REP-103 (x vorwärts, y links, z oben), mit dem Ursprung im Mittelpunkt der vier Schnittpunkte der Hüftachsen. Er ist in hardware/kinematics.yaml (base_frame) definiert, zusammen mit der Rotation aus dem CAD-Frame (STEP).
  • Frame-Baum: ros2/strido_description/urdf/strido.urdf.xacro definiert base_link, imu_link, lidar_link, camera_link, camera_optical_frame und für jedes Bein *_hip, *_thigh, *_calf und *_foot.
  • Orientierung: Die Firmware führt einen Mahony-Filter aus und gibt eine Quaternion aus (firmware/strido_esp32s3/src/main.cpp). mcu_bridge veröffentlicht sie als /imu/data in imu_link.
  • Beintransformationen im Code: foot_position in packages/strido-core/src/strido/leg.py.

Frames ​

Ein Frame ist ein Ursprung plus drei orthogonale Einheitsachsen. Ein Punkt p hat für sich allein keine Koordinaten; er hat nur Koordinaten in einem Frame. Wir schreiben Ap für „die Koordinaten von p im Frame A“. Alle Frames hier sind rechtshändig: x^×y^=z^.

ROS legt die Konventionen in REP-103 fest. Körper-Frames verwenden x vorwärts, y links und z oben. Einheiten sind Meter und Radiant. Strido folgt dem. Sein base_link-Ursprung ist der Mittelpunkt der vier Schnittpunkte der Hüftachsen, daher liegen die Hüften bei (±0.120,±0.039,0)m (legs_base in hardware/kinematics.yaml).

Das CAD-Modell verwendet einen anderen Frame. hardware/kinematics.yaml speichert die Rotation, die STEP-Koordinaten in Basiskoordinaten abbildet:

Rbase←STEP=[0−10100001]

Das ist eine Drehung um +90∘ um z: Die STEP-y-Achse zeigt nach hinten, daher wird STEP −y zu Basis +x.

Rotationsmatrizen ​

Die Orientierung von Frame B relativ zu Frame A ist eine 3×3-Matrix ARB. Ihre Spalten sind die Einheitsachsen von B, ausgedrückt in A-Koordinaten. Ein Vektor wird umgerechnet als Av=ARBBv. Da die Spalten orthonormal sind:

R⊤R=I,detR=+1,R−1=R⊤

Rotationsmatrizen mit diesen Eigenschaften bilden die Gruppe SO(3). Die drei elementaren Rotationen sind:

Rx(θ)=[1000cos⁡θ−sin⁡θ0sin⁡θcos⁡θ],Ry(θ)=[cos⁡θ0sin⁡θ010−sin⁡θ0cos⁡θ],Rz(θ)=[cos⁡θ−sin⁡θ0sin⁡θcos⁡θ0001]

Rotationen werden durch Multiplikation verknüpft, ARC=ARBBRC. Die Reihenfolge zählt, weil Rotationen nicht kommutieren: im Allgemeinen gilt RxRy≠RyRx.

Rollen, Nicken, Gieren und Gimbal Lock ​

Eine Rotation hat drei Freiheitsgrade, ihre Matrix aber neun Zahlen. Euler-Winkel beschreiben sie mit drei aufeinanderfolgenden elementaren Rotationen. ROS und URDF verwenden Roll-Nick-Gier (RPY): Rollen ϕ um x, Nicken θ um y, Gieren ψ um z, in dieser Reihenfolge um die festen Achsen angewendet. Das ergibt:

R=Rz(ψ)Ry(θ)Rx(ϕ)

RPY ist leicht zu lesen. Die Kamera von Strido ist mit rpy="0 0.261799 0" montiert, einer Neigung von 15∘ nach unten. Ein um 5∘ „gerollter“ Körper ist leicht vorstellbar.

RPY-Winkel haben eine Singularität. Bei θ=±90∘ fallen Roll- und Gierachse zusammen, und nur ϕ±ψ ist definiert. Ein Freiheitsgrad ist verloren. Das ist der Gimbal Lock. In seiner Nähe kann eine kleine Orientierungsänderung einen großen Sprung der Winkel verursachen, und die Winkelraten

ϕ˙, θ˙, ψ˙

gehen gegen unendlich. Das liegt daran, dass die Matrix, die die Winkelgeschwindigkeit des Körpers auf (ϕ˙,θ˙,ψ˙) abbildet, 1/cos⁡θ enthält. Kein Satz aus drei Winkeln vermeidet das überall; es ist eine topologische Eigenschaft von SO(3). Ein gehender Roboter nickt selten um 90∘, ein Sturz kann es aber. Das ist ein Grund, warum Schätzer die Orientierung als Quaternion speichern.

Quaternionen ​

Eine Einheitsquaternion q=(w,x,y,z) mit w2+x2+y2+z2=1 kodiert eine Rotation um den Winkel α um die Einheitsachse n^:

q=(cos⁡α2, n^sin⁡α2)

Rotationen werden durch das Quaternionenprodukt (Hamilton-Produkt) verknüpft. q und −q ergeben dieselbe Rotation. Die Darstellung hat keine Singularität, braucht vier statt neun Zahlen und lässt sich nach numerischer Drift günstig renormieren. Die äquivalente Rotationsmatrix ist:

R(q)=[1−2(y2+z2)2(xy−wz)2(xz+wy)2(xy+wz)1−2(x2+z2)2(yz−wx)2(xz−wy)2(yz+wx)1−2(x2+y2)]

Die Firmware von Strido erhält q aus orientation.getQuaternion und sendet sie an den Pi. Die gelernte Policy verwendet nicht die rohen Winkel. Sie verwendet die Richtung der Schwerkraft aus Sicht des Körpers, Bg=R(q)⊤(0,0,−1)⊤ (siehe packages/strido-sim/src/strido_sim/rl/env.py). Dieser Vektor ist für jede Orientierung glatt und hat keinen Gimbal Lock. Siehe State Estimation, wie der Filter q erzeugt.

Homogene Transformationen ​

Eine Pose kombiniert eine Rotation und eine Translation. Eine homogene 4×4-Transformation fasst beide zusammen:

ATB=[ARBAtB0⊤1],[Ap1]=ATB[Bp1]

Hier ist AtB der Ursprung von B, ausgedrückt in A. Transformationen werden durch Multiplikation verkettet, ATC=ATBBTC. Die Inverse ist:

BTA=(ATB)−1=[R⊤−R⊤t0⊤1]

Jedes URDF-Gelenk ist genau eine solche Transformation. Zuerst kommt der feste <origin xyz rpy>. Bei einem Drehgelenk folgt eine Rotation um <axis> um den Gelenkwinkel.

Der tf-Baum von Strido ​

Diagramm wird gezeichnet…

robot_state_publisher berechnet die Beintransformationen aus den Gelenkwinkeln. Die Sensor-Frames sind fest. Zum Beispiel liegt imu_link bei (0.042,−0.004,−0.011)m, mit Achsen parallel zu base_link. camera_optical_frame verwendet rpy="-π/2 0 -π/2", damit seine z-Achse entlang der Blickrichtung zeigt, was die optische Konvention in REP-103 ist. odom → base_link kommt von gait_node, das die kommandierte Körpergeschwindigkeit integriert. Es ist keine gemessene Odometrie (siehe den Docstring von ros2/strido_control/strido_control/gait_node.py).

Für das vordere linke Bein lautet die URDF-Kette:

baseTfoot=Trans(0.1197,0.039,0)Rotx(q1)⏟FL_hip_jointTrans(0,0.0383,0)Roty(q2)⏟FL_thigh_jointTrans(0,0,−0.130)Roty(q3)⏟FL_calf_jointTrans(0,0,−0.124)⏟FL_foot_joint

Rechenbeispiel: Abduktion des vorderen linken Beins ​

In der Standpose (stand_pose() in strido/gait.py, Körperhöhe 0.17m) sind die Gelenkwinkel vorne links q1=0, q2=46.5∘ und q3=−96.0∘. Die Rotationen von Oberschenkel und Unterschenkel platzieren den Fuß bei phip=(0, 0.0383, −0.170)m relativ zum Ursprung des Hüftgelenks. Die 0.0383m sind der seitliche Versatz zur Beinebene, und der Fuß steht senkrecht unter der Hüfte.

Nun Abduktion um q1=10∘ (cos=0.9848, sin=0.1736):

Rx(10∘)phip=[00.9848⋅0.0383−0.1736⋅(−0.170)0.1736⋅0.0383+0.9848⋅(−0.170)]=[00.0672−0.1608]m

Addiert man den Hüftursprung (0.1197,0.039,0), liegt der Fuß bei (0.1197, 0.1062, −0.1608)m in base_link. foot_position("FL", (0.1745, 0.8121, -1.6761)) liefert denselben Punkt. Dieselbe Rotation als Quaternion ist (cos⁡5∘,sin⁡5∘,0,0)=(0.9962,0.0872,0,0).

Prüfen Sie sich selbst ​

  1. Warum ist ARB−1 einfach die Transponierte?
  2. Der IMU-Frame ist parallel zu base_link, aber um einige Zentimeter versetzt. Ändert der Versatz die gemessene Winkelgeschwindigkeit? Ändert er die gemessene Beschleunigung?
  3. Warum beobachtet die Policy den Schwerkraftvektor statt Rollen, Nicken und Gieren?
  4. Schreiben Sie camera_opticalTbase mithilfe der URDF-Transformationen.
Antworten
  1. Die Spalten sind orthonormal, daher gilt R⊤R=I.
  2. Die Winkelgeschwindigkeit ist überall auf einem starren Körper gleich, daher ändert der Versatz sie nicht. Die lineare Beschleunigung ändert sich: Ein versetzter Punkt sieht zusätzliche Terme ω×(ω×r)+ω˙×r.
  3. Er ist stetig und hat keine Singularität. Außerdem ist das Gieren mit einer IMU ohne Magnetometer nicht beobachtbar, und das Gehen braucht es nicht.
  4. (baseTcameracameraToptical)−1, wobei jeder Faktor aus xyz und rpy des Gelenks gebildet wird.

Weiterführende Literatur ​

MIT-Lizenz. Mechanik abgeleitet von Yertle (Jerome Graves). CAD, Simulation und native Tests sind kein Hardware-Nachweis – siehe Verifikation.