Skip to the content
FixTheRobot Explore Robotics / UAV / Module 5 / M5-T5

UAV Systems Engineering · Module 5

M5-T5: Attitude control

Two ways to close the attitude loop: stack an angle loop on a rate loop, or define the error on the rotation group itself and control it directly.

  • Lesson 5 of 17
  • UAV Guidance, Navigation and Control (GNC)
  • Established engineering
  • About 5 minutes to read

Everything a multirotor does rests on its attitude controller. The cascade is the industrial standard; the geometric controller is the clean mathematical form that works for any attitude error. Both reduce to the same idea: a proportional term on the attitude error and damping on the rate.

Learning objectives

After this lesson, you should be able to:

  • Describe the cascaded angle-rate attitude controller and its tuning order.
  • Define the attitude error on SO(3) and write the geometric control law.
  • Explain the roles of inertia, torque limits and motor lag in attainable bandwidth.
  • Simulate large-angle recovery with the geometric controller.

Conceptual explanation

The cascaded controller (as in PX4 and ArduPilot) has an outer angle loop (PP controller turning attitude error into a desired body rate) and an inner rate loop (PID turning rate error into torque), lesson M5-T6. The geometric controller (Lee, Leok, McClamroch 2010) defines the error directly on the rotation group and computes the torque in one step, with almost-global stability on SO(3).

Attitude control structuresCascade: attitude setpoint to angle P controller to rate setpoint to rate PID to torque to mixer. Geometric: attitude setpoint and rates to attitude error on SO(3) and rate error to a PD law with gyroscopic feed-forward to torque to mixer.Attitude setpointR_d, ω_dError on SO(3)e_R, e_ωPD + feed-forwardtorqueMixermotorsa rate loop inside, an angle loop outside, or one geometric law
Attitude control structures.
Animation of attitude step responses for a single axis with a limit on the available torque. For a small 20 degree step the response follows the linear second-order prediction. For a 120 degree step the torque saturates for the first part of the manoeuvre, the angle rises at a constant acceleration, and the settling is slower and overshoots more than the small-step response scaled up. Strips show angle, rate and torque, with the saturation limit marked.
Cascade: angle error → rate setpoint → torque. Real motors give a bounded torque, so a large step runs into the limit: the rate is no longer what the linear loop expected and the response is slower, with overshoot if the loop is not rate-limited. Single axis J θ¨=τJ\,\ddot{\theta }=\tau , PD law with torque limit ±0.5 NN·mm; computed. (Looping, about 6 seconds; drawn and computed for this course with illustrative values.)

Engineering intuition

The attitude plant is a double integrator (torque to angular acceleration to rate to angle) with limits: the motors can deliver bounded torque, so there is a maximum angular acceleration amax⁡=τmax⁡/Ja_{\max}=\tau _{\max}/J. A proportional-derivative law sets a natural frequency ωn=Kp\omega _{n}=\sqrt{K_{p}} and damping; asking for ωn\omega _{n} beyond what the torque limit and motor lag allow saturates the motors and makes the loop slow and oscillatory (lesson M1-T6). For large errors a saturated, rate-limited angle loop (a square-root controller) turns the vehicle as fast as it can without overshoot.

Mathematical formulation

Geometric attitude control for desired attitude RdR_{d} and angular velocity Ωd\Omega _{d}, current RR and Ω\Omega (body frame):

Geometric attitude control law (Lee et al. 2010)
eR=12(Rd⊤R−R⊤Rd)∨\mathbf{e}_R = \tfrac{1}{2}\left(\mathbf{R}_d^{\top}\mathbf{R} - \mathbf{R}^{\top}\mathbf{R}_d\right)^{\vee}
Angular-velocity error
eΩ=Ω−R⊤Rd Ωd\mathbf{e}_\Omega = \boldsymbol{\Omega} - \mathbf{R}^{\top}\mathbf{R}_d\,\boldsymbol{\Omega}_d
Control moment
M=−kR eR−kΩ eΩ+Ω×JΩ−J([Ω]×R⊤RdΩd−R⊤RdΩ˙d)\mathbf{M} = -k_R\,\mathbf{e}_R - k_\Omega\,\mathbf{e}_\Omega + \boldsymbol{\Omega}\times\mathbf{J}\boldsymbol{\Omega} - \mathbf{J}\left([\boldsymbol{\Omega}]_{\times}\mathbf{R}^{\top}\mathbf{R}_d\boldsymbol{\Omega}_d - \mathbf{R}^{\top}\mathbf{R}_d\dot{\boldsymbol{\Omega}}_d\right)

For small errors eRe_{R} ≈ sin of the rotation angle times the axis, so the law is a PD controller with natural frequency kR/J\sqrt{k_{R}/J} and damping kΩ/(2kRJ)k_{\Omega }/(2\sqrt{k_{R} J}). The error function has an unstable equilibrium at a 180∘180^{\circ} error (the “antipodal” attitude), so convergence is almost global: a small perturbation leaves it. Cascade equivalent: angle loop Ωcmd=Kp e\Omega _{\text{cmd}}=K_{p}\,e (saturated at Ωmax⁡\Omega _{\max}) and rate loop τ=J(Kd(Ωcmd−Ω)+…)\tau =J(K_{d}(\Omega _{\text{cmd}}-\Omega )+\ldots ).

eRe_{R}, eΩe_{\Omega }
attitude and rate errors.
kRk_{R}, kΩk_{\Omega }
positive gains.
JJ
inertia matrix.
∨
vee map (skew matrix to vector).

Architecture and data flow

