Example: IMU Sensor Model
This headless example compares an ideal IMU and a modeled IMU attached to the same moving body. It demonstrates separate accelerometer/gyro errors, sensor bandwidth, acquisition timestamps and delayed delivery. It prints CSV and does not start a renderer or TCP server.
For the measurement equations and parameter units, see the IMU guide. The Server Example: Sensor Suite example covers cameras and LiDAR alongside the IMU.
Build and run
CMake target: imu_sensor_model. Its source is
examples/src/server/sensors/imu_sensor_model.cpp.
Build it from an examples build configured as described in Build, Test, and Benchmark:
cmake --build build-examples --target imu_sensor_model --config Release --parallel 12
./build-examples/examples/imu_sensor_model > /tmp/imu.csv
On Windows, use the build’s bin directory:
.\build-examples\bin\imu_sensor_model.exe > "$env:TEMP\imu.csv"
The example takes no arguments and finds activation.raisim in the examples’
resource directory via exampleRscPath(argv[0], ...). Install your activation
key in that resource directory before running.
No robot or mesh assets are needed: the source declares a small URDF in memory.
Use matching RaiSim headers and binaries with
InertialMeasurementUnit::ChannelProperties support. Older binary packages do
not provide the modeled-sensor API. CMake omits this target with an explanatory
status message when the selected package lacks that API.
What it simulates
A floating 1 kg body with unit rotational inertia carries two IMUs, both 0.1 m along its +X axis with the same orientation. Gravity is compensated by an applied force, with an additional vertical sinusoid and an oscillating torque about +Z. The ideal IMU therefore exposes vertical specific force, angular velocity, and both tangential and centripetal acceleration from the offset mount.
Physics runs at 1000 Hz; both IMUs acquire at 400 Hz. Their acquisition intervals alternate between 2 ms and 3 ms. The modeled IMU adds initial bias, white noise, bias random walk, first-order filtering, quantization, per-axis clipping and 3 ms of delivery latency. Parameters illustrate the interface rather than a particular commercial device.
auto properties = std::as_const(*modeled).getProperties();
properties.seed = 43;
properties.accelerometer.bias = {0.01, -0.02, 0.03};
properties.accelerometer.noiseDensity = 0.002;
properties.accelerometer.biasRandomWalk = 0.0001;
properties.accelerometer.cutoffFrequency = 30.;
properties.accelerometer.resolution = 0.001;
properties.gyroscope.bias = {0.001, -0.002, 0.003};
properties.gyroscope.noiseDensity = 0.0002;
properties.gyroscope.biasRandomWalk = 0.00001;
properties.gyroscope.cutoffFrequency = 50.;
properties.gyroscope.resolution = 0.0001;
properties.maxAcc = 16. * 9.81;
properties.maxAngVel = 2000. * kPi / 180.;
properties.latency = 0.003;
modeled->setProperties(properties);
The settings are fixed in the source, with seed 43 and 1000 physics steps. Change the property assignments to try another model. The ideal sensor already provides the zero-error reference in every CSV row.
Reading the CSV
Each row represents one delivered modeled sample. The columns are:
Columns |
Meaning |
|---|---|
|
Acquisition and availability in simulation seconds. |
|
Ideal specific force at the same acquisition time, in sensor axes, m/s². |
|
Modeled accelerometer output, m/s². |
|
Ideal angular velocity at that acquisition time, rad/s. |
|
Modeled gyro output, rad/s. |
|
Perfect sensor-to-world orientation at acquisition; not an estimated attitude. |
The example retains a short history of ideal samples and matches each delayed reading by acquisition time. Comparing it to the current ideal reading would mix latency-induced motion differences into the apparent sensor error. The remaining difference includes the configured bias, filtering and noise.
Plot either measured channel against its ideal counterpart using
acquisition_s on the horizontal axis. Plot delivery_s - acquisition_s to
inspect availability latency. The first default reading is acquired at 0.001 s
and delivered at 0.004 s; no startup buffers with negative timestamps are emitted.
At the end of the one-second simulation, the newest delayed samples may still be pending. The example does not advance extra physics solely to flush them. Running the same motion with the same seed reproduces CSV on the same platform/build; a different seed changes the stochastic readings while preserving ideal motion.