ADCS Deep Dive — Laser-Comm Pointing Case Study

An end-to-end Attitude Determination & Control System design study for a large laser-comm platform that must hold a beam to ±0.01° with ≤5 arcsec jitter while slewing 30° in 30 s, from LEO to MEO. This walks the whole chain — requirements → disturbances → actuator sizing → sensors → estimator → control laws → allocation → budgets → FDIR — and then red-teams it.

Symbols used on this page are defined in the Nomenclature → attitude & rotations.

Design-study values (representative engineering assumptions), from ADCS/ADCS_Laser_Pointing.md and its critique companion.

The three-sentence summary. The pointing requirement forces arcsecond knowledge, which forces star-trackers + a FOG gyro fused in a MEKF; the agility requirement forces 12.8 N·m, which forces CMGs (and therefore singularity steering and momentum dumping); and the jitter requirement cannot be met by the bus at all, which forces a fine-steering-mirror inner loop. Everything else follows.

1 · Baseline & requirements

A 3000 kg (wet) / 1500 kg (dry) box bus with 12 m solar arrays; worst-case sizing inertia $I_{max}\approx5500$ kg·m². The requirements drive everything downstream:

#RequirementValue
R1Pointing accuracy (laser)±0.01° (36 arcsec), 3σ
R2Jitter (stability)≤ 5 arcsec / 1 s
R3Pointing knowledge±0.005° (18 arcsec)
R4/R5Slew rate / agility≥ 2°/s; 30° + settle in ≤ 30 s
R6Settling time≤ 10 s
R7OrbitLEO (400 km) → MEO (10,000 km)
Knowledge must beat control: R3 (18″) is tighter than R1 (36″) — you can never control better than you can measure, so the estimator budget is allocated first.

2 · Disturbance-torque budget

Worst case is LEO; each environmental torque is worked from first principles:

  • Gravity gradient: $T_{gg}=\tfrac{3\mu}{2R^3}\lvert I_{zz}-I_{xx}\rvert\sin2\theta \approx 3.8\times10^{-3}$ N·m
  • Aerodynamic drag: $T_{aero}=\tfrac12\rho V^2 C_d A(c_{pa}-c_g)\approx 1.9\times10^{-3}$ N·m
  • Solar radiation pressure: $T_{srp}=\tfrac{\Phi}{c}A_s(1+q)(c_{ps}-c_g)\approx 5.8\times10^{-5}$ N·m
  • Magnetic: $T_{mag}=D\times B\approx 3\times10^{-5}$ N·m
RegimeRSS disturbanceDominant termMomentum per orbit
LEO (400 km)≈4.3×10⁻³ N·mgravity gradient, then drag≈3–4 N·m·s
MEO (10,000 km)≈6×10⁻⁵ N·mSRP (secular, sun-fixed)≈0.3 N·m·s

The regime problem: drag and gravity gradient fall away with altitude while SRP does not. In LEO the magnetic field is strong enough to dump momentum for free; in MEO it is not, so desaturation must switch to thrusters — which is why the design carries both and arbitrates between them (§9).

3 · Actuator sizing — why CMGs

A bang-bang (accelerate-then-decelerate) 30° slew in 30 s sets the torque and momentum:

$$ \alpha=\frac{4\theta}{t^2}=2.3\times10^{-3}\ \text{rad/s}^2,\qquad T_{slew}=I_{max}\,\alpha\approx 12.8\ \text{N·m},\qquad H=I_{max}\,\omega\approx 190\ \text{N·m·s}. $$

Reaction wheels cannot produce 12.8 N·m at sane mass/power, so the primary actuator is a 4-SGCMG pyramid (skew $\beta=54.7°$, rotor momentum $h=75$ N·m·s each, $\dot\delta_{max}=1$ rad/s). A single-gimbal CMG delivers $\mathbf T=\mathbf h\times\dot{\boldsymbol\delta}$ — torque amplification: a small gimbal rate on a large stored momentum yields large torque. Peak per CMG is $h\dot\delta=75$ N·m (≈6× margin), and cluster momentum $\approx4h\approx300$ N·m·s covers the 190 needed.

ActuatorQtySizingRole
SGCMG4 (pyramid, β=54.7°)h=75 N·m·s, δ̇=1 rad/sprimary: slew + fine point
Reaction wheel4~0.2 N·m, 50 N·m·sfine / backup / quiet hold
Magnetorquer3 (orthogonal triad)~500 A·m²LEO dumping, detumble
Thruster12 (couples)~1 N, moment arm ~1.5 mMEO dumping, Δv, safe mode

3.1 Placement & minimum counts

  • General rule: three axes need ≥3 independent actuators; one-fault tolerance needs ≥4. Hence 4 CMGs, 4 wheels, and thrusters in opposing pairs so each pair is a pure couple (no Δv coupling).
  • CMG quad pyramid: four gimbal axes on a pyramid at skew 54.7° — chosen because it makes the momentum envelope nearly spherical (equal authority in all directions) and leaves a 1-D null space for singularity avoidance.
  • Wheels — three common configurations:
    • 3 orthogonal + 1 skew spare — simplest bookkeeping; the spare is only partially effective until you re-map, and its axis must not be coplanar with any two others.
    • 4 in a pyramid (all tilted from one axis) — graceful degradation, biased toward one axis.
    • 4 in a tetrahedron — maximally isotropic: any three still span 3-space, so a single failure costs momentum envelope but never controllability. Chosen here.
  • Magnetorquers: orthogonal triad on the bus, mounted away from the magnetometer, and duty-cycled: torquers off → sample the field → then actuate (measure-then-actuate), or the torquer corrupts its own sensor.

