IMU#
Inertial measurement unit — gyroscope and accelerometer.
The imu class models a strapdown gyroscope and accelerometer pair. The gyroscope measures body rates
[p, q, r]. The accelerometer measures the full body-frame specific force[ax, ay, az].An imu instance is a
statewhose state vector is the last measured sample,X = [ax, ay, az, p, q, r]. This gives imu thestore()anddata()methods for free (measureuses store internally, see below).- Parameters:
gyro_std (float, optional) – Standard deviation of the gyroscope noise, [rad/s]. Defaults
0.01.acc_std (float, optional) – Standard deviation of the accelerometer noise, [m/s²]. Defaults
0.05.gyro_bias (array_like, optional) – Constant gyroscope bias
[bp, bq, br], [rad/s]. Defaults[0, 0, 0].acc_bias (array_like, optional) – Constant accelerometer bias
[bax, bay, baz], [m/s²]. Defaults[0, 0, 0].g (float, optional) – Gravitational acceleration, [m/s²]. Defaults
9.81.isideal (bool, optional) – A flag indicating whether the errors model is off. Defaults False.
dt (float, optional) – Fallback timestep, [s], used for the accelerometer’s finite-difference inertial term when consecutive calls to
measuredon’t carry increasing t values. Defaults0.005(\(200Hz\)).
See also
Functionality
At each sample the imu returns rate and acceleration measurements based on the true state of a rigid body. Let the true state be:
\[X = [x, y, z, v_x, v_y, v_z, \varphi, \theta, \psi, p, q, r]^T\]Where:
\(x, y, z\) are the inertial position coordinates
\(v_x, v_y, v_z\) are the inertial velocity coordinates
\(\varphi, \theta, \psi\) are the Euler angles (roll, pitch, yaw)
\(p, q, r\) are the body rates about the roll, pitch, yaw axes
The gyroscope measurement is the last three states directly:
\[[p, q, r]_{meas} = [p, q, r] + bias_{gyro} + noise_{gyro}\]The accelerometer measures the full body-frame specific force, i.e. gravity reaction plus the vehicle’s own coordinate acceleration:
\[[a_x, a_y, a_z]_{ideal} = [BI] \cdot \big(\dot{v} + [0,\ 0,\ g]^T\big)\]where \([BI]\) is the body-from-inertial DCM and \(\dot{v}\) is the inertial-velocity derivative. Since measure is given only the current true state, \(\dot{v}\) is approximated by a finite difference against the previous call’s true state:
\[\dot{v} \approx {v(t) - v(t_{prev}) \over t - t_{prev}}\]which is why
measurekeeps the previous sample as an internal attribute (t_prev, x_prev) rather than asking the caller for it: the first call to measure (no previous sample yet) therefore reports the gravity term alone.Errors Model
Bias: a constant offset, set at construction through gyro_bias / acc_bias and unchanged between measurements.Noise: a zero-mean Gaussian sample, drawn independently at every call tomeasure, with standard deviation gyro_std / acc_std.
The errors model can be disabled by applying
isideal = Trueat the imu construction stage: the gyroscope and accelerometer standard deviations and biases are then muted (forced to zero), regardless of thegyro_std/acc_std/gyro_bias/acc_biasarguments, andmeasurereturns the noise-free, bias-free truth.Construction
An imu instance is created by making a direct call to the constructor:
>>> imu_sensor = c4d.sensors.imu()
Initialization does not require any mandatory arguments.
Examples
Import required packages:
>>> import c4dynamics as c4d >>> import numpy as np
Ideal imu
An ideal imu can be created by muting the errors model:
>>> imu_ideal = c4d.sensors.imu(isideal = True) >>> rb = c4d.rigidbody(theta = -0.1, p = 0.2, q = -0.1, r = 0.05) >>> ax, ay, az, p, q, r = imu_ideal.measure(rb) >>> np.array([p, q, r]) [0.2 -0.1 0.05] >>> ax -0.979... >>> az -9.760...
Non-ideal imu
>>> np.random.seed(100) >>> imu_sensor = c4d.sensors.imu(gyro_std = 0.01, acc_std = 0.05) >>> rb = c4d.rigidbody() >>> imu_sensor.measure(rb) (-0.012..., 0.049..., -9.784..., -0.017..., 0.003..., 0.011...)
Store
Passing
store = Truestores the sampled [ax, ay, az, p, q, r] along with the given timestamp; the histories are then available throughdata():>>> np.random.seed(200) >>> imu_sensor = c4d.sensors.imu(isideal = True) >>> rb = c4d.rigidbody() >>> for t in np.arange(0, 0.02, 0.005): ... rb.p = 0.1 * t ... imu_sensor.measure(rb, t = t, store = True) >>> imu_sensor.data('p') (array([0. , 0.005, 0.01 , 0.015]), array([0. , 0.0005, 0.001 , 0.0015]))
Demo
The built-in
demomethod provides a compact demonstration of the imu errors model and plots the true and measured rates and accelerations:>>> fig = c4d.sensors.imu.demo(show = True)
The same demonstration can be run without displaying the figure by using
show = False.Methods
imu.measure(rb[, t, store])Measures body rates and specific acceleration of a rigid body.