Project 5: The Attitude Estimator (Sensor Fusion)
Build a deterministic attitude estimator that fuses gyro, magnetometer, and sun sensor data to estimate satellite orientation using quaternions and an EKF-style filter.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 4: Expert |
| Time Estimate | 2-3 weeks |
| Main Programming Language | Python |
| Alternative Programming Languages | C, C++ |
| Coolness Level | Level 5: Control Systems Wizard |
| Business Potential | Level 3: ADCS Tooling |
| Prerequisites | Linear algebra, quaternions, basic filtering |
| Key Topics | Attitude kinematics, sensor fusion, EKF |
1. Learning Objectives
By completing this project, you will:
- Represent spacecraft attitude with quaternions and propagate it with gyro data.
- Model sensor noise and biases for magnetometers and sun sensors.
- Implement a Kalman-style filter to fuse multiple sensors.
- Validate estimator performance with deterministic simulation data.
- Understand how estimator stability drives control performance.
2. All Theory Needed (Per-Concept Breakdown)
Attitude Representation and Quaternion Kinematics
Fundamentals Attitude is the spacecraft’s orientation in 3D space. Quaternions are the most common representation because they avoid gimbal lock and are numerically stable. A quaternion encodes a rotation as a four-component unit vector. To propagate attitude, you integrate angular velocity from gyros over time. If you do not maintain quaternion normalization, the estimate will drift and become invalid. Understanding quaternion math is essential for any attitude estimator.
Deep Dive into the concept A quaternion represents a rotation by an angle theta around a unit axis u. It is written as q = [q0, q1, q2, q3] where q0 = cos(theta/2) and [q1,q2,q3] = u * sin(theta/2). The key property is that the quaternion must be unit length. When you propagate attitude with gyro measurements, you integrate the quaternion differential equation: q_dot = 0.5 * Omega(omega) * q, where omega is the angular velocity vector and Omega(omega) is a 4x4 matrix derived from omega. In discrete time, you can approximate q_{k+1} = q_k + q_dot * dt and renormalize. More accurate methods use quaternion multiplication by a delta quaternion constructed from omega * dt.
The attitude estimator uses quaternions to maintain a consistent frame mapping between body and inertial coordinates. You must be clear about your convention: does q rotate from inertial to body or body to inertial? This affects how you apply sensor models. For example, a sun sensor measures the sun vector in body coordinates. If you have an inertial sun vector, you must rotate it into body coordinates using the quaternion. A sign or convention mistake yields a 180-degree flipped attitude.
Quaternion normalization is mandatory. Numerical integration errors accumulate; if you do not renormalize, the quaternion will drift away from unit length and eventually represent an invalid rotation. A common practice is to renormalize after every update. In high-precision systems, you can use a correction term, but renormalization is sufficient for CubeSat simulations.
Attitude kinematics also involve frame definitions: body frame, inertial frame, and sometimes orbit frame. A robust estimator clarifies which frame each sensor measurement belongs to. For example, magnetometer measurements are in body frame; the Earth’s magnetic field model provides an inertial or orbit-frame vector. Converting between these frames requires applying the quaternion and potentially a fixed alignment matrix for sensor mounting offsets.
Finally, quaternions are not intuitive. Use visualizations and sanity checks: a quaternion representing zero rotation should be [1,0,0,0], and a 180-degree rotation around X is [0,1,0,0]. Always test these simple cases to ensure your implementation is correct.
How this fit on projects This concept drives Section 3.2 (attitude propagation) and Section 4.4 data structures, and is critical for P06 control.
Definitions & key terms
- Quaternion -> Four-element rotation representation.
- Unit quaternion -> Quaternion with norm 1.
- Body frame -> Coordinate frame fixed to the spacecraft.
- Inertial frame -> Fixed frame used for reference.
Mental model diagram (ASCII)
Inertial vector -> [Quaternion] -> Body vector
How it works (step-by-step, with invariants and failure modes)
- Read gyro angular rates.
- Compute delta rotation for dt.
- Update quaternion via multiplication or integration.
- Renormalize quaternion to unit length.
Invariants: quaternion norm == 1; consistent frame convention.
Failure modes: sign errors, non-normalized quaternions, incorrect axis order.
Minimal concrete example
omega = np.array([0.0, 0.0, 0.01])
q = quat_propagate(q, omega, dt)
q = q / np.linalg.norm(q)
Common misconceptions
- “Euler angles are enough” -> They suffer gimbal lock.
- “Normalization is optional” -> It is required for stability.
Check-your-understanding questions
- Why do we renormalize quaternions after integration?
- What does q = [1,0,0,0] represent?
- How do you rotate a vector using a quaternion?
Check-your-understanding answers
- Integration error accumulates and violates unit norm.
- No rotation (identity).
- Use q * v * q^{-1} (or an equivalent rotation matrix).
Real-world applications
- CubeSat attitude estimation and control loops.
- UAV and robotics orientation tracking.
Where you’ll apply it
- See Section 3.2 (propagation) and Section 5.10 Phase 1.
- Also used in: P06-reaction-wheel-pid-controller-the-mover.md
References
- Markley & Crassidis, Fundamentals of Spacecraft Attitude Determination and Control
- Wertz, Spacecraft Attitude Determination and Control
Key insights Quaternions are the safest way to represent attitude in flight software.
Summary Attitude kinematics are quaternion math plus disciplined normalization.
Homework/Exercises to practice the concept
- Propagate a quaternion with constant angular velocity for 10 seconds.
Solutions to the homework/exercises
- Compare against an analytically computed rotation angle.
Sensor Fusion and Extended Kalman Filtering
Fundamentals No single sensor provides perfect attitude. Gyros drift, magnetometers are noisy and biased, and sun sensors only work in sunlight. Sensor fusion combines these imperfect measurements into a more reliable estimate. The Extended Kalman Filter (EKF) is a common approach: it predicts the state using a model (gyro integration), then corrects it using sensor measurements. The EKF maintains both the state estimate and its uncertainty, allowing you to weigh sensors by their noise levels.
Deep Dive into the concept The EKF is a recursive estimator for nonlinear systems. In attitude estimation, your state might include the quaternion and gyro bias. The process model uses gyro measurements to propagate the quaternion forward. The measurement model predicts what sensors should read given the current attitude (e.g., predicted magnetic field vector in body frame). The EKF then computes the difference between predicted and actual measurements (innovation) and applies a correction weighted by the Kalman gain.
The math behind the EKF is based on linearizing nonlinear models. You compute Jacobians of the process and measurement models to propagate covariance. For example, the Jacobian of the quaternion propagation with respect to gyro bias tells you how bias affects attitude. These Jacobians can be complex, but for a CubeSat-level simulator you can simplify: treat gyro bias as slowly varying and approximate linear relationships. The key is that the filter should converge and remain stable, not that it is mathematically perfect.
Sensor models matter. A magnetometer measures the Earth’s magnetic field vector in the body frame. You need a reference magnetic field model in the inertial or orbit frame to compare against. A sun sensor measures the sun vector in body frame, but only when illuminated. You must gate measurements based on eclipse status. Each sensor has noise characteristics; you encode these as covariance matrices (R for measurement noise, Q for process noise). The tuning of Q and R determines how much you trust each sensor. If Q is too low, the filter ignores measurements; if R is too low, it overreacts to noisy sensors.
Bias estimation is crucial. Gyro bias accumulates over time, causing attitude drift. By including bias as part of the state, the filter can learn and correct it. This requires a process model for bias (e.g., random walk). Without bias estimation, your attitude will gradually diverge, which directly impacts control performance.
To validate the filter, you should run a deterministic simulation with known true attitude and synthetic sensor noise. Compare the estimated attitude to truth and compute errors (e.g., angular error in degrees). The filter should converge to small errors and remain stable. If it diverges, check units, Jacobians, and covariance tuning.
How this fit on projects This concept drives Section 3.2 estimator requirements and Section 6 testing. It also feeds into P06 control and P13 mission integration.
Definitions & key terms
- EKF -> Extended Kalman Filter for nonlinear systems.
- Innovation -> Measurement residual (actual - predicted).
- Covariance (P) -> Uncertainty of the state estimate.
- Process noise (Q) -> Model uncertainty.
- Measurement noise (R) -> Sensor uncertainty.
Mental model diagram (ASCII)
Predict (gyro model) -> Compare to sensors -> Correct -> Updated attitude
How it works (step-by-step, with invariants and failure modes)
- Predict state using gyro model.
- Predict sensor measurements from state.
- Compute innovation and Kalman gain.
- Correct state and covariance.
Invariants: covariance matrix stays positive semi-definite; quaternion normalized.
Failure modes: divergence due to bad tuning, sensor model mismatch, unhandled eclipse.
Minimal concrete example
x_pred = f(x, omega)
P_pred = F @ P @ F.T + Q
K = P_pred @ H.T @ np.linalg.inv(H @ P_pred @ H.T + R)
Common misconceptions
- “EKF will fix any bad model” -> It cannot compensate for wrong physics.
- “More sensors always improves accuracy” -> Bad sensors can degrade estimates.
Check-your-understanding questions
- What is the role of Q and R in the EKF?
- Why include gyro bias in the state?
- How do you handle sun sensor measurements in eclipse?
Check-your-understanding answers
- They weight trust in model vs measurements.
- Bias causes drift; estimating it corrects long-term error.
- Gate them off when no sun is visible.
Real-world applications
- Satellite attitude estimation.
- Robotics and drones.
Where you’ll apply it
- See Section 3.2 (requirements), Section 6.2 (critical tests).
- Also used in: P06-reaction-wheel-pid-controller-the-mover.md, P13-full-mission-simulator-the-digital-twin.md
References
- Markley & Crassidis, Fundamentals of Spacecraft Attitude Determination and Control
- Simon, Optimal State Estimation
Key insights Sensor fusion is a trust-balancing problem: weight each sensor by its uncertainty.
Summary An EKF combines gyro propagation with sensor corrections to maintain attitude accuracy.
Homework/Exercises to practice the concept
- Simulate a gyro bias and observe drift without correction.
Solutions to the homework/exercises
- Add bias to state and verify drift reduction.
3. Project Specification
3.1 What You Will Build
A deterministic attitude estimator that fuses gyro, magnetometer, and sun sensor measurements using a quaternion-based EKF, with outputs logged as attitude and error metrics.
3.2 Functional Requirements
- Quaternion propagation with gyro measurements.
- Sensor models for magnetometer and sun sensor.
- EKF fusion with tuned Q/R matrices.
- Error evaluation against truth data.
3.3 Non-Functional Requirements
- Determinism: fixed random seed for simulated noise.
- Stability: filter convergence within defined error bounds.
- Usability: CLI to run a simulation with output logs.
3.4 Example Usage / Output
$ python attitude_est.py --sim 600 --seed 42
[INFO] RMS error: 0.8 deg
[PLOT] attitude_error.png
3.5 Data Formats / Schemas / Protocols
Simulation config JSON:
{"dt":0.1,"gyro_bias_dps":[0.01,0.0,0.0],"noise_std":0.005}
3.6 Edge Cases
- Eclipse (no sun sensor).
- Magnetometer saturation.
- Large initial attitude error.
3.7 Real World Outcome
A plot of attitude error versus time and logs that show estimator convergence.
3.7.1 How to Run (Copy/Paste)
python attitude_est.py --sim 600 --seed 42 --out logs/
3.7.2 Golden Path Demo (Deterministic)
- Seed 42 and config
configs/nominal.json. - Compare against
golden_error.csv.
3.7.3 Failure Demo (Deterministic)
python attitude_est.py --sim 600 --seed 42 --config configs/bad_tuning.json
Expected: filter diverges; log error exceeds 10 deg and exit code 3.
3.7.4 If CLI: Exact Terminal Transcript
$ python attitude_est.py --sim 600 --seed 42
[INFO] RMS error: 0.8 deg
ExitCode=0
4. Solution Architecture
4.1 High-Level Design
Truth Simulator -> Sensor Models -> EKF -> Attitude Estimate -> Error Metrics
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Propagator | Simulate true attitude | Integration method |
| Sensor Models | Add noise/bias | Noise distributions |
| EKF | Fuse data | State vector design |
| Evaluator | Compute errors | RMS/Max metrics |
4.3 Data Structures (No Full Code)
state = {"q": np.array([1,0,0,0]), "bias": np.array([0,0,0])}
4.4 Algorithm Overview
Key Algorithm: EKF loop
- Propagate quaternion with gyro.
- Predict sensor measurements.
- Update state with EKF correction.
- Renormalize quaternion.
Complexity Analysis:
- Time: O(n) per step (matrix ops).
- Space: O(n^2) covariance.
5. Implementation Guide
5.1 Development Environment Setup
python -m venv .venv
source .venv/bin/activate
pip install numpy matplotlib
5.2 Project Structure
project-root/
+-- attitude_est.py
+-- configs/
+-- logs/
+-- README.md
5.3 The Core Question You’re Answering
“How do you estimate orientation when every sensor lies a little?”
5.4 Concepts You Must Understand First
- Quaternion propagation.
- Sensor noise models.
- EKF correction.
5.5 Questions to Guide Your Design
- Which sensors are available in eclipse?
- How do you tune Q and R?
- What error metric defines success?
5.6 Thinking Exercise
Simulate gyro bias with no correction and observe drift.
5.7 The Interview Questions They’ll Ask
- “Why use quaternions instead of Euler angles?”
- “How does an EKF differ from a KF?”
- “What happens if sensor noise is underestimated?”
5.8 Hints in Layers
Hint 1: Start with gyro-only propagation.
Hint 2: Add magnetometer correction.
Hint 3: Add sun sensor correction with eclipse gating.
Hint 4: Tune Q/R until RMS error stabilizes.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Attitude estimation | Markley & Crassidis | EKF chapters |
| Kalman filters | Simon, Optimal State Estimation | Nonlinear filters |
| Sensor models | Wertz, Spacecraft Attitude Determination | Sensors |
5.10 Implementation Phases
Phase 1: Quaternion Propagation (4-5 days)
Goals: stable attitude propagation. Tasks: implement quaternion integration and normalization. Checkpoint: constant rate rotation matches truth.
Phase 2: Sensor Fusion (5-7 days)
Goals: implement EKF corrections. Tasks: add magnetometer and sun sensor models. Checkpoint: RMS error below 2 deg in nominal case.
Phase 3: Tuning and Validation (4-5 days)
Goals: robust estimator. Tasks: tune Q/R, run stress tests. Checkpoint: estimator stable in eclipse and high noise cases.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| State vector | q only / q + bias | q + bias | Corrects drift |
| Filter | EKF / complementary | EKF | Better for multi-sensor fusion |
| Frame | inertial->body / body->inertial | document clearly | Avoid sign errors |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Unit Tests | Quaternion math | normalization, rotation |
| Integration Tests | Full filter | nominal config |
| Edge Case Tests | Eclipse, high noise | stress configs |
6.2 Critical Test Cases
- No sensor noise: estimator equals truth.
- Gyro bias: estimator corrects over time.
- Eclipse: filter falls back to magnetometer.
6.3 Test Data
configs/nominal.json
configs/high_noise.json
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| Quaternion drift | Attitude explodes | Renormalize every step |
| Bad tuning | Divergence | Increase R or Q appropriately |
| Frame mismatch | 180-degree error | Verify rotation conventions |
7.2 Debugging Strategies
- Plot innovation and covariance to spot instability.
- Compare estimated vs true attitude with angle error.
7.3 Performance Traps
Matrix inversions dominate; keep state size minimal.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add a simple complementary filter baseline.
8.2 Intermediate Extensions
- Include star tracker measurements.
8.3 Advanced Extensions
- Implement multiplicative EKF (MEKF).
9. Real-World Connections
9.1 Industry Applications
- CubeSat ADCS estimators.
- Small satellite attitude determination units.
9.2 Related Open Source Projects
- cFS attitude estimation apps.
- Orekit attitude propagation modules.
9.3 Interview Relevance
- Demonstrates applied estimation theory and sensor modeling.
10. Resources
10.1 Essential Reading
- Markley & Crassidis, Fundamentals of Spacecraft Attitude Determination and Control.
- Wertz, Spacecraft Attitude Determination and Control.
10.2 Video Resources
- Attitude estimation lectures (ADCS courses).
10.3 Tools & Documentation
- numpy, matplotlib for simulation.
10.4 Related Projects in This Series
11. Self-Assessment Checklist
11.1 Understanding
- I can derive quaternion kinematics from angular velocity.
- I can explain EKF prediction and update.
- I can justify Q/R tuning choices.
11.2 Implementation
- Estimator converges on nominal simulations.
- Divergence is detected and logged.
- Output error metrics are deterministic.
11.3 Growth
- I can explain estimator limitations and improvement paths.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Quaternion propagation with gyro input.
- Basic sensor correction with magnetometer.
Full Completion:
- EKF fusion with magnetometer and sun sensor.
- RMS error below 2 deg in nominal case.
Excellence (Going Above & Beyond):
- Bias estimation and MEKF implementation.