4 · CMG singularities & steering laws

Stack the four per-CMG torque directions into the Jacobian $A(\boldsymbol\delta)\in\mathbb R^{3\times4}$, so cluster torque is $\mathbf T = A\,\dot{\boldsymbol\delta}$ and total momentum is $\mathbf h(\boldsymbol\delta)=\sum_i h\,\hat{\mathbf h}_i(\delta_i)$ with $A=\partial\mathbf h/\partial\boldsymbol\delta$. A singularity is any gimbal set where the four torque axes become coplanar,

$$ \operatorname{rank}A<3,\qquad m=\sqrt{\det\!\big(AA^\top\big)}\to 0 $$

and the cluster loses torque authority along the direction normal to that plane. The dangerous ones are internal (elliptic) singularities, which null motion alone cannot always escape. Four steering laws:

LawFormulaBehaviour
(a) Pseudo-inverse$\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}=A^\top(AA^\top)^{-1}\mathbf T_{cmd}$exact torque, but blows up as $m\to0$
(b) Singularity-robust$\dot{\boldsymbol\delta}=A^\top(AA^\top+\lambda I)^{-1}\mathbf T_{cmd}$bounded rates; injects torque error exactly when slewing hard
(c) Generalized SR$(AA^\top+\lambda E)^{-1}$, $E$ with dithered off-diagonalsdeterministic perturbation escapes internal singularities
(d) Null-motion (baseline)$\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}+(I_4-A^{+}A)\mathbf d$reconfigures gimbals at zero torque — no pointing error

The SR damping is scheduled on the singularity measure, and the null motion climbs its gradient:

$$ \lambda=\lambda_0\,e^{-\mu m^2}\ (\lambda_0=0.01,\ \mu=10),\qquad \mathbf d = k_n\,\nabla_{\boldsymbol\delta}\,m $$

Because $A$ is $3\times4$, the null space is 1-D: there is always a gimbal motion that changes configuration without producing torque. the reference design therefore uses null-motion as the primary (it is free — no torque error, so pointing is untouched), GSR dithering only as a brief escape if trapped internally, and parks the gimbals near the isotropic (high-$m$) point during idle/comm periods so a slew never starts near a singularity.

The singularity story is much clearer interactively. Below are four gimbals on the 54.7° pyramid: each blue vector is one rotor's momentum, the white vector is the cluster total, and the bar is $m=\sqrt{\det(AA^\top)}$. Drive the gimbals until the torque axes go coplanar and watch the measure — and the cluster's authority on one axis — collapse. Then switch on the null-motion sweep: the gimbals move but the torque does not, which is how you escape a singularity for free:

5 · Attitude determination

SensorQtyAccuracy (1σ)Role
Star tracker2 (cross-boresight)1–3″ cross, ~10″ rollprimary fine attitude
FOG IMU1 (3-axis)bias 0.01°/hr, ARW 0.002°/√hrrate + propagation
Sun sensors6 (4π)±1°safe mode / acquisition
Magnetometer2±0.5° (LEO)magnetorquer control
GPS2~10 morbit / time knowledge

A single star tracker is excellent about its two cross-boresight axes and poor about roll (its own boresight) — roughly 5× worse. Two trackers at ~90° fix that: each one's good axes cover the other's weak axis, giving few-arcsecond 3-axis knowledge, and the pair keeps lock through Sun/Earth exclusion cones.

Sensor σ → knowledge: the useful conversion is that a vector sensor of accuracy $\sigma_v$ constrains the two axes perpendicular to the measured vector and says nothing about rotation about it. Averaging $N$ independent frames helps as $\sigma/\sqrt N$ only for the white (NEA) part — the low-frequency thermo-elastic bias does not average down, which is why alignment ends up dominating the budget (§7).

6 · Estimator — the MEKF

Attitude lives on a manifold, so the filter is multiplicative: it estimates a small attitude error and the gyro bias, then folds the correction back into the quaternion (full theory on the Attitude page).

$$ \hat{\mathbf x}=\begin{bmatrix}\delta\boldsymbol\theta\\ \Delta\mathbf b\end{bmatrix}\in\mathbb R^{6},\qquad \mathbf q = \delta\mathbf q(\delta\boldsymbol\theta)\otimes\hat{\mathbf q} $$

The gyro model carries bias, ARW and rate noise; the trackers bound the drift:

$$ \tilde{\boldsymbol\omega}=\boldsymbol\omega+\mathbf b+\boldsymbol\eta_v,\qquad \dot{\mathbf b}=\boldsymbol\eta_u $$

Each vector measurement (star direction, Sun vector, magnetic field) has the same sensitivity structure — a measured unit vector is only sensitive to rotations perpendicular to itself:

$$ \mathbf z = \hat{\mathbf b}_{meas}-\hat{\mathbf b}_{pred},\qquad H=\big[\;[\hat{\mathbf b}_{pred}\times]\quad \mathbf 0_{3\times3}\;\big] $$

so multiple sensors stack into one taller update, and the reset step applies $\delta\boldsymbol\theta$ to the reference quaternion and zeroes it — keeping the linearization valid and the $3\times3$ attitude covariance meaningful.

Multi-sensor fusion (stacked update). Concatenating the available vector measurements gives one update whose weighting falls out of the noise covariance automatically:

