Your gyro is configured for 400 Hz, so you expect one IMU message every 2.5 ms. The log instead shows one message, then a pair of two, over and over — and the pattern survives every rate, cable and port you try. This is the most common shape of an IMU recording complaint on depth cameras, and in most cases nothing is missing: the average rate is exactly right and only the delivery is bursty. This guide gives you the window test that proves it in ten seconds, the settings that steady the messages you do get, and the point at which an external IMU is the honest answer. It is written for engineers recording IMU streams for visual-inertial odometry on robots.
Why does a 400 Hz gyro arrive as one sample, then two?
The sensor is sampling at 400 Hz and the bus is not: the camera queues IMU samples in hardware and hands several of them to the host in one USB transfer, so your driver receives a burst every 7.5 ms instead of one sample every 2.5 ms.
Do the arithmetic and the observed pattern confirms itself. At 400 Hz the nominal interval is 1 / 400 Hz = 2.5 ms, so three samples span 7.5 ms. A delivery of one message followed by a couplet of two puts three messages into each 7.5 ms window: 3 / 7.5 ms = 400 samples per second. The rate is perfect. Only the spacing is uneven, at roughly 3.7 ms between successive deliveries.
The spacing belongs to the transport, not the sensor. USB moves data in packets on a schedule of its own: the sensor writes every sample, with its hardware timestamp, into an on-board queue, and the host driver drains that queue in chunks whenever its transfers complete. Two or three 2.5 ms samples landing in one chunk is what a queued endpoint looks like from user space. The same mechanism is why IMU read rate drops while a video stream runs: image data takes bus time first, and the IMU queue is drained in whatever shape remains.
Changing stream rates reshapes the chunks without changing the mechanism, which is why a lower gyro rate shows the same grouped pattern at a different scale. Periodic dips in arrival spacing — one recording showed a drop roughly every second — are the drain cadence showing through. They are not lost samples until the window count in the next section says so.
Is data actually lost when the intervals are uneven?
Count samples over a fixed window instead of reading individual gaps: divide the message count minus one by the span between the first and last hardware timestamps, and call the stream healthy when the result is within about 1% of the configured rate over 10 seconds or more.
Here f is the configured rate in Hz, n the number of messages recorded, and t_last and t_first the first and last hardware timestamps in the file.
Worked example, gyro configured at 400 Hz, recorded for 10.000 s of camera time. Nominal interval: 1 / 400 Hz = 2.5 ms. The file holds 3,998 messages stamped 0.000 s to 10.000 s. Measured rate = (3,998 − 1) / (10.000 − 0.000) s = 3,997 / 10.000 s = 399.7 Hz. That is 0.3 Hz below target, or 0.075%, comfortably inside the 1% line — exactly what a complete but batched stream looks like.
The same window catches real loss. A file with 3,600 messages over 10.000 s gives 3,599 / 10.000 s = 359.9 Hz, a 10% shortfall. Batching never produces a deficit that size; only dropped samples do. That result sends you to the version and contention checks below, not to more launch-flag experiments.
Use the hardware stamps as the second discriminator. Arrival times that bunch while the stamps step evenly at 2.5 ms mean every sample is present and only the delivery is lumpy. Gaps in the stamps themselves — 5 ms steps where 2.5 ms steps belong, repeating — are genuine drops. Value-level noise is a separate complaint from timing; for that, follow the calibration and filtering guide for unstable IMU readings.
Which launch settings make the IMU stream steadier?
Three settings change what each message means: unite_imu_method set to copy keeps every united message on a true gyro timestamp, enable_sync set to true tags the closest frames of different sensors with one time, and global_time_enabled set to false stops the host from re-stamping against its own clock.
The unite choice matters most for odometry. With a 400 Hz gyro and a 250 Hz accelerometer, linear_interpolation builds each united message by interpolating the slower accelerometer stream onto gyro timestamps — synthesized stamps carrying interpolated values. The copy mode exists for exactly this problem: VIO pipelines need steadier input, so copy publishes each united message against a raw gyro sample, without interpolation, at the gyro rate you configured. Both are wrapper parameters that live in your launch file beside gyro_fps and accel_fps, for example unite_imu_method:=copy.
Set expectations correctly: none of these settings un-batches USB delivery. The burst shape in the arrival times stays, because it comes from the transfer schedule. What improves is the semantics of each message — real stamps instead of interpolated ones, and frames aligned where you asked for alignment. enable_sync gathers the closest frames of different sensors under one time tag, which helps when your pipeline wants depth and motion stamped together; test it with and against global_time_enabled, one change at a time.
Do SDK and firmware versions change IMU delivery?
Yes: run a firmware and SDK pairing that the vendor lists for your wrapper generation, because a mismatched triple of camera firmware, SDK runtime and wrapper release is a known source of stream faults, and a wrapper whose development has stopped will never be updated for newer SDKs.
The tell-tale signs live in the start-up log: the runtime the wrapper was built against, the runtime it actually loaded, and a camera firmware that targets a newer runtime than the installed one. Vendors pair each firmware line with the SDK versions that support it, and running ahead of your runtime produces exactly this class of oddity — grouped messages, transfer warnings, occasional stalls — that looks like a sensor fault. The fix is unglamorous and reliable: install the pairing from the vendor's compatibility table, not the newest release.
Wrapper generations matter as much as versions. A wrapper line whose development has stopped will not chase newer SDKs, so on an older Linux release the older pairing is the supported one and the newest SDK is the wrong one. For the procedure, see the SDK version check to run before blaming the cable and the firmware and SDK alignment fix.
Driver warnings belong in the same check. A message such as control_transfer returned error with Resource temporarily unavailable (errno 11) means the host's transfer came back busy and will be retried — evidence of a busy endpoint, not of a dying sensor. Log those warnings with host timestamps and check whether they sit on the burst boundaries.
How should you timestamp IMU data for VIO?
Integrate on the hardware timestamp inside each message, never on host arrival time: arrival is bursty by design, while the stamp records when the sample actually happened, and that is the quantity your filter's integrator consumes.
A stream that logs a hardware-clock time domain, with the note that timestamps may reset periodically, is telling you its stamps come from the camera's own counter. That clock is the right one for fusion — far better than host receive times — with one failure mode: resets.
If your filter assumes a fixed step, resample on the host after recording, with the hardware stamps as truth: interpolate onto a 1 / 400 Hz = 2.5 ms grid and the filter sees uniform steps. Check the stamps are complete first, then resample. To carry samples from sensor axes into the platform frame, follow the IMU optical frame transform check.
Keep the recording itself robust: capture the raw streams the way the ROS image transport recording guide describes, and do the rate verification offline by reading every frame from the bag rather than trusting the live topic.
When is uneven delivery a real fault you must fix?
Call delivery faulty only when the window count fails or the hardware stamps themselves show holes: a measured rate below roughly 99% of configured, repeated multi-sample gaps between stamps, or bursts that start the moment another stream joins the cable.
Work down the causes in this order:
- Transport batching — not a fault. Test: the 10-second window count. Fix: none; integrate on hardware stamps.
- Wrapper and firmware mismatch. Test: compare camera firmware, SDK runtime and wrapper release against the vendor's compatibility table. Fix: install the pairing from that table.
- Bus contention from parallel streams. Test: record the IMU alone, add depth, then infra, and run the count after each addition; confirm the start-up log negotiates USB 3.x. Fix: a shorter cable in good condition, a different root port, or fewer streams. The stream-mode interactions are the same ones behind low frame rate on software trigger.
- A recorder that cannot keep up. Test: run the read loop with no sleep and no queue, then compare counts. Fix: tighten the loop or record to faster storage.
Make the window count part of every new rig's bring-up, keep the three version numbers on a card at the bench, and budget the streams on one cable before adding the next sensor. Ten seconds of counting settles most of the IMU rate cases that reach us.
Which depth camera should you pick when the IMU matters most?
Treat the IMU as a first-class sensor when you specify the camera: ask the maker for the unit's native output rate, its timestamp domain, and whether the SDK publishes raw per-sample messages, then choose between the built-in unit and an external IMU before the rig exists.
The escalation integrators use in practice: when an estimator needs tighter per-sample consistency than a camera's bus-time delivery provides, mount a dedicated external IMU on the platform, time-align it with the camera through one clock, and let the depth camera continue doing geometry, with the built-in unit left running as a cross-check. For the sensor, lens and IMU trade-offs on the camera side, see VIO camera module components.
Our 3D sensors range covers laser profilers, stereo and structured-light cameras and ToF units, and the camera finder filters it by type and resolution. Two depth cameras from that range:
- Type
- Depth / ToF camera
- Type
- Stereo / structured light
The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.
For the wider system view — cameras, controllers, mounts and the rest of the cell — the 3D learning topic collects the guides, and the contact page reaches the applications team when a stream still fights you after the window count comes back clean.
Questions
Does lowering the gyro rate fix batched IMU delivery?
No. Tests at 200 Hz gyro and 63 Hz acceleration show the same grouped pattern, because the grouping follows the USB transfer schedule rather than the sensor clock. Lower rates shrink bandwidth and can reduce contention, but the burst shape stays. Judge any change by counting samples over a 10-second window, not by how evenly spaced the arrivals look in the live topic.
How many IMU samples should a one-minute recording contain at 400 Hz?
About 24,000: 400 samples per second for 60 seconds is 400 × 60 = 24,000 messages. A healthy stream lands within roughly 1% of that, so between 23,760 and 24,240. Count them by reading the bag offline rather than watching the live publisher, because host-side publication adds its own spacing artifacts on top of the USB batching.
What does the hardware clock warning mean for long recordings?
The warning that the frame time domain is a hardware clock which may reset periodically tells you the stamps come from the camera's internal counter, not the host clock. If a reset happens mid-recording, stamps jump backwards and a filter integrator will blend two time bases. Split recordings at any stamp discontinuity, and check for resets before fusing.
Should I add an external IMU for VIO instead of the camera's built-in one?
When your estimator needs tighter per-sample consistency than the camera stream provides, yes: a dedicated external IMU on the robot, time-aligned with the camera, is the path many integrators take, while the depth camera continues to supply geometry. Keep the camera's IMU running as a fallback, and align both streams through one clock before fusion.
Can I combine accelerometer and gyro streams without distorting the timing?
Yes, if the unite method copies instead of interpolating. Copy mode publishes each united message against a real gyro timestamp, while linear interpolation synthesizes stamps by resampling the slower acceleration stream onto gyro times. For visual-inertial odometry the copy mode is the stability-oriented choice, and the gyro rate you configured sets the united message rate.

