Skip to content

feat: wave 4 roadmap items (M32, M12, M11, M14, M10, P2) - #35

Merged
gabrielfrasantos merged 7 commits into
mainfrom
claude/determined-einstein-bznlpi
Nov 5, 2026
Merged

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

Conversation

@gabrielfrasantos

Copy link
Copy Markdown
Contributor

This PR is wave 4 of the roadmap: the small consumers that build on the wave-3 foundation (frame chain, geometric Jacobian, chain dynamics model). The wave's mobile items (W4–W8) still wait on SE(2) (NT66) in numerical-toolbox-cpp.

As in earlier waves, each item is one self-contained commit following roadmap/DEPLOYMENT.md:

  • header and coverage .cpp;
  • the spec's test cases;
  • CMake wiring;
  • doc page and doc-table rows;
  • removal of the item's roadmap/ spec and its rows in ROADMAP.md and roadmap/README.md.

Items

Commit Item Summary
b89828a M32 RNEA with an external tool wrench Adds ToolWrench plus an InverseDynamics overload that subtracts the environment's wrench in the backward pass. Satisfies τ(w) − τ(0) = −Jᵀw, which the tests check against GeometricJacobian.
22f7d63 M12 ComputedTorqueControl Computes a_q = q̈_d + Kd·ė + Kp·e, then makes one InverseDynamicsModel call. With an exact model, the plant's tracking error matches the ideal error dynamics ë + Kd·ė + Kp·e = 0 step by step in closed loop.
cb58fd9 M11 ManipulabilityIndex Yoshikawa index from J·Jᵀ or Jᵀ·J (whichever is not rank-deficient by shape) via LU. Velocity-ellipsoid axes and condition number via SVD; a near-singular guard. Works on any JacobianProvider.
0d855a2 M14 RedundancyResolution q̇ = J⁺_λ·ẋ + (I − J⁺J)·q̇₀ on upstream solvers::DampedPseudoInverse (NT62). The projector is undamped and rank-thresholded, so secondary motion never reaches the task for any damping λ.
cf7a452 M10 CartesianSlerpInterpolation Straight-line position plus shortest-arc quaternion SLERP on one time law. The time law is a template parameter, so there is no virtual call. Also returns the twist feed-forward (v; ω) = ṡ·(Δp; φ·k).
b47f46e P2 PotentialField Quadratic-then-conic attraction plus Khatib repulsion, clamped to a maximum speed. Each command reports Moving, Reached or Stalled, so local minima are detected rather than hidden.

Changes from the specs

  • New test doubles:
    • dynamics::MockInverseDynamicsModel in robotics.dynamics_test_doubles, for M12.
    • kinematics::MockJacobianProvider in a new robotics.kinematics_test_doubles target, for M11.
  • M14: the undamped_primary_task_is_exact test also asserts J·J⁺ = I. This covers the DampedPseudoInverse(q) accessor, which no spec case exercised.
  • P2: the FieldStatus values are PascalCase (Moving, Reached, Stalled) to match the repo's other enums. The spec had them lowercase.
  • Roadmap README: its canonical worked example pointed at the ComputedTorqueControl spec, which this PR deletes. It now points to ImpedanceControl.
  • Build: robotics.trajectory now links numerical.motion_profiles, and the dynamics test target links robotics.kinematics for the M32 Jacobian cross-check.

Verification

  • The host-single-Debug build and the coverage build (EMIL_ENABLE_COVERAGE=On) both pass 5/5 test executables.
  • Merged gcov line coverage is 100% on every new or changed header.
  • Reference values from the specs are met, including M14's 1e-5 exactness checks on a 7R arm (iiwa-like DH table) and M11's condition numbers within 0.1%.
  • clang-format and scripts/validate-docs.py pass. No doc line exceeds markdownlint's 400-character limit, and doc tables are aligned.

Not run locally: the Qt simulator build, cppcheck, and SonarCloud. CI covers these.


Generated by Claude Code

ToolWrench carries the environment's force and moment at the tool
point. The new InverseDynamics overload subtracts it from the last
link's load in the backward pass, which satisfies
tau(w) - tau(0) = -J^T w.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Feedback-linearizing joint controller: a_q = qdd_d + Kd e_dot + Kp e,
then tau = ID(q, qdot, a_q) in one InverseDynamicsModel call, which
gives decoupled error dynamics. Adds a MockInverseDynamicsModel test
double.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Yoshikawa index through the unit-consistent Gram determinant (J J^T or
J^T J, whichever is not rank-deficient by shape), velocity-ellipsoid
axes and condition number through the SVD, and a near-singular guard,
all over a JacobianProvider. Adds a MockJacobianProvider test double.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
qdot = J+_lambda xdot + (I - J+ J) qdot0 over a JacobianProvider, on
upstream solvers::DampedPseudoInverse (NT62). The undamped,
rank-thresholded projector keeps secondary motion invisible to the task
for any damping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Straight-line position and shortest-arc quaternion SLERP driven by one
time law (template parameter, no virtual call), with the twist
feed-forward (v; omega) = sdot (p1 - p0; phi k) computed from the
sign-fixed quaternion pair.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WUWh44uw7k4JjMd6YkAwN
Quadratic-then-conic attraction plus Khatib repulsion from proximity
readings, clamped to a maximum speed. Each command reports moving,
reached or stalled, so local minima are detected rather than hidden.

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 5, 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.48s
✅ CPP clang-format 89 0 0 0 0.96s
✅ CPP cppcheck 89 0 0 1.37s
✅ DOCKERFILE hadolint 1 0 0 0.36s
✅ JSON jsonlint 8 0 0 0.09s
✅ JSON prettier 8 2 0 0 0.32s
✅ MARKDOWN markdownlint 152 0 0 0 1.85s
✅ MARKDOWN markdown-table-formatter 152 0 0 0 0.19s
⚠️ SPELL lychee 195 2 0 16.09s
✅ YAML prettier 12 0 0 0 0.43s
✅ YAML yamllint 12 0 0 0.47s

Detailed Issues

⚠️ SPELL / lychee - 2 errors
[ERROR] failed to verify TLS certificate: invalid peer certificate: UnknownIssuer
📝 Summary
---------------------
🔍 Total..........217
🔗 Unique..........93
✅ Successful.....205
⏳ 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

MSVC (C2244) cannot match the out-of-class definition when its return
type spells the dependent static member as
std::array<T, ManipulabilityIndex<...>::Axes>. An AxesArray alias,
referenced as typename ...::AxesArray like the rest of the library,
builds on MSVC, GCC and Clang.

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

sonarqubecloud Bot commented Nov 5, 2026

Copy link
Copy Markdown

@gabrielfrasantos
gabrielfrasantos merged commit 20f230f into main Nov 5, 2026
12 checks passed
@gabrielfrasantos
gabrielfrasantos deleted the claude/determined-einstein-bznlpi branch November 5, 2026 12:26
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