$$ \mathbf z=\begin{bmatrix}\mathbf z_{st}\\ \mathbf z_{sun}\\ \mathbf z_{mag}\end{bmatrix},\quad H=\begin{bmatrix}H_{st}\\ H_{sun}\\ H_{mag}\end{bmatrix},\quad R=\operatorname{diag}\big(R_{st},R_{sun},R_{mag}\big) $$

Because $R_{st}\!\sim\!(2^{\prime\prime})^2$ while $R_{sun}\!\sim\!(1°)^2$, the star trackers dominate the gain by ~6 orders of magnitude — the Sun sensor and magnetometer contribute essentially nothing while the trackers are healthy, and take over gracefully when they are not. Since $R$ is block-diagonal the update can be processed one scalar at a time in any order (§3 of the NASA practices), avoiding a matrix inverse.

Bias: estimated or "considered"? Estimating gyro bias needs observability (attitude updates while the geometry changes). When a tracker is blinded, bias becomes weakly observable and estimating it can make the filter optimistic; carrying it as a consider parameter instead keeps the covariance honest. This is precisely the trade in the NASA best-practices page.

Converged performance: ~3–6″ attitude knowledge, bias observable to ~0.001°/hr — meeting R3 with margin.

7 · Control laws — Lyapunov, PID and LQR

Everything here is built on the attitude-error kinematics and Euler's rigid-body dynamics. With $\mathbf q_e=\mathbf q_{cmd}^{-1}\otimes\mathbf q$ (error quaternion, vector part $\mathbf q_{ev}$, scalar $q_{e0}$) and $\boldsymbol\omega_e=\boldsymbol\omega-\boldsymbol\omega_{cmd}$:

$$ \dot{\mathbf q}_{ev}=\tfrac12\big(q_{e0}\boldsymbol\omega_e+\mathbf q_{ev}\times\boldsymbol\omega_e\big), \qquad \dot q_{e0}=-\tfrac12\mathbf q_{ev}^\top\boldsymbol\omega_e $$ $$ J\dot{\boldsymbol\omega}=-\,\boldsymbol\omega\times J\boldsymbol\omega+\mathbf T_{ctrl}+\mathbf T_{dist} $$

7.1 Quaternion Lyapunov controller (nonlinear, globally stabilizing)

The nonlinearity that breaks naive linear tuning is the gyroscopic term $\boldsymbol\omega\times J\boldsymbol\omega$, which grows with the square of rate — exactly when you slew fast. The Lyapunov design handles it by construction. Take the candidate function (kinetic energy + an attitude "spring" potential):

$$ V=\underbrace{\tfrac12\boldsymbol\omega_e^\top J\boldsymbol\omega_e}_{\text{rotational KE}\;\ge0} +\underbrace{k_p\big[\mathbf q_{ev}^\top\mathbf q_{ev}+(1-q_{e0})^2\big]}_{\text{attitude potential}\;\ge0}, \qquad k_p>0 $$

$V$ is positive-definite and vanishes only at $\boldsymbol\omega_e=0$, $\mathbf q_e=[\mathbf 0,1]$ — the target. Differentiating along the dynamics, using the identity $\tfrac{d}{dt}\!\left[\mathbf q_{ev}^\top\mathbf q_{ev}+(1-q_{e0})^2\right]=\mathbf q_{ev}^\top\boldsymbol\omega_e$, the cross terms cancel if we choose

$$ \boxed{\;\mathbf T_{ctrl}= \underbrace{\boldsymbol\omega\times J\boldsymbol\omega}_{\text{gyroscopic feed-forward}} \;-\;\underbrace{k_p\,\operatorname{sgn}(q_{e0})\,\mathbf q_{ev}}_{\text{attitude spring}} \;-\;\underbrace{k_d\,\boldsymbol\omega_e}_{\text{rate damping}}\;} $$

which leaves a manifestly non-positive derivative:

$$ \dot V=-k_d\,\boldsymbol\omega_e^\top\boldsymbol\omega_e\;\le\;0 $$

$\dot V=0$ only on the set $\boldsymbol\omega_e=0$; on that set the dynamics force $\mathbf q_{ev}\to0$, so by Barbashin–Krasovskii/LaSalle the equilibrium is asymptotically stable for arbitrarily large initial errors — a genuinely global result, unlike a gain-margin argument from a linearization.

Why each term earns its place:

  • $\boldsymbol\omega\times J\boldsymbol\omega$ feed-forward — cancels the nonlinear coupling exactly, so the closed loop behaves linearly even during a 2°/s slew. Without it, cross-axis coupling appears as a disturbance that a fixed PD gain must absorb with margin (i.e. slower loops).
  • $\operatorname{sgn}(q_{e0})$ — the crucial detail. $\mathbf q$ and $-\mathbf q$ are the same attitude (double cover of $SO(3)$), so a controller that ignores the sign can rotate the long way around: the unwinding phenomenon. The sign flip picks whichever representative has $q_{e0}\ge0$, guaranteeing the shortest-path eigenaxis rotation (≤180°). Cost: a discontinuity at $q_{e0}=0$, so flight code adds hysteresis there.
  • $k_d\boldsymbol\omega_e$ — the only dissipation in the system; it is what makes $\dot V<0$.

Gain selection maps directly onto a second-order response per axis:

$$ k_p=2J\omega_n^2,\qquad k_d=2\zeta J\omega_n $$