Position controller → desired thrust direction (and yaw) → RdR_{d} and thrust magnitude → attitude controller → torque → mixer (lesson M1-T6). PX4 implements the cascaded form (multicopter attitude and rate controllers, with parameters in the PID tuning guide); the geometric form appears in research controllers and in trajectory-tracking papers that fly aggressive manoeuvres.

Real-world UAV applications

  • Large-angle recovery after a disturbance or flip.
  • Aggressive trajectory tracking where small-angle linearisation fails.
  • Analysing attainable bandwidth from the torque limit.
  • Replacing Euler-angle controllers that have singularities.

Implementation example

This runs as shown: the geometric controller recovers from a 120∘120^{\circ} attitude error to level in about a second with bounded torque, and the closed-loop energy decreases monotonically.

import numpy as np
hat = lambda w: np.array([[0, -w[2], w[1]], [w[2], 0, -w[0]], [-w[1], w[0], 0]])
vee = lambda S: np.array([S[2, 1], S[0, 2], S[1, 0]])
def Exp(w):
    th = np.linalg.norm(w)
    if th < 1e-12: return np.eye(3) + hat(w)
    K = hat(w / th); return np.eye(3) + np.sin(th) * K + (1 - np.cos(th)) * K @ K

J = np.diag([0.029, 0.029, 0.055]); kR, kW = 30.0 * 0.029, 8.5 * 0.029       # gains scaled by inertia: natural frequency about sqrt(30) rad/s, damping near 0.78
tau_max = 0.5; dt = 0.002
R = Exp(np.array([1.2, -0.8, 0.9]) / np.linalg.norm([1.2, -0.8, 0.9]) * np.radians(120)); W = np.zeros(3); Rd = np.eye(3)
hist = []; torque_peak = 0.0
for k in range(int(4.0 / dt)):
    eR = 0.5 * vee(Rd.T @ R - R.T @ Rd); eW = W                           # desired rate is zero
    M = -kR * eR - kW * eW + np.cross(W, J @ W)
    M = np.clip(M, -tau_max, tau_max); torque_peak = max(torque_peak, np.abs(M).max())
    W = W + np.linalg.solve(J, M - np.cross(W, J @ W)) * dt; R = R @ Exp(W * dt)
    ang = np.degrees(np.arccos(np.clip((np.trace(Rd.T @ R) - 1) / 2, -1, 1))); hist.append(ang)
hist = np.array(hist); t_settle = np.argmax(hist[::-1] > 2.0)
print(f"initial error {hist[0]:.0f} deg, below 2 deg after {(len(hist) - t_settle) * dt:.2f} s, final {hist[-1]:.4f} deg, peak torque {torque_peak:.3f} N m")
assert hist[0] > 100 and hist[-1] < 0.1 and (len(hist) - t_settle) * dt < 3.0
assert np.allclose(R @ R.T, np.eye(3), atol=1e-9)                          # the rotation stays on SO(3) throughout
Geometric attitude controller recovering from a 120 degree error with torque limits.

Common engineering mistakes

Asking for bandwidth the motors cannot provide

The loop saturates and rings; check torque limit and lag.

Euler-angle errors near vertical

Singularity: use SO(3) errors.

Missing the gyroscopic feed-forward on large rates

Matters for fast rotations; small for modest ones.

No rate limit on the angle loop

Large errors produce huge rate commands: saturate the angle loop output.

Tuning the angle loop before the rate loop

Tune the inner (rate) loop first.

Failure modes

Failure modes, symptoms and causes
Failure modeHow it shows upLikely cause
Saturated oscillationLimit cycle after a large commandTorque limit hit with an aggressive gain
Yaw sluggishHeading follows slowlyLow yaw authority (drag-torque coefficient); yaw gains set lower
Flip near 180∘180^{\circ} errorUnstable equilibrium and chatterAntipodal attitude: unavoidable, ensure it is not commanded
Rate-loop noise amplificationMotors hot, buzzingDD term on noisy gyro (lesson M5-T6)

Debugging approach

  1. Step the attitude setpoint and log angle, rate and torque; check the torque saturation flags.
  2. Estimate amax⁡=τmax⁡/Ja_{\max}=\tau _{\max}/J and compare with the requested acceleration.
  3. Test large errors (90∘, 150∘)(90^{\circ},\,150^{\circ}) in simulation.
  4. Compare cascade and geometric on the same manoeuvre.

Practical exercises

  1. Derive the small-angle PD form and the natural frequency in terms of kRk_{R} and JJ.
  2. Find the largest initial error from which the example controller still converges and explain the 180∘180^{\circ} case.
  3. Add a first-order motor lag to the example and re-tune.
  4. Compute amax⁡a_{\max} for τmax⁡=0.5 N⋅m\tau _{\max}=0.5\,N\cdot m and Jx=0.029 kg⋅m2J_{x}=0.029\,\mathrm{kg}\cdot m^{2}.

Interview questions

Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.

Question 1

What is the geometric attitude controller?

Model answer

A control law whose error is defined on SO(3) (eeR from the skew part of Rd⊤R−R⊤RR_{d^{\top}R}-R^{\top}R_d) with PD feedback and gyroscopic compensation, giving almost-global stability without Euler-angle singularities.

Question 2

What limits attitude bandwidth?

Model answer

Available torque over inertia (maximum angular acceleration), motor and ESC lag, sensor noise and delay.

Question 3

Why tune the rate loop first?

Model answer

The angle loop treats the rate loop as its actuator, so the inner loop must be fast and well damped before the outer is closed.

References and further reading

Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.

What’s next

Mark this lesson

Saved in this browser and synced to your account when you are signed in.

Practice this lesson

M5-L1: Implement PID attitude control

Tune a PID attitude loop on the quadrotor.

Next lesson

M5-T6: PID controllers

Tune cascaded PID loops from the inside out and prevent integrator windup and derivative noise problems.