Zum Inhalt springen

Reinforcement Learning für die Fortbewegung ​

Wie sich ein Lauf-Controller in der Simulation durch Versuch und Irrtum lernen lässt: Markov-Entscheidungsprozesse, Returns und Value Functions, das Policy-Gradient-Theorem, GAE, PPO sowie die genaue Observation, Action und Reward für Strido, dazu, wie Domain Randomization die Sim-to-Real-Lücke verkleinert.

In Strido

Die Umgebung ist StridoEnv in packages/strido-sim/src/strido_sim/rl/env.py (Gymnasium + MuJoCo); das Training ist rl/train.py (stable-baselines3 PPO auf der CPU). Gemeinsame Konstanten (CONTROL_DT, ACTION_SCALE, COMMAND_RANGES) liegen in packages/strido-core/src/strido/policy.py, und der Roboter führt das exportierte Netz in ros2/strido_control/strido_control/policy_node.py aus. Arbeitsablauf: Simulation und RL und docs/simulation.md.

Der Markov-Entscheidungsprozess ​

Ein MDP ist ein Tupel (S,A,P,r,γ): Zustände, Actions, Übergangswahrscheinlichkeiten P(s′∣s,a), Reward r(s,a) und Diskontfaktor γ∈[0,1). In jedem Schritt beobachtet der Agent st, zieht at∼πθ(a∣st) aus einer Policy mit Parametern θ (einem neuronalen Netz), und die Umgebung liefert rt und st+1. Markov bedeutet, dass st+1 nur von (st,at) abhängt, nicht von der früheren Geschichte. Ein realer Roboter sieht nur einen Teil des Zustands (ein POMDP); in der Praxis fügen wir genug Geschichte hinzu (hier die vorherige Action und einen Gait-Takt), damit die Observation nahezu markovsch wird.

Returns und Diskontierung ​

Der Return ab Zeitpunkt t ist die diskontierte Summe künftiger Rewards:

Gt=∑k=0∞γkrt+k

Die Diskontierung hält die Summe endlich und drückt eine Präferenz für früheren Reward aus. Der effektive Horizont beträgt etwa 1/(1−γ) Schritte. Rechenbeispiel: Strido trainiert mit γ=0.99 (train.py) bei einer Policy-Rate von 50Hz (Δt=0.02s), der Horizont beträgt also etwa 100 Schritte =2s, d. h. fünf Gangzyklen zu 0.4s: lang genug, um Nicht-Umfallen zu bewerten, kurz genug, um schnell zu lernen.

Das Ziel ist der erwartete Return J(θ)=Eτ∼πθ[G0] über Trajektorien τ.

Value Functions ​

Vπ(s)=Eπ[Gt∣st=s],Qπ(s,a)=Eπ[Gt∣st=s,at=a]

Sie erfüllen die Bellman-Gleichung

Vπ(s)=Ea∼π,s′∼P[r(s,a)+γVπ(s′)]

Der Advantage Aπ(s,a)=Qπ(s,a)−Vπ(s) misst, um wie viel besser die Action a als der Durchschnitt der Policy im Zustand s ist.

Das Policy-Gradient-Theorem ​

Wir wollen ∇θJ, ohne durch die (unbekannte, nicht differenzierbare) Physik zu differenzieren. Der Likelihood-Ratio-Trick liefert

∇θJ(θ)=Eπθ[∑t∇θlog⁡πθ(at∣st)Aπ(st,at)]

In Worten: Erhöhe die Log-Wahrscheinlichkeit von Actions, die sich als besser als der Durchschnitt erwiesen haben, und senke sie für schlechtere. Benötigt werden nur Stichproben aus dem Simulator und der Gradient der eigenen Log-Wahrscheinlichkeit des Netzes. Die Verwendung des Advantage (statt Gt) zieht eine Baseline V(s) ab, was den Gradienten erwartungstreu lässt, aber seine Varianz stark verringert.

Generalised Advantage Estimation (GAE) ​

Der Advantage wird aus einem gelernten Critic Vϕ geschätzt. Der einstufige TD-Fehler ist

δt=rt+γVϕ(st+1)−Vϕ(st)

GAE bildet eine exponentiell gewichtete Summe davon:

A^t=∑l=0∞(γλ)lδt+l

λ=0 ergibt die varianzarme, aber verzerrte einstufige Schätzung; λ=1 ergibt den erwartungstreuen, aber varianzreichen Monte-Carlo-Return minus V. Strido verwendet λ=0.95 (gae_lambda in train.py). Bei Abbruch (einem Sturz) ist der Bootstrap Vϕ(st+1) null; bei Kürzung durch das Zeitlimit bleibt er erhalten, da der Roboter hätte weitermachen können.

PPO: Proximal Policy Optimisation ​