For $J=5500$ kg·m², $\omega_n=2\pi(1\,\text{Hz})\!\approx\!6.3$ rad/s is far too stiff for a flexible bus — the practical choice is $\omega_n\!\sim\!0.1$–$0.3$ rad/s with $\zeta\approx0.7$, keeping the loop below the 0.5–1 Hz array modes (§8). Drive the slew below the CMG torque limit and $k_p$ is capped by $T_{max}$, not by stability.

7.2 PID for the fine-pointing hold

Inside the linear region ($\lvert\boldsymbol\theta_e\rvert<1°$), $\mathbf q_{ev}\approx\tfrac12\boldsymbol\theta_e$ and a PID law is simpler and — critically — can carry an integrator:

$$ \mathbf T_{ctrl}=-K_p\boldsymbol\theta_e-K_d\boldsymbol\omega_e-K_i\!\int\!\boldsymbol\theta_e\,dt+\mathbf T_{ff} $$

The integral term is what drives steady-state error to zero against the secular SRP / CG-offset torque — a pure Lyapunov or LQR law leaves a bias offset proportional to disturbance/gain. Requirements: anti-windup whenever the CMGs saturate, and the eigenaxis slew profile fed forward in $\mathbf T_{ff}$.

the reference design therefore gain-schedules: Lyapunov (with gyroscopic feed-forward) for the retarget slew, blending smoothly into PID for the comm hold once inside 1°.

7.3 LQR — optimal gains instead of tuned gains

Lyapunov gives stability but not optimality: any $k_p,k_d>0$ is stable, so how do you pick among them? LQR answers that by minimising a cost. Linearize about the hold ($\boldsymbol\omega$ small, so $\boldsymbol\omega\times J\boldsymbol\omega$ is second-order and drops out) and use $\mathbf x=[\boldsymbol\theta_e^\top,\ \boldsymbol\omega_e^\top]^\top$:

$$ \dot{\mathbf x}=A\mathbf x+B\mathbf u,\qquad A=\begin{bmatrix}\mathbf 0&I_3\\ \mathbf 0&\mathbf 0\end{bmatrix},\qquad B=\begin{bmatrix}\mathbf 0\\ J^{-1}\end{bmatrix},\qquad \mathbf u=\mathbf T_{ctrl} $$

which is just three decoupled double integrators. Minimise the quadratic cost

$$ \mathcal J=\int_0^\infty\!\big(\mathbf x^\top Q\,\mathbf x+\mathbf u^\top R\,\mathbf u\big)\,dt, \qquad Q=Q^\top\succeq0,\ R=R^\top\succ0 $$

The optimal control is linear feedback whose gain comes from the algebraic Riccati equation:

$$ A^\top P+PA-PBR^{-1}B^\top P+Q=0,\qquad \boxed{\;\mathbf u=-K\mathbf x,\quad K=R^{-1}B^\top P\;} $$

For one axis with $J=1$, $Q=\operatorname{diag}(q,0)$, $R=r$, the Riccati solution is closed-form and shows exactly how the weights become a bandwidth and a damping ratio:

$$ K=\Big[\sqrt{q/r}\;,\;\sqrt{2\sqrt{q/r}}\Big] \;\Rightarrow\; \omega_n=(q/r)^{1/4},\qquad \zeta=\tfrac{1}{\sqrt2}\approx0.707 $$

That $\zeta=0.707$ falling out for free is the classic LQR result — the optimal double-integrator regulator is exactly critically-damped-ish, which is why hand-tuned PD designs converge on the same answer. Design intent enters through the weights: $Q$ buys pointing accuracy, $R$ buys actuator economy. Weight $\boldsymbol\theta$ heavily for tight pointing, weight $\boldsymbol\omega$ to suppress overshoot, and weight $\mathbf u$ to respect the CMG torque/rate envelope and to avoid exciting flexible modes.

LawGuaranteeHandles big angles?Zero steady-state?Where used
Lyapunovglobal asymptotic stabilityyes (+ shortest path)no (unless augmented)retarget slew
PIDlocal, margin-basednoyes (integrator)comm hold
LQRoptimal for the cost; guaranteed marginsno (linearized)no (add LQI/integral)gain selection, MIMO coupling
B-dotenergy dissipationn/an/adetumble (no attitude needed)
They are not rivals. The honest architecture is: LQR/LQI to choose the gains (it handles the $3\times3$ inertia cross-coupling that per-axis tuning ignores), the Lyapunov structure to stay valid at large angles (gyroscopic feed-forward + $\operatorname{sgn}(q_{e0})$), and an integrator for the secular disturbance. Add LQR's robust cousins (LQG/H∞, or $Q$-weighted notch shaping) when the plant is uncertain — a +30% mass growth or a slosh-shifted inertia is a plant perturbation.

8 · Two-level control: torque command → actuator allocation

With CMGs, magnetorquers and thrusters all present, writing one monolithic controller per actuator is a combinatorial mess and couples the pointing design to the hardware manifest. The standard answer is a two-level (cascaded) architecture — and it is exactly the structure you proposed:

Level 1
LQR / Lyapunov
attitude law
→
$\mathbf T_{cmd}\in\mathbb R^3$
virtual torque
→
Level 2
control allocation
$B\mathbf u=\mathbf T_{cmd}$
→
$\dot{\boldsymbol\delta}$ · $\mathbf m$ · thruster
on-times

