Skip to content

Odom anchor sets - #278

Merged
apirrone merged 2 commits into
mainfrom
odom-anchor-sets
Sep 13, 2026
Merged

Odom anchor sets#278
apirrone merged 2 commits into
mainfrom
odom-anchor-sets

Conversation

@apirrone

Copy link
Copy Markdown
Contributor

Odometry: anchor points sampled on the alpha sole mesh, 16-point grid by default

The contact odometry picks its ground anchor from a set of candidate points on each sole, expressed in the foot-site frame. Since the port those were four hardcoded corners: the v1.5 sole bbox, ±27.0 × ±20.6 mm on the site's Z = 0 plane, flagged as a placeholder and never measured.

The alpha sole does not look like that. In the site frame it spans X [-20, +34] mm (54 mm long, 7 mm forward of the site), Y ±21 mm, and its bottom is canted 4.9° about X. The old corners float 2 mm above the real contact on one side and sit inside the sole on the other, and the robot stands 2 to 4 mm taller than it is.

What changes

  • odometry/src/anchors.rs is generated by microduck_rl/scripts/odom_anchor_points.py (PR pollen-robotics/microduck_rl#), which shoots a vertical ray through each sample point and keeps the lowest triangle of the sole collision mesh. Each foot is sampled on its own mesh. Three sets:
    • V15: the legacy corners, unchanged.
    • ALPHA4: the four corners of the flat contact patch, on the mesh.
    • ALPHA16: a 4×4 grid over the whole footprint, bevels included, on the mesh.
  • Odometry::new takes an &'static AnchorSet; alpha_with(&SET) picks one; Odometry::alpha() now runs ALPHA16. robotd needs no change.
  • Tests: the generated sets must lie on the sole and mirror between feet; an ignored timing test and an ignored reference-trajectory dump (used to validate the Python replica in microduck_rl, which matches to 27 µm with identical anchor-foot decisions).

Why 16 points

Measured in the MuJoCo twin with infer_policy --odom-compare (perfect IMU, so only the contact geometry differs), 3.2 m of keyboard-driven walking over 23.8 s:

set pts/foot final xy err max xy err xy err / path final z err
v15 4 17.3 mm 24.5 mm 0.5 % +3.7 mm
alpha4 4 15.6 mm 21.6 mm 0.5 % +0.9 mm
alpha16 16 9.1 mm 19.7 mm 0.3 % +0.5 mm

The sole is rounded, so when the foot pitches the contact rolls onto the bevel; four corners on the flat patch cannot follow that, the grid can.

Cost

cargo test -p odometry --release -- --ignored --nocapture update_cost_per_anchor_set, x86 laptop:

set ns per update
4 points 484
16 points 951

On the Zero 3's A55 expect a few µs per 20 ms tick. Negligible.

Checks

fmt, test, clippy, cargo board -p robotd all pass. Not yet validated on the robot: the sim used rigid feet, and the PU sole's compliance may shift the numbers.

🤖 Generated with Claude Code

apirrone and others added 2 commits September 13, 2026 14:19
The contact odometry picked its anchor from four hardcoded corners: the
v1.5 sole bbox, ±27.0 x ±20.6 mm on the foot-site Z = 0 plane, a placeholder
since the port. The alpha sole is 54 mm long, sits 7 mm forward of the
site, and its bottom is canted 4.9° about X in the site frame, so those
corners float 2 mm above the real contact on the low side and 3 mm under
the mesh on the high side.

`anchors.rs` is GENERATED by microduck_rl/scripts/odom_anchor_points.py,
which drops a grid of vertical rays onto the sole collision mesh:

  V15      the legacy corners (unchanged behaviour)
  ALPHA4   the flat contact patch's four corners, on the mesh
  ALPHA16  a 4x4 grid over the whole footprint, bevels included

`Odometry` takes an `&'static AnchorSet`; `Odometry::alpha()` still uses
V15, so robotd is unchanged until the sets have been compared (infer_policy
--odom-compare in microduck_rl). `alpha_with(&ALPHA16)` is the switch.

Cost, `update_cost_per_anchor_set` on an x86 laptop: 484 ns per update
with 4 points per foot, 951 ns with 16. On the Zero 3's A55 expect a
handful of µs — nothing next to a 20 ms tick.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ZPSQ6nCsfqannMDXwAKZ3
Measured in the MuJoCo twin (infer_policy --odom-compare, perfect IMU,
3.2 m of keyboard-driven walking, 23.8 s):

  set      final xy err  max xy err  final z err
  v15         17.3 mm      24.5 mm     +3.7 mm
  alpha4      15.6 mm      21.6 mm     +0.9 mm
  alpha16      9.1 mm      19.7 mm     +0.5 mm

Odometry::alpha() now runs the 16-point grid. V15 and ALPHA4 stay as
named sets for alpha_with() and the cost/reference tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ZPSQ6nCsfqannMDXwAKZ3
@github-actions

Copy link
Copy Markdown

Coverage

71.59% lines on this branch, against a floor of 70%.

Per-file
Filename                              Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
btd/src/adv.rs                             79                 0   100.00%           9                 0   100.00%          42                 0   100.00%           0                 0         -
btd/src/bluez.rs                          482               482     0.00%          34                34     0.00%         314               314     0.00%           0                 0         -
btd/src/chorale.rs                        346               246    28.90%          23                13    43.48%         230               171    25.65%           0                 0         -
btd/src/framing.rs                        253                 9    96.44%          20                 1    95.00%         120                 5    95.83%           0                 0         -
btd/src/gatt.rs                             3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
btd/src/link.rs                            24                 0   100.00%           3                 0   100.00%          26                 0   100.00%           0                 0         -
btd/src/main.rs                            77                77     0.00%          11                11     0.00%          77                77     0.00%           0                 0         -
btd/src/pairing.rs                        149                 2    98.66%          12                 1    91.67%          81                 1    98.77%           0                 0         -
btd/src/route.rs                          352                32    90.91%          27                 0   100.00%         351                11    96.87%           0                 0         -
btd/src/session.rs                       1218                73    94.01%          71                 5    92.96%         706                41    94.19%           0                 0         -
btd/src/upstream.rs                       397                35    91.18%          34                 8    76.47%         241                19    92.12%           0                 0         -
configd/src/bluez.rs                      586               498    15.02%          85                79     7.06%         375               326    13.07%           0                 0         -
configd/src/identity.rs                   111                 5    95.50%          12                 1    91.67%          52                 3    94.23%           0                 0         -
configd/src/logs.rs                       314                33    89.49%          31                 3    90.32%         219                36    83.56%           0                 0         -
configd/src/main.rs                       515               515     0.00%          38                38     0.00%         345               345     0.00%           0                 0         -
configd/src/net.rs                        246                12    95.12%          38                 2    94.74%         181                 4    97.79%           0                 0         -
configd/src/nm.rs                         271               213    21.40%          43                39     9.30%         171               120    29.82%           0                 0         -
configd/src/pad.rs                        379                13    96.57%          38                 2    94.74%         222                 8    96.40%           0                 0         -
configd/src/power.rs                       30                30     0.00%           6                 6     0.00%          28                28     0.00%           0                 0         -
configd/src/store.rs                      350                25    92.86%          28                 2    92.86%         173                 9    94.80%           0                 0         -
configd/src/units.rs                      183               116    36.61%          24                18    25.00%         116                79    31.90%           0                 0         -
duck-control/src/bus.rs                   587               452    23.00%          52                37    28.85%         394               307    22.08%           0                 0         -
duck-control/src/fall.rs                  173                 0   100.00%          15                 0   100.00%         108                 0   100.00%           0                 0         -
duck-control/src/imu.rs                   370                 8    97.84%          20                 0   100.00%         195                 5    97.44%           0                 0         -
duck-control/src/io.rs                    134                19    85.82%          21                 5    76.19%         120                17    85.83%           0                 0         -
duck-control/src/model.rs                 120                 1    99.17%          15                 0   100.00%          73                 0   100.00%           0                 0         -
duck-control/src/obs.rs                   263                 6    97.72%          24                 2    91.67%         177                 8    95.48%           0                 0         -
duck-control/src/policy.rs                701               560    20.11%          67                47    29.85%         452               347    23.23%           0                 0         -
duck-control/src/safety.rs                450                13    97.11%          33                 2    93.94%         292                 6    97.95%           0                 0         -
duck-control/src/sim.rs                   426                63    85.21%          32                10    68.75%         233                40    82.83%           0                 0         -
duck-detect/src/bin/duck-bench.rs         306               306     0.00%          16                16     0.00%         170               170     0.00%           0                 0         -
duck-detect/src/lib.rs                    641                15    97.66%          27                 0   100.00%         333                 8    97.60%           0                 0         -
duck-detect/src/onnx.rs                    96                96     0.00%           5                 5     0.00%          52                52     0.00%           0                 0         -
duck-detect/src/rknn.rs                   267               237    11.24%          15                11    26.67%         216               195     9.72%           0                 0         -
duck-ether/src/main.rs                    504               404    19.84%          27                16    40.74%         270               217    19.63%           0                 0         -
duck-ipc-proto/src/lib.rs                2089               163    92.20%         133                13    90.23%        1530                88    94.25%           0                 0         -
duckctl/src/main.rs                      2617              1023    60.91%         156                45    71.15%        1629               654    59.85%           0                 0         -
kinematics/src/hand.rs                    394                 2    99.49%          22                 2    90.91%         181                 2    98.90%           0                 0         -
kinematics/src/head.rs                    392                 9    97.70%          22                 0   100.00%         193                 4    97.93%           0                 0         -
kinematics/src/lib.rs                     348                10    97.13%          23                 1    95.65%         174                 7    95.98%           0                 0         -
kinematics/src/math.rs                    171                 0   100.00%          16                 0   100.00%          79                 0   100.00%           0                 0         -
kinematics/src/mjcf.rs                    233                32    86.27%          17                 1    94.12%         134                15    88.81%           0                 0         -
kinematics/src/tof.rs                     338                17    94.97%          14                 0   100.00%         184                10    94.57%           0                 0         -
mediad/src/camera.rs                      291                 5    98.28%          21                 0   100.00%         204                 5    97.55%           0                 0         -
mediad/src/config.rs                       87                 5    94.25%           7                 1    85.71%          46                 4    91.30%           0                 0         -
mediad/src/detect.rs                      293               222    24.23%          13                 9    30.77%         200               145    27.50%           0                 0         -
mediad/src/exposure.rs                    412               161    60.92%          28                 8    71.43%         279               110    60.57%           0                 0         -
mediad/src/main.rs                        376               376     0.00%          10                10     0.00%         254               254     0.00%           0                 0         -
mediad/src/pipeline.rs                   1622              1410    13.07%         108                86    20.37%        1051               905    13.89%           0                 0         -
mediad/src/producer.rs                    161                33    79.50%          20                 5    75.00%         109                20    81.65%           0                 0         -
mediad/src/relay.rs                      2217               234    89.45%         179                28    84.36%        1448               171    88.19%           0                 0         -
mediad/src/route.rs                       180                19    89.44%          12                 0   100.00%         155                 8    94.84%           0                 0         -
mediad/src/session.rs                     671                21    96.87%          37                 0   100.00%         427                18    95.78%           0                 0         -
mediad/src/stream.rs                      826               129    84.38%          55                 9    83.64%         521                87    83.30%           0                 0         -
mediad/src/turn.rs                        420                31    92.62%          39                 3    92.31%         254                16    93.70%           0                 0         -
mediad/src/upstream.rs                    263                16    93.92%          17                 1    94.12%         160                12    92.50%           0                 0         -
mediad/src/web.rs                         119                26    78.15%          15                 4    73.33%          82                17    79.27%           0                 0         -
odometry/src/anchors.rs                     5                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
odometry/src/lib.rs                       445                80    82.02%          28                 5    82.14%         254                50    80.31%           0                 0         -
pad-imu/src/lib.rs                        608                 7    98.85%          39                 0   100.00%         372                 5    98.66%           0                 0         -
padd/src/main.rs                         1088               606    44.30%          36                13    63.89%         664               417    37.20%           0                 0         -
padd/src/tap.rs                          1253               682    45.57%          73                36    50.68%         767               407    46.94%           0                 0         -
pet-detect/src/bin/detect.rs               61                61     0.00%           1                 1     0.00%          38                38     0.00%           0                 0         -
pet-detect/src/bin/features.rs             46                46     0.00%           2                 2     0.00%          20                20     0.00%           0                 0         -
pet-detect/src/lib.rs                     362               184    49.17%          27                13    51.85%         224               122    45.54%           0                 0         -
pet-detect/src/worker.rs                  381               230    39.63%          24                14    41.67%         276               160    42.03%           0                 0         -
robotctl/src/configure.rs                1596               477    70.11%          61                12    80.33%         820               322    60.73%           0                 0         -
robotctl/src/duck.rs                     1211               144    88.11%          63                 1    98.41%         604                47    92.22%           0                 0         -
robotctl/src/imu_view.rs                  266                25    90.60%          19                 2    89.47%         173                19    89.02%           0                 0         -
robotctl/src/main.rs                     5141              2779    45.94%         282               131    53.55%        3497              1885    46.10%           0                 0         -
robotctl/src/monitor.rs                  4308               748    82.64%         222                36    83.78%        2721               477    82.47%           0                 0         -
robotctl/src/path_map.rs                  425                59    86.12%          24                 2    91.67%         223                36    83.86%           0                 0         -
robotctl/src/show.rs                      714                46    93.56%          31                 1    96.77%         509                25    95.09%           0                 0         -
robotd-params/src/edit.rs                1904               120    93.70%         114                14    87.72%         929                52    94.40%           0                 0         -
robotd-params/src/lib.rs                 1976                95    95.19%         182                 9    95.05%        1414                55    96.11%           0                 0         -
robotd-params/src/registry.rs             193                10    94.82%          15                 2    86.67%         144                17    88.19%           0                 0         -
robotd/src/chorale.rs                    1366                30    97.80%          71                 4    94.37%         826                20    97.58%           0                 0         -
robotd/src/control.rs                     450               411     8.67%          29                24    17.24%         355               307    13.52%           0                 0         -
robotd/src/intents.rs                     419                74    82.34%          48                 9    81.25%         308                49    84.09%           0                 0         -
robotd/src/main.rs                       7308              1611    77.96%         356                54    84.83%        4724              1028    78.24%           0                 0         -
robotd/src/soc.rs                          47                25    46.81%           4                 1    75.00%          30                15    50.00%           0                 0         -
robotd/src/sound.rs                       968               692    28.51%          50                34    32.00%         565               420    25.66%           0                 0         -
robotd/src/theremin.rs                    472               112    76.27%          32                12    62.50%         271                64    76.38%           0                 0         -
sounds/src/chorale/beat.rs                403                16    96.03%          26                 1    96.15%         246                12    95.12%           0                 0         -
sounds/src/chorale/midi.rs               1047                80    92.36%          44                 2    95.45%         581                43    92.60%           0                 0         -
sounds/src/chorale/mod.rs                1423                57    95.99%          83                 3    96.39%         812                41    94.95%           0                 0         -
sounds/src/chorale/text.rs                700                60    91.43%          41                12    70.73%         376                17    95.48%           0                 0         -
sounds/src/lib.rs                         167                35    79.04%          14                 6    57.14%          87                21    75.86%           0                 0         -
sounds/src/main.rs                        463               463     0.00%          20                20     0.00%         240               240     0.00%           0                 0         -
sounds/src/personality.rs                 174                 0   100.00%           6                 0   100.00%          84                 0   100.00%           0                 0         -
sounds/src/rng.rs                         173                 0   100.00%          18                 0   100.00%          96                 0   100.00%           0                 0         -
sounds/src/stream.rs                      719                 7    99.03%          46                 1    97.83%         420                 6    98.57%           0                 0         -
sounds/src/synth.rs                       353                 7    98.02%          29                 0   100.00%         197                 3    98.48%           0                 0         -
sounds/src/voices.rs                      679                 2    99.71%          26                 0   100.00%         353                 2    99.43%           0                 0         -
test-support/src/lib.rs                   272                 2    99.26%          22                 0   100.00%         167                 0   100.00%           0                 0         -
tof/src/config.rs                          42                 8    80.95%           4                 1    75.00%          23                 7    69.57%           0                 0         -
tof/src/imu.rs                            223               153    31.39%          10                 5    50.00%         137                93    32.12%           0                 0         -
tof/src/lib.rs                             88                 0   100.00%           9                 0   100.00%          54                 0   100.00%           0                 0         -
tof/src/main.rs                           770               687    10.78%          37                26    29.73%         481               437     9.15%           0                 0         -
tof/src/sensor.rs                         230               148    35.65%          22                15    31.82%         163               114    30.06%           0                 0         -
tof/src/status.rs                          76                 2    97.37%           7                 1    85.71%          58                 1    98.28%           0                 0         -
updater/src/account.rs                     87                 0   100.00%           9                 0   100.00%          76                 0   100.00%           0                 0         -
updater/src/config.rs                     436                24    94.50%          38                 4    89.47%         354                17    95.20%           0                 0         -
updater/src/engine.rs                    3265               499    84.72%         217                29    86.64%        2117               313    85.21%           0                 0         -
updater/src/faults.rs                      69                 7    89.86%           7                 0   100.00%          51                 0   100.00%           0                 0         -
updater/src/fsutil.rs                     104                30    71.15%          10                 6    40.00%          51                24    52.94%           0                 0         -
updater/src/hooks.rs                      454                15    96.70%          37                 2    94.59%         382                12    96.86%           0                 0         -
updater/src/ipc.rs                        925               333    64.00%          67                20    70.15%         569               179    68.54%           0                 0         -
updater/src/journal.rs                    832                78    90.62%          57                10    82.46%         483                53    89.03%           0                 0         -
updater/src/lib.rs                         55                16    70.91%           5                 0   100.00%          41                14    65.85%           0                 0         -
updater/src/main.rs                       550               222    59.64%          38                14    63.16%         420               151    64.05%           0                 0         -
updater/src/manifest.rs                   159                 6    96.23%          16                 0   100.00%         110                 1    99.09%           0                 0         -
updater/src/orphan.rs                     288                 6    97.92%          25                 0   100.00%         181                 3    98.34%           0                 0         -
updater/src/policy.rs                    1549               599    61.33%         124                52    58.06%         830               344    58.55%           0                 0         -
updater/src/preflight.rs                  382                16    95.81%          47                 4    91.49%         284                11    96.13%           0                 0         -
updater/src/reconcile.rs                  292                15    94.86%          25                 3    88.00%         172                 5    97.09%           0                 0         -
updater/src/robot.rs                      225                33    85.33%          37                10    72.97%         139                21    84.89%           0                 0         -
updater/src/source/github.rs              474               169    64.35%          51                26    49.02%         304                99    67.43%           0                 0         -
updater/src/source/hf_hub.rs              136                72    47.06%          20                12    40.00%          81                41    49.38%           0                 0         -
updater/src/source/http.rs                319                82    74.29%          29                11    62.07%         260                88    66.15%           0                 0         -
updater/src/source/local.rs               346                37    89.31%          36                 9    75.00%         192                26    86.46%           0                 0         -
updater/src/source/mod.rs                  39                30    23.08%           4                 2    50.00%          30                24    20.00%           0                 0         -
updater/src/spawn.rs                       94                13    86.17%           5                 0   100.00%          49                 4    91.84%           0                 0         -
updater/src/store.rs                      593                41    93.09%          43                 7    83.72%         271                42    84.50%           0                 0         -
updater/src/transcript.rs                 518                42    91.89%          31                 3    90.32%         290                22    92.41%           0                 0         -
updater/src/unix.rs                        44                 3    93.18%           3                 0   100.00%          22                 2    90.91%           0                 0         -
updater/src/verify.rs                     786                95    87.91%          55                18    67.27%         424                75    82.31%           0                 0         -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                   79959             22104    72.36%        5255              1407    73.23%       49941             14186    71.59%           0                 0         -

@apirrone
apirrone merged commit e9cca62 into main Sep 13, 2026
4 checks passed
@apirrone
apirrone deleted the odom-anchor-sets branch September 13, 2026 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant