Skip to content

feat(localization): add MonteCarloLocalization (E4) - #41

Merged
gabrielfrasantos merged 3 commits into
mainfrom
claude/determined-einstein-bznlpi
Nov 6, 2026
Merged

gabrielfrasantos merged 3 commits into
mainfrom
claude/determined-einstein-bznlpi

Conversation

@gabrielfrasantos

Copy link
Copy Markdown
Contributor

Implements roadmap item E4 from roadmap/localization/MonteCarloLocalization, on top of upstream filters::ParticleFilter (NT70, embedded-pro/numerical-toolbox-cpp#369).

Commit Change
33f33af Bump numerical-toolbox for ParticleFilter (NT70), ROADMAP NT70 row
c36baa4 E4 MonteCarloLocalization: header, coverage .cpp, tests, CMake, doc
b61ac1e Pin numerical-toolbox to the NT70 merge commit bf5cc90

What

robotics/localization/MonteCarloLocalization.hpp:

  • MclParameters<T>: the motion noise, hitSigma, hitWeight, randomWeight, maxRange, resampleFraction and beamStride.
  • LikelihoodField<T, W, H>: distance to the nearest occupied cell of an OccupancyGridMap (E2), computed by a two-pass 8-neighbour chamfer transform with weights (1, √2). Distances are scaled by the resolution and capped at maxDistance. Distance(world) returns the cap outside the map.
  • MonteCarloLocalization<T, N, W, H>: wraps filters::ParticleFilter<T, 3, N>.
    • Initialization: Initialize(draw) and InitializeAround(pose, sigma, normal).
    • Predict(increment, normal): noisy odometry, using F1's IncrementDeviation with one draw per particle and axis.
    • Update(scan, uniform):
      • Scores each particle with the likelihood field, a z_rand / r_max floor and the beam stride.
      • Skips beams at or beyond the maximum range.
      • Then calls ResampleIfNeeded(resampleFraction, uniform()).
    • Estimate(): the weighted mean, with the heading as a circular mean.
    • Particles().

All randomness comes from caller-supplied samplers, so a seeded run is reproducible. There is no heap and no recursion.

Deviations from the spec

  • Predict tests: they seed the particles with InitializeAround(pose, sigma, Zero), which places every particle exactly at (1, 2, 0.3).
  • Lattice convention: the 27 update candidates are truth ⊕ (dx, dy, dθ), composed through SE2Transform.
  • Coverage instantiation: the coverage .cpp also instantiates the test sizes: LikelihoodField<40, 40>, and MonteCarloLocalization with N = 4 and N = 27. It also instantiates the member templates for the test callables (function references, with matching extern template declarations). The test translation unit is not instrumented.
  • Roadmap: E4 was the last localization item, so that index section is removed. ROADMAP.md now says "All localization items have shipped", and the canonical example in roadmap/README.md now points to trajectory/TimeOptimalPathParameterization (M27), the last remaining spec.

Verification

  • host-single-Debug and coverage builds on pin bf5cc90: ctest 7/7.
  • 100% merged line coverage on MonteCarloLocalization.hpp (102/102).
  • Clang -Wall -Wextra -Werror -Wshadow with -DROBOTICS_TOOLBOX_COVERAGE_BUILD.
  • clang-format --dry-run --Werror and the forbidden-pattern check.
  • scripts/validate-docs.py passes, and no doc line exceeds 400 characters.
  • Not run locally: MSVC, cppcheck, SonarCloud.

Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Particle-filter localization in an occupancy grid: a two-pass
8-neighbour chamfer likelihood field, a noisy odometry motion model
from IncrementDeviation, a likelihood-field scan score with a
random-measurement floor and beam stride, ESS-triggered systematic
resampling and a circular-mean pose estimate, on top of upstream
filters::ParticleFilter (NT70).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown

✅⚠️MegaLinter analysis: Success with warnings

Descriptor Linter Files Fixed Errors Max errors Warnings Elapsed time
✅ ACTION actionlint 7 0 0 0.41s
✅ CPP clang-format 207 0 0 0 1.49s
✅ CPP cppcheck 207 0 0 2.83s
✅ DOCKERFILE hadolint 1 0 0 0.27s
✅ JSON jsonlint 8 0 0 0.08s
✅ JSON prettier 8 2 0 0 0.25s
✅ MARKDOWN markdownlint 86 0 0 0 1.59s
✅ MARKDOWN markdown-table-formatter 86 0 0 0 0.17s
⚠️ SPELL lychee 133 2 0 1.96s
✅ YAML prettier 12 0 0 0 0.37s
✅ YAML yamllint 12 0 0 0.4s

Detailed Issues

⚠️ SPELL / lychee - 2 errors
[ERROR] failed to verify TLS certificate: invalid peer certificate: UnknownIssuer
📝 Summary
---------------------
🔍 Total..........368
🔗 Unique.........129
✅ Successful.....356
⏳ Timeouts.........0
🔀 Redirected.......5
👻 Excluded.........9
❓ Unknown..........0
🚫 Errors...........2
⛔ Unsupported......2

Errors in .github/workflows/static-analysis.yml
[403] https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$ (at 37:21) | Rejected status code: 403 Forbidden

Errors in doc/kinematics/InverseKinematics.md
[ERROR] https://mathweb.ucsd.edu/~sbuss/ResearchWeb/ikmethods/iksurvey.pdf (at 125:169) | SSL certificate not trusted. Use --insecure if site is trusted

Hint: Followed 5 redirects. You might want to consider replacing redirecting URLs with the resolved URLs. Use verbose mode (`-v`/`-vv`) to see redirection details.
Hint: You can configure accepted/rejected response codes with `-a` or `--accept`

Notices

⚠️ Your configuration references items that have been removed from MegaLinter and are ignored: REPOSITORY_GITLEAKS, REPOSITORY_KICS. See Removed linters to find their replacements.

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@10.1.0 --custom-flavor-setup --custom-flavor-linters ACTION_ACTIONLINT,CPP_CPPCHECK,CPP_CLANG_FORMAT,DOCKERFILE_HADOLINT,JSON_JSONLINT,JSON_PRETTIER,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,SPELL_LYCHEE,YAML_PRETTIER,YAML_YAMLLINT

MegaLinter is provided by OX Security
Show us your support by starring ⭐ the repository

@sonarqubecloud

sonarqubecloud Bot commented Nov 6, 2026

Copy link
Copy Markdown

@gabrielfrasantos
gabrielfrasantos merged commit 5d50077 into main Nov 6, 2026
12 checks passed
@gabrielfrasantos
gabrielfrasantos deleted the claude/determined-einstein-bznlpi branch November 6, 2026 11:07
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.

2 participants