Level 1 is a 3-DOF problem in physics units: it produces the torque the body needs and knows nothing about hardware. Level 2 is a constrained algebra problem: find actuator commands that produce that torque while respecting limits and preferences. The interface is a plain 3-vector, so you can change the actuator suite without retuning the pointing loop — and you can prove stability of Level 1 assuming only that Level 2 achieves $B\mathbf u\approx\mathbf T_{cmd}$.

8.1 The allocation problem

Let $\mathbf u$ collect every actuator's command and $B$ (the effectiveness matrix) map commands to body torque. With $n$ actuators and 3 axes, $n>3$ makes the system over-actuated — infinitely many solutions, so we pick the best one:

$$ \min_{\mathbf u}\ \tfrac12\lVert W_u\mathbf u\rVert_2^2 \quad\text{s.t.}\quad B\mathbf u=\mathbf T_{cmd},\quad \mathbf u_{min}\le\mathbf u\le\mathbf u_{max} $$

Ignoring the inequality, the weighted least-norm solution is the classic weighted pseudo-inverse:

$$ \mathbf u^\star = W^{-1}B^\top\big(BW^{-1}B^\top\big)^{-1}\mathbf T_{cmd}, \qquad W=W_u^\top W_u $$

and the general solution adds any null-space term, which is free torque-wise:

$$ \mathbf u=\underbrace{B^{+}\mathbf T_{cmd}}_{\text{achieves the torque}} +\underbrace{(I-B^{+}B)\,\mathbf z}_{\text{null motion: zero torque}} $$

That null term is the whole game in over-actuated systems: it is how you de-saturate a CMG, keep gimbals away from singularities, equalize wheel speeds, or shift effort off a failed unit without disturbing the attitude — the same $(I-A^{+}A)\mathbf d$ trick from §4, generalized to the full actuator set.

When saturation matters, the equality-constrained pseudo-inverse is wrong (it can command impossible values). Real options, in increasing fidelity:

MethodSolvesNotes
Pseudo-inverse + clip—cheapest; clipping changes direction of the delivered torque
Redistributed pseudo-inverseiterate: saturate, freeze, re-solve on the resta few passes, deterministic, flight-friendly
Weighted QP / active-set$\min\lVert W_u\mathbf u\rVert^2$ s.t. box + equalitythe "right" answer; needs a bounded-time QP solver
Linear program (l₁)max attainable torque / min fuelnatural when the objective is propellant, gives vertex (on/off) solutions
Cascaded / prioritizedfill from cheapest actuator, spill to nextmatches the physical hierarchy; what the reference platform actually does

If the demand simply cannot be met, the QP is relaxed to trade direction fidelity against magnitude:

$$ \min_{\mathbf u}\ \lVert B\mathbf u-\mathbf T_{cmd}\rVert_2^2+\gamma\lVert W_u\mathbf u\rVert_2^2 $$

Pointing cares far more about torque direction than magnitude — a scaled-down but correctly-aimed torque just slews slower, whereas a mis-aimed one excites the wrong axis.

8.2 What makes each actuator's row of $B$ special

The three actuator families are not interchangeable columns — each has its own structure:

  • CMGs — nonlinear, state-dependent, rate-limited. The map is $\mathbf T=A(\boldsymbol\delta)\dot{\boldsymbol\delta}$, so "$B$" changes with gimbal angle and can lose rank (§4). Allocation here is the steering law: $\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}+(I-A^{+}A)\mathbf d$, subject to $\lvert\dot\delta_i\rvert\le\dot\delta_{max}$ and the momentum envelope $\lVert\mathbf h\rVert\le 4h$. CMGs get the lowest cost in $W_u$: they are fast, precise and free.
  • Magnetorquers — fundamentally underactuated. Torque is $\mathbf T=\mathbf m\times\mathbf B$, so $B_{mtq}=-[\mathbf B\times]$, a matrix of rank 2: the component along $\mathbf B$ is unreachable at that instant, no matter the dipole. The achievable set is the plane $\perp\mathbf B$, so allocation must project: $$ \mathbf m_{cmd}=\frac{\mathbf B\times\mathbf T_{cmd}}{\lVert\mathbf B\rVert^2} \;\Rightarrow\; \mathbf T_{mtq}=-\frac{[\mathbf B\times]^2}{\lVert\mathbf B\rVert^2}\mathbf T_{cmd} = \mathbf T_{cmd,\perp\mathbf B} $$ Over an orbit $\mathbf B$ sweeps a large solid angle, so all three axes eventually get authority — the averaged system is controllable even though the instantaneous one is not. Also $\lVert\mathbf m\rVert\le m_{max}$ and torque $\propto\lVert\mathbf B\rVert$, hence useless in MEO.
  • Thrusters — on/off, non-negative, quantized in time. Each thruster gives a fixed force along a fixed line: $\mathbf T=\sum_i F_i(\mathbf r_i\times\hat{\mathbf f}_i)u_i$ with $u_i\in\{0,1\}$ (or a duty cycle in $[0,1]$). The constraint $u_i\ge0$ is what makes thruster allocation genuinely different — you need opposing pairs to make a pure couple, and the natural solver is an LP minimising total impulse (fuel) rather than a 2-norm. Continuous demand is realized by PWM/PWPF modulation, whose minimum impulse bit sets a torque quantization — and whose pulsing is a jitter source, so thrusters are forbidden during comm windows.

8.3 Arbitration — who is allowed to act, and when

