Kinematics API¶
propagate_gyro ¶
propagate_gyro(R0: ndarray, angular_velocity: ndarray, dt: float | ndarray, bias: ndarray | None = None) -> jnp.ndarray
Propagate attitude from body-frame angular-rate measurements.
This function integrates a sequence of gyroscope measurements directly on \(SO(3)\). Each angular increment is mapped to a rotation matrix with the exponential map and composed with the current attitude. Consequently, the propagation does not require Euler angles, quaternion normalization, or projection of an additively integrated matrix back onto the rotation group.
Frame convention
R0 is the initial body-to-world rotation. For a vector
\(\mathbf{v}_B\) expressed in the body frame, the corresponding vector
in the world frame is
Angular velocity is expressed in the body frame. The attitude increment is therefore composed on the right. If \(R_k\) is the attitude at sample \(k\), the update is
where \(\boldsymbol{\omega}_{m,k}\) is the measured angular velocity, \(\mathbf{b}\) is a constant gyroscope bias, and \(\Delta t_k\) is the duration represented by that measurement. Equivalently, the model assumes
Setting bias to the known sensor bias therefore recovers the corrected
body rate \(\boldsymbol{\omega}_k\) before propagation. When bias
is omitted, it is taken to be zero.
The angular velocity is treated as constant over each sampling interval. Under that assumption, the exponential update is the exact rotation for the individual interval. Accuracy over a complete trajectory still depends on the sampling rate, measurement quality, timestamp accuracy, and validity of the constant-bias assumption.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
R0
|
(Array, shape(3, 3))
|
Initial body-to-world rotation matrix. The caller is responsible for providing a proper rotation in \(SO(3)\). |
required |
angular_velocity
|
(Array, shape(samples, 3))
|
Body-frame gyroscope measurements in radians per second. Rows are consumed in chronological order. |
required |
dt
|
(float or Array, shape(samples))
|
Sampling interval in seconds. A scalar applies the same interval to every measurement. A one-dimensional array supplies one interval per measurement. |
required |
bias
|
(Array, shape(3))
|
Constant body-frame gyroscope bias in radians per second. The default
is a zero vector with the same dtype as |
None
|
Returns:
| Type | Description |
|---|---|
(Array, shape(samples + 1, 3, 3))
|
Body-to-world attitude history. Element zero is exactly |
Notes
The recurrence is evaluated with jax.lax.scan, so the complete
propagation is compatible with jax.jit and can be differentiated
with respect to the angular velocities, timesteps, initial attitude, or
bias. The output remains on \(SO(3)\) up to floating-point roundoff when
R0 is a proper rotation.
This is gyroscope-only attitude propagation, not a complete IMU model or state estimator. It does not estimate a time-varying bias, fuse accelerometer or magnetometer observations, model noise, propagate a covariance, or correct accumulated drift. Those responsibilities belong to the estimator or application using this kinematic primitive.
Examples:
Propagate one second of constant yaw rate, correcting a known sensor bias:
>>> import jax.numpy as jnp
>>> from symplie.kinematics import propagate_gyro
>>> R0 = jnp.eye(3)
>>> true_rate = jnp.array([0.0, 0.0, 0.5])
>>> bias = jnp.array([0.01, -0.02, 0.03])
>>> measurements = jnp.broadcast_to(true_rate + bias, (100, 3))
>>> attitudes = propagate_gyro(R0, measurements, dt=0.01, bias=bias)
>>> attitudes.shape
(101, 3, 3)
See Also
symplie.so3.exp Exponential map used for each body-frame angular increment.