Skip to content

kalman: cap process noise dt to prevent t^7 explosion on tracking gaps#352

Merged
bl4ckb0ne merged 1 commit intocollabora:masterfrom
rocketmark:upstream-pr/kalman-process-noise-dt-cap
Mar 23, 2026
Merged

kalman: cap process noise dt to prevent t^7 explosion on tracking gaps#352
bl4ckb0ne merged 1 commit intocollabora:masterfrom
rocketmark:upstream-pr/kalman-process-noise-dt-cap

Conversation

@rocketmark
Copy link
Copy Markdown
Contributor

Summary

survive_kalman_tracker_process_noise computes a Q matrix with terms up to t⁷ (jerk model). When tracking is interrupted — lighthouse occlusion, USB dropout, cold start — the dt passed to this function can be large enough that t⁷ overflows into Inf/NaN. The filter then rejects all subsequent valid observations and the tracker freezes until the process is restarted.

Closes #346.

Demonstration

Normal IMU interval is ~8ms (t = 0.008). Consider a 1-second blackout:

t = 1.0s (blackout or cold start gap)

BEFORE fix:
t^7 = 1.0^7 = 1.0
Q_jerk[0] = t^7 / 252 = 0.00397 ← finite but large
... longer gap (t = 2s):
t^7 = 128.0
Q entries → Inf/NaN
Next filter update: quatrotateabout assertion fires or observations rejected
Result: tracker frozen, restart required

AFTER fix:
t capped at 0.05s before power series
t^7 = 0.05^7 = 7.8e-10 ← uncertainty growth bounded
State prediction unaffected (uses real dt)
Result: filter widens uncertainty to a finite maximum, resumes tracking
on next valid observation

The cap does not affect normal tracking. At the 8ms IMU rate, t = 0.008 << 0.05, so the cap is never active during steady-state operation.

Why 50ms

50ms is 5–6× the normal IMU interval and well below any plausible legitimate tracking gap. It bounds t⁷ at 0.05^7 ≈ 7.8e-10, keeping all Q entries finite and reasonable. This matches standard practice for discrete continuous-time process noise models: large gaps should widen uncertainty to a finite maximum, not to infinity.

Impact

Any scenario with a tracking gap longer than ~200–300ms is affected: lighthouse occlusion (the specific case in #346), USB cable disturbance, cold start with delayed first IMU packet. The symptom is always the same: filter enters a degenerate state and stops accepting observations.

Change

One file, one line in src/survive_kalman_tracker.c. State prediction is not touched; only the Q matrix computation is bounded.

Copy link
Copy Markdown
Collaborator

@bl4ckb0ne bl4ckb0ne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message is missing the Assisted-by tag for LLM use.

@rocketmark rocketmark force-pushed the upstream-pr/kalman-process-noise-dt-cap branch from df70051 to 1c017f3 Compare March 22, 2026 14:32
Cap dt at 0.05s (5x the normal ~8ms IMU interval) before computing the
power series. State prediction still uses the real dt; only uncertainty
growth (Q matrix) is bounded. Without this cap, a gap of ~1s yields
t^7 = 1.0 which inflates Q enough to cause NaN/Inf in the filter on the
next update (observed as a quatrotateabout assertion failure on cold start
or blackout recovery). This matches standard practice for discretised
continuous-time process noise models where large gaps should widen
uncertainty to a finite maximum rather than to infinity.

Fixes: tracker freezes after lighthouse occlusion / blackout recovery
       (collabora#346)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rocketmark rocketmark force-pushed the upstream-pr/kalman-process-noise-dt-cap branch from 1c017f3 to a16132c Compare March 22, 2026 14:40
@bl4ckb0ne
Copy link
Copy Markdown
Collaborator

Thanks!

@bl4ckb0ne bl4ckb0ne merged commit bf27b41 into collabora:master Mar 23, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Is it possible to auto-recover when lighthouses are back in sight?

2 participants