Weights alone are not enough: a supervisor decides which actuators are even eligible, based on task, device state and orbit regime. Two distinct switches exist, and conflating them is a classic design error:

SwitchBetweenDecided by
Attitude-control actuatorCMG ↔ reaction wheeltask (agility/pointing vs. quiet hold or backup) — not by $\boldsymbol\omega$
Desaturation actuatormagnetorquer ↔ thrusterstored momentum threshold + regime + health + comm window

Momentum dumping triggers on stored momentum, never on spacecraft angular velocity:

DESAT ARBITRATION (mode manager, low rate)
─────────────────────────────────────────────────────────
IF   |h_store| < H_low                      : IDLE  (CMG null-motion only)
ELIF in_comm_window AND |h_store| < H_hard  : DEFER (protect jitter)
ELIF |h_store| ≥ H_dump_threshold:
       IF regime=LEO AND |B|>B_min AND mag_ok AND ≥2 MTQ axes
                                            : MAGNETORQUER dump (free)
       ELIF thrusters_ok                    : THRUSTER couple dump
       ELSE                                 : SAFE (flag: cannot dump)
ThresholdMeaningRepresentative value (300 N·m·s envelope)
$H_{low}$clean target after a dump~5% (~15 N·m·s)
$H_{dump}$start a dump~40–50% (~120–150 N·m·s)
$H_{hard}$dump even during comm~80% (~240 N·m·s)
$\omega_{acq}$detumble → pointing handover~0.5 °/s

The one place rate rules is detumble: B-dot ($\mathbf m=-k\dot{\mathbf B}$) runs while $\lVert\boldsymbol\omega\rVert>\omega_{acq}$ and needs no attitude knowledge at all. Every switch is bumpless: ramp the incoming actuator over a few seconds, feed the predicted reaction forward into the active attitude loop, and put hysteresis on the triggering variable ($\lVert\mathbf B\rVert$, $\lvert h\rvert$, $\lVert\boldsymbol\omega\rVert$) so it cannot chatter.

8.4 Momentum dumping in detail

The bookkeeping that makes dumping make sense: total system momentum is $\mathbf h_{sys}=J\boldsymbol\omega+\mathbf h_w$. Internal actuators can only trade momentum between body and wheels — to actually remove it you need an external torque (magnetic or thruster). During a dump the attitude loop holds the body still while the wheels are deliberately spun down (slowed, not powered off — a powered-off wheel keeps its momentum), and the external torque absorbs the reaction.

The magnetorquer B-cross dump law drives the wheel-momentum error $\Delta\mathbf h_w$ to zero:

$$ \mathbf m_{cmd}=\frac{k}{\lVert\mathbf B\rVert^2}\big(\mathbf B\times\Delta\mathbf h_w\big) \;\Longrightarrow\; \mathbf T_{mtq}=-k\Big(\Delta\mathbf h_w-(\Delta\mathbf h_w\!\cdot\hat{\mathbf B})\hat{\mathbf B}\Big) =-k\,\Delta\mathbf h_{w,\perp} $$

i.e. gradient descent on $\lVert\Delta\mathbf h_w\rVert$ restricted to the plane $\perp\mathbf B$. The along-field component waits for the field to rotate — which motivates align-and-dump: rather than dumping continuously and inefficiently, briefly orient (or simply wait for) a favourable field geometry so the momentum to be removed lies perpendicular to $\mathbf B$, then dump hard. For thrusters there are two options: fire body-fixed opposing pairs per axis (simple, no reorientation, some cosine loss), or slew so the stored momentum aligns with the most efficient thruster couple (fuel-optimal, costs a maneuver). the reference platform uses a hybrid, always scheduled outside comm windows. Life-cycle desat propellant works out to a few kg — small, but it is the reason MEO operations are propellant-limited rather than power-limited.

9 · Loop shaping, flexible modes & notch filters

Single-axis rigid plant at worst inertia is a double integrator — 180° of phase lag, so rate feedback is mandatory:

$$ G_{rb}(s)=\frac{1}{Is^2},\qquad I=5500\ \text{kg·m}^2 $$

The real spacecraft is not rigid: the 12 m arrays add lightly-damped modes at 0.5–1 Hz with damping $\zeta\sim0.002$–$0.01$, appearing as resonant pole/zero pairs inside or near the intended crossover:

$$ G(s)=\frac{1}{Is^2}+\sum_{k}\frac{\phi_k^2}{s^2+2\zeta_k\omega_k s+\omega_k^2} $$

Two mitigation strategies, and they trade against each other:

StrategyHowCost
Gain stabilization (notch)put a notch at $\omega_k$ so the mode is below 0 dBphase lag near crossover; fails if $\omega_k$ shifts (fuel burn, thermal, deployment)
Phase stabilization (roll-off)set crossover well below $\omega_1$ (~1/5–1/10)slow loop: worse disturbance rejection and settling
$$ N(s)=\frac{s^2+2\zeta_n\omega_n s+\omega_n^2}{s^2+2\zeta_d\omega_n s+\omega_n^2},\qquad \zeta_d\gg\zeta_n $$

the reference design does both: crossover ~0.1–0.2 Hz (comfortably under the first array mode) plus notches with deliberately wide skirts to tolerate ±20% frequency uncertainty, since a notch tuned to a mode that has moved is worse than no notch. Targets: gain margin ≥ 6 dB, phase margin ≥ 30–40°, and every flexible mode ≥ 8–10 dB attenuated. Digital effects eat margin too — sampling at $f_s$ plus computation delay adds $\angle=-\omega(T_d+T_s/2)$, so the 10 Hz estimator/50 Hz control rates are part of the stability argument, not an implementation detail.

