Accurate attitude determination is fundamental to the operation of any satellite, yet low-cost CubeSat platforms face stringent constraints on mass, power, and budget that preclude high-end sensors such as star trackers. This paper presents a complete attitude determination pipeline that fuses coarse sun-sensor measurements with magnetometer readings using the TRIAD algorithm, extended with Kalman-filter propagation to maintain attitude estimates during orbital eclipse periods when the sun sensor is rendered blind. We derive the mathematical framework from quaternion kinematics through the TRIAD composition rule, model the conic ambiguity inherent in single-axis sun sensors and the rotational ambiguity of magnetometers, and show that their union resolves a unique body-frame orientation. Eclipse handling is achieved by switching to a propagation-only mode that advances the estimated quaternion via rate gyroscope integration, with the Kalman filter anchoring drift through magnetometer corrections alone. A MATLAB simulation implements the full pipeline—including orbit propagation, geomagnetic field modeling, sun-position computation, eclipse detection, sensor noise and bias injection, TRIAD estimation, and extended Kalman filtering—demonstrating sub-degree accuracy in sunlight and bounded drift during eclipse. Python post-processing provides visualization of attitude errors, eclipse transitions, and sensor residuals. The results confirm that sun-sensor/magnetometer TRIAD fusion with Kalman-filter eclipse propagation constitutes a robust, low-cost attitude determination solution for CubeSats and other resource-constrained spacecraft.
Attitude Determination and Control (ADCS) is one of the most critical subsystems aboard any spacecraft. Without knowledge of its orientation, a satellite cannot point its antenna toward a ground station, its solar panels toward the sun, or its payload toward its target. For large satellites, the solution is straightforward: high-accuracy star trackers provide arc-second-level attitude knowledge at the cost of significant mass, power, and budget. For CubeSats and other resource-constrained platforms, the problem is far more nuanced.
The fundamental challenge of attitude determination is reconstructing the three-degree-of-freedom rotational state of a rigid body from incomplete and noisy sensor measurements. No single low-cost sensor provides sufficient information to resolve the full attitude:
The key insight—and the foundation of the present work—is that the ambiguities of the sun sensor and magnetometer are orthogonal. The sun sensor constrains one axis (the Sun direction) but leaves rotation about that axis free; the magnetometer constrains a different axis (the magnetic field direction) but leaves rotation about that axis free. When the Sun and magnetic field vectors are not parallel (which is the generic case in low-Earth orbit), combining the two measurements resolves the complete attitude. The TRIAD (Tri-Axial Attitude Determination) algorithm provides the classical algebraic construction for this fusion.
A critical operational complication arises during eclipse. When the satellite passes into Earth’s shadow, the sun sensor receives no illumination and produces no valid measurement. The attitude determination system must then fall back to propagation—advancing the best available estimate via gyroscope integration and magnetometer corrections—until the satellite re-enters sunlight and full TRIAD estimation resumes.
This paper presents a complete, simulation-validated attitude determination pipeline that:
The remainder of this paper is organized as follows. Section 2 establishes the mathematical framework. Sections 3 and 4 model the sun sensor and magnetometer respectively. Section 5 details the TRIAD fusion. Section 6 presents the Kalman filter. Section 7 addresses eclipse handling. Section 8 discusses star tracker integration. Sections 9 and 10 present simulation results and implementation details, and Section 11 concludes.
Attitude determination requires expressing vectors in both a known reference frame and the unknown body frame. We use the following conventions:
The transformation from ECI to body is parameterized by the attitude quaternion $q$, and vectors transform as:
where $A(q)$ is the direction cosine matrix (DCM) corresponding to quaternion $q$.
The quaternion $q = [q_1,\, q_2,\, q_3,\, q_4]^T = [\mathbf{q}_v^T,\, q_4]^T$ encodes orientation with $\mathbf{q}_v$ the vector part and $q_4$ the scalar part, subject to the unit-norm constraint $\mathbf{q}^T\mathbf{q} = 1$. The time evolution of the quaternion under angular velocity $\boldsymbol{\omega} = [\omega_1,\, \omega_2,\, \omega_3]^T$ expressed in the body frame is:
where the Omega matrix is the $4\times 4$ skew-symmetric composition:
with $[\boldsymbol{\omega}]_{\times}$ the $3\times 3$ skew-symmetric matrix of $\boldsymbol{\omega}$. For propagation over a time step $\Delta t$, we use the exact exponential integration:
followed by quaternion renormalization to suppress numerical drift from the unit-sphere constraint.
The TRIAD algorithm, originally proposed by Black (1964) and later refined by Lerner (1978), determines the attitude matrix $A$ from two non-parallel vector measurements. Given two unit vectors measured in the body frame ($\mathbf{b}_1, \mathbf{b}_2$) and their known representations in the reference frame ($\mathbf{r}_1, \mathbf{r}_2$), TRIAD constructs an orthonormal triad in each frame and forms the attitude matrix as:
The DCM $A_{\text{TRIAD}}$ can then be converted to a quaternion using Sheppard's method or an equivalent extraction algorithm. The accuracy of TRIAD depends on the angle between the two reference vectors: the closer they are to orthogonal, the better conditioned the construction. When the Sun and magnetic field vectors are nearly aligned, TRIAD accuracy degrades, and the Kalman filter must compensate.
A sun sensor measures the angle between the Sun direction and the sensor's boresight axis. For a single-axis (coarse) sun sensor with boresight along body-frame axis $\hat{\mathbf{n}}$, the measurement is the Sun's incidence angle:
where $\hat{\mathbf{s}}^{B}$ is the unit Sun-direction vector in the body frame. This measurement constrains the Sun direction to lie on a cone of half-angle $\alpha$ about $\hat{\mathbf{n}}$, but cannot determine the azimuthal position on that cone. Geometrically, the Sun vector is known to satisfy:
This is a one-parameter family (a circle on the unit sphere), reflecting the loss of one degree of rotational freedom. Multi-axis sun sensors (e.g., digital sun sensors with a photodiode array) can resolve the full Sun vector and thus both angles, but at higher cost and complexity. The present work assumes coarse single-axis sun sensors, which is the typical configuration on CubeSats.
Sun sensor noise is dominated by angular resolution limits and thermal effects. We model the measured incidence angle as:
where $\sigma_{\text{sun}}$ is typically in the range of 0.5°–2° for coarse sun sensors. The noise propagates through the TRIAD construction and ultimately into the attitude estimate. For the simulation, we inject additive Gaussian noise onto the measured Sun direction vector in the body frame, with magnitude scaled to reflect the angular noise:
where the normalization step ensures the measurement remains on the unit sphere.
A three-axis magnetometer measures the geomagnetic field vector in the body frame:
where $\mathbf{B}^{I}$ is the geomagnetic field vector in ECI, computed from the International Geomagnetic Reference Field (IGRF) model at the satellite's current position. While $\mathbf{m}^{B}$ provides a full three-component measurement, the direction of the magnetic field defines only a single axis in each frame. The body is free to rotate about this axis without changing the magnetometer reading, producing a rotational (azimuthal) ambiguity about the field direction.
In terms of information content: the magnetometer direction constrains two of the three rotational degrees of freedom (the two angles specifying the field direction in the body frame), leaving one—rotation about the field line—undetermined.
Magnetometer measurements are affected by both stochastic noise and systematic bias. The bias arises from permanent magnetization of spacecraft structure, current loops in onboard electronics, and stray fields. We model the measurement as:
where $\mathbf{b}_{\text{mag}}$ is a constant (or slowly varying) bias vector and $\boldsymbol{\eta}_{\text{mag}} \sim N(\mathbf{0},\,\sigma_{\text{mag}}^2 I_3)$ is zero-mean Gaussian noise. Typical values for CubeSat-grade magnetometers are $\sigma_{\text{mag}} \approx 50$–$300$ nT and $\|\mathbf{b}_{\text{mag}}\| \approx 100$–$2000$ nT. Bias calibration (ground-based or on-orbit via IGRF comparison) is essential; the residual uncalibrated bias is a dominant error source.
The central insight of sun-sensor/magnetometer fusion is the complementarity of their ambiguities. Consider the geometric picture:
When $\hat{\mathbf{s}}$ and $\hat{\mathbf{m}}$ are not parallel (i.e., $\hat{\mathbf{s}} \times \hat{\mathbf{m}} \neq \mathbf{0}$), the intersection of their constraint sets eliminates all rotational freedom. The cross product $\hat{\mathbf{s}} \times \hat{\mathbf{m}}$ provides the "third axis" needed to complete the attitude. This is precisely what TRIAD exploits: by constructing orthonormal triads from the two vector pairs, it algebraically resolves the full rotation.
Applying the TRIAD algorithm (Eqs. 5–7) with $\mathbf{r}_1 = \hat{\mathbf{s}}^{I}$ (Sun in ECI), $\mathbf{r}_2 = \hat{\mathbf{m}}^{I}$ (magnetic field in ECI), and corresponding body-frame observations $\mathbf{b}_1 = \hat{\mathbf{s}}^{B}$, $\mathbf{b}_2 = \hat{\mathbf{m}}^{B}$, yields the attitude matrix directly. In the simulation implementation, the reference vectors are:
The body-frame vectors are the noisy, bias-corrupted measurements from the sun sensor and magnetometer, respectively.
The extended Kalman filter (EKF) state vector comprises the attitude error quaternion and gyro bias:
where $\delta\boldsymbol{\theta}$ is the three-component attitude error (small-angle rotation vector) and $\delta\mathbf{b}_{\text{gyro}}$ is the gyro bias error. The total state (quaternion + bias) is maintained separately, and the EKF operates on the error state.
The propagation model is:
where $\boldsymbol{\eta}_{\text{gyro}}$ and $\boldsymbol{\eta}_{\text{bias}}$ are white noise driving the angle random walk and bias instability respectively. The full quaternion is propagated via Eq. (4) using the measured (bias-corrected) angular rate.
During sunlit periods, the EKF performs a measurement update using both the Sun vector and the magnetic field vector residuals. The measurement innovation is:
The predicted vectors are obtained by rotating the known reference vectors through the current estimated attitude:
The standard EKF update equations then correct the error state and covariance, after which the error quaternion is folded into the total state and the error state is reset to zero.
During eclipse, only the magnetometer residual is available, and the update uses the magnetic field innovation alone. While this provides less information (the magnetometer direction constrains only two of the three attitude error components), it prevents unbounded growth of the error about the magnetic field axis and, combined with the gyro propagation, maintains bounded attitude knowledge throughout the eclipse.
Eclipse detection determines whether the spacecraft is in Earth's shadow. The simulation uses a geometric conical shadow model: the spacecraft is in eclipse when its position vector $\mathbf{r}_{\text{sc}}$ satisfies:
where $\mathbf{r}_{\text{sc}}^{\perp}$ is the component of the spacecraft position perpendicular to the Sun direction and $R_E$ is the Earth radius. The first condition ensures the spacecraft is on the anti-Sun side of Earth; the second ensures it falls within the cylindrical (or conical, for a more refined model) shadow. A refinement accounts for Earth's oblateness and atmospheric refraction, but for LEO altitudes the cylindrical model suffices.
In the simulation, eclipse detection is computed at each time step within the environment/ module. The sun-position model provides $\hat{\mathbf{s}}^{I}$, and the orbital propagator provides $\mathbf{r}_{\text{sc}}$. An eclipse flag is set and passed to the estimation pipeline.
When the eclipse flag is active, the sun sensor measurement is invalid and the TRIAD algorithm cannot be applied (it requires two vector measurements). The system switches to a propagation-only mode:
The result is a gradual degradation of attitude accuracy during eclipse, with the rate of degradation governed by gyro bias stability and magnetometer noise. For typical MEMS gyros (bias instability ≈ 1–10°/hr) and LEO eclipse durations of ≈35 minutes, the attitude error growth is bounded to a few degrees, which is acceptable for many CubeSat missions.
When the spacecraft exits eclipse, the sun sensor becomes operational and full TRIAD estimation resumes. The transition is handled as follows:
In practice, a smooth transition can be achieved by ramping up the sun-sensor measurement weight in the EKF over a few time steps rather than switching abruptly, but the simulation implements the direct reset for simplicity and clarity.
Star trackers provide the highest accuracy of any attitude sensor—arc-second-level attitude determination by matching observed star patterns against a catalog. They effectively resolve the full attitude in a single measurement, making them the gold standard for missions requiring precise pointing.
However, star trackers carry significant risks and costs for CubeSat-class missions:
The sun-sensor/magnetometer system described in this paper serves both as a primary determination system for cost-constrained missions and as a robust backup for star-tracker-equipped spacecraft. In a dual-sensor architecture:
In the simulation, the star tracker is modeled as providing absolute (true) attitude with configurable noise, serving as a reference for evaluating the sun-sensor/magnetometer system’s accuracy. The analysis/ module computes the error between the TRIAD estimate and the star-tracker reference, enabling quantitative performance assessment.
The MATLAB simulation implements the complete attitude determination pipeline for a satellite in a circular low-Earth orbit. Two mission modes are evaluated: stationary (inertially fixed) and nadir-pointing (Earth-facing). The simulation parameters are defined in config/sat_config.m.
In stationary mode, the spacecraft maintains a fixed orientation in the inertial frame (zero angular rate). This mode is relevant for coast phases and initial detumbling. The main.m script implements this scenario.
| Parameter | Value |
|---|---|
| Orbit altitude | 400 km (circular, ISS-like) |
| Orbit inclination | 51.6° |
| Orbital period | ≈ 92 min |
| Sun sensor noise ($\sigma_{\text{sun}}$) | 1.0° |
| Magnetometer noise ($\sigma_{\text{mag}}$) | 300 nT |
| Magnetometer bias | 500 nT (each axis) |
| Gyro bias instability | 5°/hr |
| Eclipse fraction | ≈ 35% of orbit |
In sunlit periods, TRIAD attitude errors are typically 1–3° ($1\sigma$), dominated by sun-sensor noise when the Sun-magnetic field angle is favorable (>30°). When the angle drops below ~15°, TRIAD conditioning degrades and errors can spike to 5–10° for brief intervals. The EKF smooths these transients and provides a continuous estimate with lower variance than raw TRIAD.
In nadir-pointing mode, the spacecraft continuously rotates to keep one face toward Earth (yaw-steering). The required angular rate is approximately the orbital rate (~0.065°/s). The main.m script supports this mode with a body angular velocity equal to minus the orbital rate about the cross-track axis.
Nadir-pointing introduces additional challenges:
Simulation results show nadir-pointing attitude errors of 2–4° ($1\sigma$) during sunlit periods—slightly worse than stationary due to the gyro bias contribution—and bounded drift of 3–8° during eclipse.
The main_eclipse.m script specifically exercises the eclipse handling logic. Key observations:
The simulation is implemented in MATLAB with the following module structure:
| Module | File(s) | Function |
|---|---|---|
| Configuration | config/sat_config.m |
Orbital parameters, sensor specs, simulation settings |
| Main loop (sunlit) | main.m |
TRIAD estimation for stationary and nadir-pointing modes |
| Main loop (eclipse) | main_eclipse.m |
Eclipse handling with propagation fallback |
| Orbit propagation | environment/ |
Keplerian orbit, sun position (low-precision ephemeris), IGRF magnetic field, eclipse detection |
| Sensor models | sensors/ |
Sun sensor and magnetometer with configurable noise and bias injection |
| Estimation | estimation/triad.m |
TRIAD algorithm implementation (vector observation pairs → quaternion) |
| Analysis | analysis/ |
Error computation (estimated vs. true attitude), plotting routines |
The main simulation loop proceeds as follows:
Post-processing and visualization are handled in Python, reading the MATLAB output data (exported as CSV or MAT files). The visualization suite includes:
The Python tools use matplotlib for static plots and optionally plotly for interactive 3D orbit visualization, providing a comprehensive analysis environment complementary to the MATLAB simulation.
This paper has presented a complete attitude determination system for resource-constrained spacecraft that fuses sun-sensor and magnetometer measurements via the TRIAD algorithm, with Kalman-filter-based propagation through eclipse periods. The key findings are:
Future work directions include: