Skip to content

Commit fd60c10

Browse files
committed
Don't throw when writing back a keyframe the fixed-lag smoother marginalized
process_pending_gtsam_updates()'s write-back loop iterated every keyframe in state_.last_estimated_states and read its T/V/W variables out of the optimizer's Values unconditionally. This is a fixed-lag smoother: once a keyframe leaves the lag window it is marginalized out and its variables go with it, so at() threw Attempting to at the key "tNNN", which does not exist in the Values. The caller treats that as fatal ("Discarding incoming observations: a fatal error ocurred above"), so the run stopped mid-sequence and dropped every later observation while still exiting 0 -- leaving a short trajectory whose APE looked good because it covered only the easy opening. Seen on two datasets, and it needs a sequence long enough to fill the lag window, which is why no keyed CI dataset trips it: - Newer College 2020 01_short_experiment: key t3478, ~14% in, 11% GT coverage and a flattering 0.26 m APE. - GEODE Offroad1_gamma: key t335, ~7.5% in, 295 of 4049 scans and a flattering 0.383 m. Skipping such an entry is the correct behavior rather than merely the safe one: it already holds the last estimate the smoother produced before marginalizing, which is that keyframe's final value. There is nothing newer to write back. Offroad1_gamma now runs to completion: 4039 poses instead of 295, 99.9% GT coverage instead of 7%, est/gt path ratio 1.007, and an honest 1.303 m APE against the beta arm's 1.282 m on the same trajectory.
1 parent a88a01e commit fd60c10

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

mola_state_estimation_smoother/src/StateEstimationSmoother.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,25 @@ void StateEstimationSmoother::process_pending_gtsam_updates_locked()
21842184
const auto tleWriteback = mola::ProfilerEntry(profiler_, "process_pending.writeback");
21852185
for (auto& [kfIdx, kf] : state_.last_estimated_states)
21862186
{
2187+
// This is a FIXED-LAG smoother: once a keyframe leaves the lag
2188+
// window it is marginalized out, and its T/V/W variables leave
2189+
// optValues with it. Reading them unconditionally threw
2190+
// "Attempting to at the key tNNN, which does not exist in the
2191+
// Values", and since the caller treats that as fatal, the whole
2192+
// run stopped mid-sequence and discarded every later
2193+
// observation. Seen on Newer College 2020 (t3478, ~14% in) and
2194+
// on GEODE Offroad1_gamma (t335, ~7.5% in).
2195+
//
2196+
// Skipping is the right behavior rather than merely the safe
2197+
// one: such an entry already holds the last estimate the
2198+
// smoother produced for it before marginalizing, which IS that
2199+
// keyframe's final value. There is nothing newer to write.
2200+
if (!optValues.exists(T(kfIdx)) || !optValues.exists(V(kfIdx)) ||
2201+
!optValues.exists(W(kfIdx)))
2202+
{
2203+
continue;
2204+
}
2205+
21872206
const auto pose = optValues.at<gtsam::Pose3>(T(kfIdx));
21882207
const auto linV = optValues.at<gtsam::Vector3>(V(kfIdx));
21892208
const auto angV = optValues.at<gtsam::Vector3>(W(kfIdx));

0 commit comments

Comments
 (0)