Here is that trade as a loop-gain plot. The lightly-damped array mode appears as a resonant peak; if it crosses 0 dB you get a limit cycle. Either lower the crossover until the mode is buried (phase stabilization, slow) or notch it (gain stabilization, fast) — then mistune the notch and watch the margin evaporate, which is why real notches are built with wide skirts:

10 · Pointing & jitter budget

Definitions matter here — the three requirements measure different things:

  • Pointing error — actual vs. desired boresight. What the link actually cares about (R1, 36″).
  • Knowledge error — estimated vs. actual attitude. What the estimator delivers (R3, 18″); it bounds how well you can ever point.
  • Stability / jitter — motion during the optical integration time, i.e. high-frequency content only (R2, 5″ over 1 s). A slow thermal bias is not jitter; a 10 Hz wobble is.

Errors are separated by kind, RSS'd within a kind, then RSS'd across kinds:

$$ \text{Total}=\sqrt{\text{knowledge}^2+\text{control}^2+\text{alignment}^2+\text{jitter}^2} $$
Budget (3σ)TermsRSSvs. requirement
Knowledgetracker NEA 3.0″, tracker bias 2.0″, gyro prop 1.5″, MEKF residual 1.0″, time-tag 1.5″, tracker→body align 4.0″≈5.9″R3 = 18″ ✓
Controlloop steady-state 5.0″, CMG quantization/steering 5.0″, gimbal ripple 3.0″, residual disturbance 4.0″≈8.7″—
Alignmentbus→payload 10.0″, thermal distortion 12.0″, launch shift/creep 5.0″≈16.4″largest contributor
Jitter (1 s)rotor imbalance 4.0″, array modes 5.0″, thruster pulsing 2.0″, microvibration 2.0″≈7.0″R2 = 5″ ✗
$$ \text{Total}=\sqrt{5.9^2+8.7^2+16.4^2+7.0^2}\approx 20.7^{\prime\prime}\;(0.0058°) $$
The bus meets accuracy but fails jitter. R1 (36″) closes at ~21″, but R2 (5″) does not — jitter is 7″, and thermo-elastic alignment (16.4″) dominates the total. Neither is fixed by better control gains: alignment is a structures/thermal problem and jitter is above the achievable bus bandwidth.

Mitigations, in order of leverage: (1) a fine-steering mirror inner loop — the real fix; (2) tuned-mass dampers + notches on the array modes; (3) hexapod isolation of the CMG/RW cluster; (4) on-orbit thermal-alignment calibration feed-forward vs. orbit phase; (5) no thruster firing in comm.

11 · The FSM / beacon fine-tracking loop

This is the same two-stage idea as §8, applied optically: a slow, strong, large-range stage (the bus) nested with a fast, weak, small-range stage (the mirror). The bus holds ~20″ — enough to keep the beacon inside the FSM's capture range — and the FSM removes the residual at 100–500 Hz, far above anything a 5500 kg body can do.

ElementProperty
FSM actuatorpiezo/voice-coil tip-tilt, ±1–2 mrad range, kHz-class bandwidth, ~µrad resolution
Sensorquad-cell / focal-plane beacon tracker, ~1″ NEA, kHz frame rate
Loophigh-gain PI + lead, crossover ~100 Hz, integrator kills bus drift
Handoverbus keeps the beacon in capture; FSM offloads its DC tilt back to the bus as a slow bias

Point-ahead angle: because light takes finite time and both terminals move, you must transmit toward where the far terminal will be, not where you see it — an offset of order $\theta_{PAA}\approx 2v_\perp/c$ (tens of µrad), computed from ephemeris and applied as a commanded FSM bias. Its residual knowledge error (~0.5″) is a line item in the final budget. Acquisition sequence: coarse ephemeris point → spiral/raster scan → beacon detect → FSM closed-loop track → data.

LayerLine-of-sight contribution
Bus residual entering the FSM~20″ (kept in capture range)
FSM tracking residual~1.5″
Beacon NEA~1.0″
Point-ahead knowledge~0.5″
Net LOS (RSS)≈2″ (0.0006°), jitter ≈1.5″/s ✓✓

12 · Mode sequence

Detumble
(B-dot, MTQ)
→
Sun acq /
safe
→
Slew
(Lyapunov + CMG)
→
Fine point
(PID + FSM)
→
Momentum
management

Transitions are on angular-velocity thresholds (detumble→acquire→fine); desaturation is on stored-momentum thresholds; actuator choice is by task and regime (§8.3).

13 · Fault detection, isolation & recovery

Redundancy: 2 star trackers, 2 magnetometers, 2 GPS, 4 CMGs (one-fault tolerant), 4 wheels, 3 MTQ axes, 12 thrusters in couples. What matters is the detection logic and the graceful-degradation ladder.

