Differential IMU
Node ID: differentialImu · Role: Filter · Realtime config: no
Description
Computes differential orientation between two IMU sensors (e.g. reference body and headset). Outputs transformed IMU data with the relative orientation removed.
Algorithm notes
What this node computes
The Differential IMU node is not a filter in the estimation sense - it carries no internal state estimate, no covariance, and no tuning gains. It is a deterministic per-sample frame subtraction: it removes the rotation rate of a moving platform from the rotation rate measured on a device riding that platform, so that downstream orientation estimators see motion relative to the platform rather than relative to the earth.
The classic use case is a headset inside a moving vehicle. The headset’s own gyroscope reports the sum of the wearer’s head motion and the vehicle’s motion. Subtracting the vehicle’s rate leaves head-relative rate, which is what a head-tracking pipeline should integrate.
Three frames are involved: the reference IMU’s own sensor frame (mounted on the vehicle or other moving body), the global frame shared by the tracking system, and the primary IMU’s sensor frame (on the headset). The reference rate is rotated from its mounting frame into the global frame using the configured static orientation, then rotated from global into the current headset frame using the headset’s live orientation, and finally subtracted from the primary gyroscope. Only the gyroscope is modified. Accelerometer, magnetometer, quaternion, Euler, timestamp, latency, and period fields pass through from the primary sample untouched - the node does not attempt to remove platform acceleration or centrifugal effects.
How the inputs are used
The node has three inputs and treats them asymmetrically.
The Primary IMU input is the clock. Every primary sample triggers one computation and one output sample, so the output rate and timestamps exactly match the primary stream.
The Reference IMU input is a latched value. Each arriving reference sample overwrites the stored angular velocity, and the most recent value is used whenever a primary sample arrives. There is no interpolation and no timestamp matching, so the reference rate applied to a given primary sample is up to one reference sample period old.
The Fused Pose input supplies the current headset orientation used for the global-to-headset rotation. Only orientation is read; position is ignored.
There is no explicit initialization phase and nothing converges. Before the first reference sample arrives, the stored reference rate is zero, so the output is simply a copy of the primary gyroscope. Before the first fused pose arrives, the headset orientation is treated as identity, so the subtraction is performed in the global frame instead of the headset frame - correct only while the headset happens to be aligned with global. Both effects vanish as soon as the first sample of each stream is received, typically within milliseconds.
Routing is by wire, not by sender name. The node distinguishes primary from reference purely by which input handle a source is connected to. An IMU arriving without a handle assignment is dropped and logged.
Parameters
There are only two user-facing settings, and they address separate concerns.
Mounting geometry. The reference orientation quaternion describes how the reference IMU is bolted to the moving body relative to the global frame. This is the only parameter that affects the numerical result, and it is the only one worth tuning. Its default is not identity - it encodes a specific mounting convention, so it must be revisited for any new installation.
Stream identity. The output sender identifier is stamped on emitted samples so downstream nodes can distinguish this differential stream from raw IMU sources. It has no effect on the math; change it only when several IMU streams would otherwise collide downstream.
Tuning and failure modes
Verify the mounting quaternion with a static test: with the headset held still relative to the vehicle, rotate the whole platform. A correct configuration drives the output gyroscope to near zero on all three axes. Residual on a single axis usually means a sign error in the quaternion; residual that swaps between axes as you change the direction of rotation means two axes are exchanged.
Known limitations to watch for:
- A wrong mounting quaternion is worse than none. An incorrect rotation injects the platform’s rate back into the output on the wrong axes, producing drift that grows with vehicle motion rather than cancelling it.
- Rate mismatch leaves residuals. If the reference IMU runs slower than the primary, the stale latched value produces transient error during fast platform maneuvers. Run the reference at or above the primary rate.
- A missing or stale fused pose silently degrades the subtraction. Because the identity fallback is not flagged, a disconnected pose input looks like a working setup until the headset turns away from global-aligned.
- Linear motion is untouched. Vehicle acceleration, vibration, and lever-arm effects remain in the accelerometer stream, so a downstream estimator that leans on gravity for pitch and roll will still be disturbed by the platform.
- Swapped inputs invert the result. Wiring the vehicle IMU to the primary handle produces an output that looks plausible in magnitude but has the wrong sign structure; check the handle labels before trusting a quiet output.
Inputs / Outputs
- Inputs:
PrimaryImu(Imu) - Primary IMU,ReferenceImu(Imu) - Reference IMU,FusedPose - Outputs:
Imu
Config aliases
DifferentialImuFilter, differentialImuFilter, differentialImu
Required feature
differential_imu_fusion
Properties
The following fields are exposed in the node’s Properties panel in the UI. Types map to UI widgets (e.g. string → text input, number → numeric, boolean → toggle, select → dropdown, json → JSON editor).
| Key | Label | Type | Default | Description / Notes |
|---|---|---|---|---|
referenceOrientationQuat | Reference Orientation | quaternion | {"w":1,"x":-1,"y":1,"z":1} | Quaternion (w,x,y,z) rotating the reference IMU’s frame into the global frame. The reference IMU’s angular velocity is rotated by this, transformed into the headset frame, and subtracted from the headset IMU’s gyroscope so the output gyro is relative to the moving reference (e.g. a vehicle). Edit when the reference IMU is mounted at a different orientation. |
outputSenderId | Output Sender ID | string | differentialImu | Sender identifier stamped on the output IMU stream, used downstream to distinguish this differential IMU from other IMU sources. |
Example node definition
A full node definition in config.json looks like the block below. Paste it under the sinks key of your config, keyed by the node’s instance name (any identifier; it doesn’t have to match the node ID).
{
"sinks": {
"differentialImu": {
"dataEndpoint": "inproc://differentialImu_data",
"inputEndpoints": [
"inproc://primaryImu_data",
"inproc://referenceImu_data",
"inproc://fusedPose_data"
],
"inputDataFilter": [
"Imu",
"Imu",
"FusedPose"
],
"settings": {
"outputSenderId": "differentialImu",
"referenceOrientationQuat": {
"w": 1,
"x": -1,
"y": 1,
"z": 1
}
}
}
}
}
Field reference
| Field | Purpose |
|---|---|
dataEndpoint | Endpoint this node binds to publish its output. Omit to let the runtime generate one. |
inputEndpoints | List of upstream endpoints this node connects to (outEndpoint / dataEndpoint values from upstream nodes). |
inputDataFilter | Optional whitelist of data types. Messages whose type isn’t in the list are dropped at the subscriber. |
settings | All user-configurable fields — see the Properties table above. |
Connections can also be declared at the top-level
connectionsarray whensettings.explicitConnectionsistrue, as an alternative to fillinginputEndpointson each node.