Der einfache Policy Gradient macht einen Schritt pro Batch, und ein zu großer Schritt kann die Policy ruinieren. PPO verwendet jeden Batch für mehrere Epochen wieder und verhindert dabei, dass sich die neue Policy weit von derjenigen entfernt, die die Daten gesammelt hat. Mit dem Wahrscheinlichkeitsverhältnis

ρt(θ)=πθ(at∣st)πθold(at∣st)

lautet das geclippte Surrogat-Ziel

LCLIP(θ)=Et[min(ρtA^t,clip(ρt,1−ϵ,1+ϵ)A^t)]

Für eine gute Action (A^>0) endet der Gewinn, sobald ρ>1+ϵ; für eine schlechte (A^<0), sobald ρ<1−ϵ. Das min macht es zu einer pessimistischen Schranke, sodass kein Anreiz besteht, sich weiter zu bewegen. Der vollständige Verlust ergänzt einen Regressionsterm für den Critic und optional einen Entropiebonus, der belohnt, die Policy zufällig genug für die Exploration zu halten:

L(θ,ϕ)=−LCLIP(θ)+c1Et[(Vϕ(st)−G^t)2]−c2Et[H(πθ(⋅∣st))]

Für kontinuierliche Actions ist die Policy eine diagonale Gaußverteilung πθ(a∣s)=N(μθ(s),diag(σ2)); im Einsatz wird der Mittelwert μθ(s) verwendet.

Einstellungen von Strido (train.py): ϵ=0.2, γ=0.99, λ=0.95, Lernrate 3×10−4, 1024 Schritte pro Umgebung pro Rollout, Minibatch 2048, 5 Epochen pro Rollout, c2=0 (ent_coef=0.0: Exploration kommt nur aus der eigenen Streuung der Gaußverteilung, log_std_init=-1.0), standardmäßig insgesamt 2×107 Schritte. Observations und Rewards werden mit laufenden Statistiken normiert (VecNormalize, Observations bei ±10 begrenzt); Mittelwert und Varianz des Normierers werden mit den Gewichten exportiert, damit der Roboter dieselbe Skalierung anwendet.

Rechenbeispiel. Angenommen, eine Action hatte A^t=0.5 und nach einem Update ρt=1.35. Ungeclippt wäre der Term 0.675; geclippt ist er 1.2×0.5=0.6, und der Gradient durch diese Stichprobe ist null, also hört PPO auf, die Wahrscheinlichkeit dieser Action nach oben zu drücken.

Die Strido-Umgebung ​

Timing. Policy mit 50Hz (CONTROL_DT = 0.02), Physik mit 500Hz (10 Teilschritte). Episoden dauern höchstens 1000 Schritte (20s). Die Servos werden als MJCF-Positionsaktuatoren mit einer Drehmomentgrenze von 3.43Nm modelliert (Blockiermoment des SPT5435LV bei 6V).

Observation (23 Werte, OBSERVATION_SIZE):

ot=[ωb,gb,c,at−1,sin⁡φt,cos⁡φt]∈R3+3+3+12+2
  • ωb: Winkelgeschwindigkeit des Körpers vom IMU-Gyroskop;
  • gb=R⊤(0,0,−1)⊤: die Richtung der Schwerkraft als Einheitsvektor im Basis-Frame, aus der IMU-Quaternion (kodiert Rollen und Nicken, nicht Gieren);
  • c=(vx,vy,ωz): das Geschwindigkeitskommando, pro Episode gezogen aus vx∈[−0.15,0.30]m/s, vy∈[−0.10,0.10]m/s, ωz∈[−0.6,0.6]rad/s, und mit Wahrscheinlichkeit 0.2 null;
  • at−1: die vorherige Action;
  • ein Gait-Takt φt=2πt/T mit T=0.4s (GAIT_PERIOD_S), passend zum geskripteten Trot.

Jede Eingabe ist auf dem realen Roboter aus /imu/data und /cmd_vel verfügbar; es gibt keine Basisgeschwindigkeit und keine Gelenkrückmeldung (die Servos haben keine).

Action. at∈[−1,1]12 sind Abweichungen von der Standpose q0:

qttarget=clamp(slew(q0+0.3at))

ACTION_SCALE =0.3rad; slew_limit begrenzt die Gelenkgeschwindigkeit auf 6rad/s (die Grenze der Firmware), und clamp_targets wendet die Gelenk- und Kniekurbelgrenzen in derselben Reihenfolge wie die Firmware an, sodass die Policy nie lernt, sich auf Bewegungen zu verlassen, die der Roboter verweigern würde.

Reward. Mit der linearen Geschwindigkeit im Basis-Frame vb, der Winkelgeschwindigkeit ωb, den Aktuatorkräften τ und der Basishöhe z:

rt=1.0exp⁡(−‖vbxy−cxy‖20.01)+0.8exp⁡(−(ωb,z−cω)20.05)−2.0vb,z2−0.05‖ωbxy‖2−0.01‖at−at−1‖2−0.002‖τ‖2−2.0max(0,0.15−z)