UnitFailure modeDetection signatureResponse
Star trackerSun/Earth blinding, false star ID, freezeinnovation $\chi^2$ spike; stale time-tag; disagreement between headsreject frames, lean on gyro + 2nd head; bias → consider state
Gyrobias jump, scale-factor drift, axis dropoutpersistent innovation bias; tracker-vs-gyro rate mismatchre-estimate bias, reduce propagation interval, tracker-only attitude
CMGgimbal stall, rotor loss, approaching singularity$m\to0$; commanded-vs-actual $\dot\delta$ mismatch3-CMG reconfiguration (reduced envelope), null-motion escape, RW backup
Wheelsaturation, bearing drag, zero-crossing stictionspeed at limit; torque deficitredistribute via null space, desaturate, drop to 3-wheel
MTQ / thrustercoil open, valve stuck open/closedno torque response; unexpected Δv or attitude driftswitch dump path (MTQ↔thruster); isolate stuck valve, use remaining couples

Actuator-loss hierarchy: 4 CMGs → 3 CMGs (smaller envelope, more singularities) → reaction wheels (slower slews, relaxed agility) → thrusters (coarse, fuel-consuming, jitter) → magnetic-only safe mode (attitude survival, no comm). Each rung is a declared degraded mode with its own achievable requirements — not an improvisation.

The hard case is the "soft" failure. A unit that fails silently and plausibly — a tracker reporting a confident wrong quaternion, a slowly drifting gyro scale factor, a valve leaking — is far more dangerous than a clean dropout, because voting needs a third opinion and the filter will happily absorb a consistent lie. Mitigation is cross-sensor residual monitoring plus limits on how fast any estimated parameter is allowed to move.

14 · Flexible-mode excitation & damping

The coupled rigid–flexible model, with modal coordinates $\boldsymbol\eta$ and participation matrix $\Phi$:

$$ J\dot{\boldsymbol\omega}+\Phi^\top\ddot{\boldsymbol\eta}=\mathbf T,\qquad \ddot{\boldsymbol\eta}+2Z\Omega\dot{\boldsymbol\eta}+\Omega^2\boldsymbol\eta=-\Phi\dot{\boldsymbol\omega} $$

Any torque with energy near $\omega_k$ pumps the modes — so the control signal itself is a disturbance source. Layered strategy:

  • Don't excite: input shaping / smooth (jerk-limited, $\sin^2$) slew profiles whose spectra have nulls at the array frequencies; notches on the command path.
  • Actively damp (low frequency): positive-position feedback or strain/rate feedback from accelerometers on the arrays, adding damping to 0.5–1 Hz modes without destabilizing the rigid loop.
  • Passively damp: tuned-mass and viscoelastic dampers on the array structure — no stability risk, no software.
  • High-frequency microvibration (rotor imbalance, cryocoolers, steppers, >10 Hz) is not controllable by the bus at all: it must be isolated (hexapod/passive mounts) and then rejected optically by the FSM.

15 · Red-team "what-if" analysis

What-ifEffectVerdict
Mass +30%slew torque 12.8→16.6 N·m; slew momentum →250 N·m·storque fine (4.5× margin); momentum envelope (300) becomes binding
Lost solar wingdestroys inertia symmetry, shifts CG → large SRP/GG torque + cross-couplingmost severe structural case; may exceed authority → reconfigure & relax pointing
Propellant slosh / depletiontime-varying inertia and CGgain-schedule on mass state or design for robustness (H∞/µ margin)
Star tracker blindedlose fine attitudedual boresight + gyro propagation bridges; redundancy is real only if geometry is right
CMG saturates mid-passloss of torque authoritypre-pass desaturation + RW backup; the 1.6× momentum margin is the buffer
FSM / optical terminal failsjitter requirement unreachableno bus-only recovery — R2 is simply not met; mission degrades to lower data rate
Array modes shift 20%notch mistuned → margin losswide-skirt notches + low crossover; on-orbit modal ID to retune
MEO transfermagnetic dumping stops workingthruster dumping + propellant budget becomes a lifetime driver
The binding constraint isn't torque, it's momentum. The CMGs are deliberately oversized in torque (≈6×), so +30% mass is comfortable on torque — but slew momentum approaches the 300 N·m·s envelope, so growth beyond ~+35% forces a rotor re-baseline. Track mass properties as a live requirement.

16 · Why these choices?

  • Why an MEKF (not additive EKF, not a quaternion in the state)? Keeps the quaternion unit-norm and the covariance non-singular in the 3-D tangent plane — see Attitude.
  • Why quaternions (not Euler)? No gimbal lock, cheap composition, and the natural error algebra for the filter and the Lyapunov proof.
  • Why Lyapunov + PID + LQR together? Global validity at large angles, zero steady-state error against secular torque, and a principled way to pick MIMO gains — each covers the others' gap (§7).
  • Why a 4-SGCMG pyramid? Torque amplification for agility, one-fault tolerance, a near-spherical momentum envelope at 54.7° skew, and a null space to steer around singularities.
  • Why two-level allocation? It decouples the 3-DOF physics problem from the hardware manifest, lets the null space absorb saturation/failures invisibly, and makes actuator changes a Level-2 edit.
  • Why two-stage pointing (bus + FSM)? The bus cannot reach 5″ against flexible modes at any gain; the FSM closes the fast residual on a beacon.
Takeaway. The design closes at nominal with explicit, tracked margins. The estimator (MEKF), the parametrization (quaternion), the actuator (CMG), the two-level allocation, and the optical inner loop are each a direct consequence of the pointing/jitter requirements colliding with the physics of a large flexible spacecraft — and the places it doesn't close (bus jitter, thermal alignment, MEO propellant) are named rather than hidden.

Related: Attitude & the MEKF · Filtering · NASA nav best practices · Star Tracker · IMU. Source: ADCS/ADCS_Laser_Pointing.md (+ critique companion).