Skip to content

Commit 21a06dc

Browse files
committed
Keep the relative formulation opt-in, and resize the test gate it exposed
Two findings from measuring rather than assuming, both of which argue against turning this on by default. 1. It costs geo-referencing. test-navstate-odom-gnss-fusion's ENU->map rotation error grows to 5.69 deg against that test's 5.0 deg gate, where the absolute-only formulation stays inside it. The mechanism is plausible: that yaw is observed by comparing GNSS motion in ENU against odometry-derived motion in map, and asserting the dead-reckoned pose absolutely, however weakly, is what makes it well observed. A relative-only chain with a single anchor does not. 2. The APE gain it buys is being paid for on a configuration that is not recommended anyway. On the seven BotanicGarden sequences this formulation is better than the absolute-only one on 5 of 7 -- but with everything else held fixed, fusing that platform's wheel odometry AT ALL is worse than ignoring it on 6 of 7. Bad odometry stays bad however correctly it is weighted. So: default off, documented as a trade with both numbers, and the guidance is to enable it when fusing wheel odometry without estimating geo-referencing. Separately, MAXIMUM_SE3_FINAL_ERROR moves 0.40 -> 0.45, and that one belongs to the covariance-accumulation commit rather than to this feature. The odometry that test simulates is noise-only -- no slip, no systematic error -- so trusting it more than the motion model says is free accuracy there, and the old threshold scored an over-confident implementation better than a correct one. Worst case across the same seven cases: 0.365 original: absolute pose fused with the LATEST INCREMENT's covariance 0.419 that covariance corrected to the accumulated dead-reckoning one 0.368 ...plus a relative factor per reading (restores part of the over-trust) 0.405 ...with the single anchor that formulation actually implies On real data the ranking inverts: the last of those is the best arm on BotanicGarden and the first DIVERGES on 7 of 7, estimating 4.5-6.8x the true path length. The fixture cannot discriminate a correct odometry weight from an over-confident one, so it must not gate that axis; it still earns its place as a regression guard on the fusion working at all, and the threshold is sized for that. The reasoning is recorded at the constant. colcon test: 34/34.
1 parent 212ff82 commit 21a06dc

3 files changed

Lines changed: 47 additions & 2 deletions

File tree

mola_state_estimation_smoother/include/mola_state_estimation_smoother/Parameters.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ class Parameters
219219
* A relative factor is skipped, rather than forced, when the previous
220220
* odometry keyframe has already been marginalized out: a factor on a
221221
* variable the smoother no longer holds would resurrect it as a free state.
222+
*
223+
* Off by default on a measured trade, not out of caution. It is the better
224+
* of the two ways to fuse on real data (BotanicGarden, better APE on 5 of 7
225+
* sequences than the absolute-only formulation), but it costs
226+
* geo-referencing: the ENU->map rotation error in
227+
* test-navstate-odom-gnss-fusion grows past that test's 5 deg gate, where
228+
* the absolute-only formulation stays inside it. Asserting the dead-reckoned
229+
* pose absolutely, however weakly, is apparently what makes that yaw well
230+
* observed. Enable this if you fuse wheel odometry and do not estimate
231+
* geo-referencing.
222232
*/
223233
bool odometry_relative_factors = false;
224234

mola_state_estimation_smoother/params/state-estimation-smoother.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,21 @@ params:
126126
# dead-reckoning covariance to be honest, which makes it nearly uninformative;
127127
# the relative one states what the reading actually measured, with the
128128
# covariance the motion model computes for it, and nothing accumulates.
129-
# Default off until measured on more than one platform.
129+
# OFF by default, and the reason is a measured trade rather than caution.
130+
#
131+
# On BotanicGarden -- the only dataset family in our evaluation corpus that
132+
# feeds wheel odometry, a skid-steer platform in dense vegetation -- this is
133+
# the better of the two ways to fuse: better APE on 5 of 7 sequences than the
134+
# absolute-only formulation. But test-navstate-odom-gnss-fusion shows it costs
135+
# geo-referencing: the ENU->map rotation error grows past its 5 deg gate
136+
# (5.69 deg), where the absolute-only formulation stays inside it. Asserting
137+
# the dead-reckoned pose absolutely, however weakly, is apparently what makes
138+
# that yaw well observed.
139+
#
140+
# And on that same platform, fusing wheel odometry AT ALL is worse than
141+
# ignoring it on 6 of 7 sequences, so the APE side of the trade is being paid
142+
# for on a configuration that is not recommended anyway. Enable this if you
143+
# fuse wheel odometry and do not estimate geo-referencing.
130144
odometry_relative_factors: ${MOLA_ODOM_RELATIVE_FACTORS|false}
131145

132146
# High-rate same-sensor decimation for IMU [seconds]. If > 0, readings

mola_state_estimation_smoother/tests/test-navstate-odom-gnss-fusion.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,28 @@ constexpr double MOTION_ANG_WZ = 0.5; // rad/s
4141
constexpr double ODOMETRY_NOISE_XY = 0.01;
4242
constexpr double ODOMETRY_NOISE_PHI = 0.1_deg;
4343

44-
constexpr double MAXIMUM_SE3_FINAL_ERROR = 0.40;
44+
// Raised from 0.40 on 2026-08-21, deliberately and with the measurements in
45+
// hand, because the old value gated the wrong thing.
46+
//
47+
// The odometry simulated below is noise-only: a zero-mean per-increment
48+
// perturbation, no slip and no systematic error. On such a source, trusting
49+
// wheel odometry MORE than the motion model says is free accuracy, so this test
50+
// scores an over-confident implementation better than a correct one. Same seven
51+
// cases, worst-case final_se3_error:
52+
//
53+
// 0.365 original: absolute pose fused with the LATEST INCREMENT's covariance
54+
// 0.419 that covariance corrected to the accumulated dead-reckoning one
55+
// 0.368 ...plus a relative factor per reading (restores part of the over-trust)
56+
// 0.405 ...with the single anchor that formulation actually implies
57+
//
58+
// On real data the ranking inverts: on the seven BotanicGarden sequences, which
59+
// have genuine wheel slip, the last of those is the best arm (0.87x the
60+
// lightweight estimator) and the first DIVERGES on 7 of 7, estimating 4.5-6.8x
61+
// the true path length. So this fixture cannot discriminate a correct odometry
62+
// weight from an over-confident one, and must not be used as the gate on that
63+
// axis. It still earns its place as a regression guard on the fusion working at
64+
// all; the threshold is sized for that.
65+
constexpr double MAXIMUM_SE3_FINAL_ERROR = 0.45;
4566
constexpr double MAXIMUM_ENU2MAP_ROTATION_ERROR = 5.0_deg;
4667

4768
constexpr const char* ODOMETRY_NAME = "odom";

0 commit comments

Comments
 (0)