Die beiden Exponentialterme belohnen das Verfolgen des Kommandos (höchstens 1.8 pro Schritt); die Strafterme verhindern Hüpfen, Wackeln, ruckartige Actions, hohes Drehmoment (Wärme, Akku) und Ducken unter 0.15m. Der Code multipliziert mit CONTROL_DT * 50, was bei 50Hz gleich 1 ist.

Abbruch. Die Episode endet mit einer Strafe von −2, wenn die Basis unter 0.09m sinkt oder sich der Körper so neigt, dass −gb,z<0.6 (etwa 53∘ Rollen oder Nicken).

Rechenbeispiel. Kommandiert vx=0.20m/s, erreicht 0.15m/s: Der Tracking-Term ist exp⁡(−0.052/0.01)=exp⁡(−0.25)≈0.78. Die Breite 0.01 bedeutet, dass Fehler um 0.1m/s bereits den Großteil des Rewards kosten (exp⁡(−1)≈0.37).

Domain Randomization und die Sim-to-Real-Lücke ​

Eine Policy, die Eigenheiten des Simulators ausnutzt, versagt auf der Hardware: die Sim-to-Real-Lücke. Ursachen sind unter anderem nicht modellierte Servodynamik und Spiel, Reibung, Fehler bei Masse und Trägheit, Sensorrauschen und Latenz. Domain Randomization trainiert auf einer Verteilung von Simulatoren, sodass der reale Roboter hoffentlich nur eine weitere Stichprobe ist:

maxθEξ∼p(ξ)[Jξ(θ)]

wobei ξ Physikparameter sind. StridoEnv._randomise zieht pro Episode:

ParameterBereich
Servosteifigkeit kp×U(0.85,1.15)
Basismasse×U(0.90,1.15)
Boden- und Fußreibung×U(0.6,1.2)
GyroskoprauschenN(0,0.052) pro Schritt
Rauschen des SchwerkraftvektorsN(0,0.022) pro Schritt
anfängliche Gelenkwinkelq0+N(0,0.022)

Da die Policy aus einer einzelnen Observation nicht erkennen kann, in welchem ξ sie sich befindet, lernt sie ein Verhalten, das über alle hinweg robust ist. Weitere Mittel gegen die Lücke (hier nicht alle verwendet): an gemessene Servoantworten angepasste Aktuatormodelle, Observation-Latenz, Stoßstörungen und Gelände-Curricula.

Prüfen Sie sich selbst ​

  1. Wie groß ist der effektive Horizont in Sekunden für γ=0.99 bei 50Hz, und wie, wenn die Policy mit demselben γ bei 100Hz liefe?

    Antwort

    Etwa 100 Schritte =2s; bei 100Hz halbiert er sich auf 1s, daher sollte γ auf etwa 0.995 steigen, um denselben Horizont zu behalten.

  2. Warum verzerrt das Abziehen von V(s) den Policy Gradient nicht?

    Antwort

    Ea∼π[∇θlog⁡πθ(a∣s)]=∇θ∑aπθ(a∣s)=∇θ1=0, daher hat jede nur vom Zustand abhängige Baseline einen erwarteten Beitrag von null.

  3. Bei ϵ=0.2 und A^t<0: Für welche ρt liefert der PPO-Term keinen Gradienten mehr?

    Antwort

    Für ρt<0.8: Die Wahrscheinlichkeit der Action wurde bereits genug verringert.

  4. Warum enthält die Observation die Schwerkraftrichtung statt Euler-Winkeln einschließlich Gieren?

    Antwort

    Gehen hängt nicht von der Blickrichtung ab, und das Gieren aus einer IMU ohne Magnetometer driftet; der Schwerkraftvektor ist driftfrei und stetig.

  5. Nennen Sie zwei Sim-to-Real-Effekte, die die Randomisierung von Strido nicht abdeckt.

    Antwort

    Zum Beispiel Sensor- und Aktuatorlatenz, Servospiel oder Totzone, äußere Stöße, unebenes Gelände.

Weiterführende Literatur ​

  • R. S. Sutton und A. G. Barto, Reinforcement Learning: An Introduction, 2. Aufl., MIT Press, 2018.
  • J. Schulman, F. Wolski, P. Dhariwal, A. Radford und O. Klimov, „Proximal Policy Optimization Algorithms“, arXiv:1707.06347, 2017.
  • J. Schulman, P. Moritz, S. Levine, M. Jordan und P. Abbeel, „High-Dimensional Continuous Control Using Generalized Advantage Estimation“, ICLR, 2016.
  • J. Tobin et al., „Domain Randomization for Transferring Deep Neural Networks from Simulation to the Real World“, IROS, 2017.
  • J. Hwangbo et al., „Learning agile and dynamic motor skills for legged robots“, Science Robotics, 2019.

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