Skip to content

feat(math): add SE2(3) extended-pose Lie group — the R-IEKF state manifold (#347) - #353

Merged
Ravenwater merged 3 commits into
mainfrom
feat/riekf-phase-b-se23
Jun 13, 2026
Merged

feat(math): add SE2(3) extended-pose Lie group — the R-IEKF state manifold (#347)#353
Ravenwater merged 3 commits into
mainfrom
feat/riekf-phase-b-se23

Conversation

@Ravenwater

@Ravenwater Ravenwater commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Phase B foundation for the R-IEKF epic (#347). SE₂(3) — the extended-pose / double-direct-isometry group (R, v, p) — is the state manifold that makes the IMU dynamics group-affine, so the right-invariant error Jacobians are state-independent and the unobservable yaw/position subspace is preserved by construction. That's the cure Phase A validated by measurement (flat yaw leak #349, state-independent propagation Φ #351).

What's here

  • math/lie/se23.hppexp/log (both translations share the SO(3) left Jacobian), compose, inverse, 5×5 matrix, 9×9 adjoint, in the rotation-first [φ; ν; ρ] ordering. Mirrors the se3.hpp/sim3.hpp idioms; clean-room (Solà 2018, Barrau-Bonnabel 2017).
  • Tests (in lie_groups): exp/log round-trip, compose/inverse, and the adjoint identity X·exp(ξ)·X⁻¹ = exp(Ad_X·ξ) — 42 assertions, alongside the existing SO3/SE3/Sim3 suite (741 total, green).

Next in Phase B

The invariant IMU propagation and camera measurement update on this state, then the MsckfInvariantBackend wiring (parallel to the shipped EKF) + the EuRoC verdict.

Refs #347, #348, #212.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added SE₂(3) extended-pose group: rotation plus velocity and position, with composition, inversion, exponential/logarithm maps, and homogeneous-like/adjoint matrix representations.
  • Tests

    • Added tests for exp/log round-trips, composition and inversion identities, adjoint conjugation consistency, and robustness near half-turn rotations across numeric types.

…ifold (#347)

Phase B foundation. SE2(3) (R, v, p) is the extended-pose / double-direct-isometry
group: a rotation plus two coupled translations (velocity, position). Writing the
IMU state here makes the dynamics group-affine, so the right-invariant error
Jacobians are state-independent and the unobservable yaw/position subspace is
preserved by construction — the cure Phase A validated (flat yaw leak,
state-independent propagation Phi).

- math/lie/se23.hpp: exp/log (both translations share the SO3 left Jacobian),
  compose, inverse, 5x5 matrix, 9x9 adjoint, in the rotation-first [phi; nu; rho]
  ordering. Mirrors the se3.hpp idioms; clean-room (Sola 2018, Barrau-Bonnabel 2017).
- lie_groups tests: exp/log round-trip, compose/inverse, and the adjoint identity
  X.exp(xi).X^-1 = exp(Ad_X.xi). Runs alongside the existing SO3/SE3/Sim3 suite.

Next: the invariant IMU propagation and camera measurement update on this state.
Refs #347, #348, #212.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4b3ee18d-801f-4dfe-820f-dbc14a5e0785

📥 Commits

Reviewing files that changed from the base of the PR and between 48ee484 and bab8e8e.

📒 Files selected for processing (1)
  • tests/math/lie_groups.cpp

Walkthrough

This PR introduces the SE₂(3) "extended pose" Lie group as a new C++20 header-only template class with rotation, velocity, and position components. It implements exp/log (using SO(3) Jacobians), group composition and inversion, 5×5 and 9×9 matrix/adjoint representations, and adds tests validating round-trips, group identities, adjoint action, multi-arithmetic coverage, and a near-half-turn regression.

Changes

SE₂(3) Extended Pose Lie Group Implementation

Layer / File(s) Summary
SE23 class definition and public interface
math/include/branes/math/lie/se23.hpp
Defines SE23<T> with SO3<T> rotation, Vector3 velocity, and Vector3 position; public constructors, component accessors, static exp(Tangent), and log() returning a 9-vector tangent using SO(3) left-Jacobian/inverse.
Group operations and matrix representations
math/include/branes/math/lie/se23.hpp
Implements operator* (rotation compose, transform+sum velocity/position), inverse(), matrix() producing a 5×5 block representation, and adjoint() producing a 9×9 adjoint in [φ; ν; ρ] ordering using hat-maps and an internal place() helper.
SE23 test suite
tests/math/lie_groups.cpp
Adds SE23 include, require_se23_close helper, tests for exp/log round-trip (including zero/identity), composition and inversion identities, adjoint conjugation identity X · exp(ξ) · X⁻¹ = exp(Ad_X · ξ), type coverage (float/posit), and a regression test near θ≈π.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the key aspects (what, why, next steps) and references relevant design papers, but the PR template's Test Results table and several checklist items are incomplete or missing. Complete the Test Results table with build/test outcomes for both gcc and clang, and explicitly check off (or address) the Conventional Commits and testing checklist items.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding the SE2(3) Lie group implementation as the R-IEKF state manifold, directly matching the primary purpose of this changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/riekf-phase-b-se23

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/math/lie_groups.cpp`:
- Around line 412-450: SE23 tests only exercise double precision; add
multi-arithmetic round-trip and near-singular tests to match SO3/SE3/Sim3. Add a
TEST_CASE "SE23 round-trip across arithmetic types" that recreates the double
round-trip using lie::SE23<float> with det::Vec<float,9> and lie::SE23<posit32>
with det::Vec<posit32,9> (typedef posit32 = sw::universal::posit<32,2>),
checking X.log() ≈ xi with tolerance ~1e-4 via require_vec_close; also add
TEST_CASE "SE23 log is finite for a half-turn rotation" using lie::SE23<double>
with a Tan near θ≈π (use the suggested xi) and assert all entries of X.log() are
finite (std::isfinite) to exercise the SO3 inverse-left-Jacobian near its
removable singularity. Ensure test names match the pattern in the file and reuse
require_vec_close/REQUIRE as shown.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7b169f8d-e541-4bf4-a205-01bfeec6d54d

📥 Commits

Reviewing files that changed from the base of the PR and between a0c35aa and f3499d5.

📒 Files selected for processing (2)
  • math/include/branes/math/lie/se23.hpp
  • tests/math/lie_groups.cpp

Comment thread tests/math/lie_groups.cpp
…singular coverage

- The adjoint TEST_CASE name had a Unicode middle-dot which MSVC ctest
  codepage-mangles, so the filter matched no case and the job failed. Use ASCII.
- Address CodeRabbit: add SE2(3) round-trip tests in float and posit32 (the
  math-lib custom-arithmetic requirement) and a near-half-turn regression that
  exercises the left-Jacobian-inverse removable singularity in exp/log + adjoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/math/lie_groups.cpp`:
- Around line 478-482: The test is asserting branch-cut-sensitive equality for
the half-turn case by checking X.log() == xi; instead, ensure the log is finite
and that the group invariant holds: replace the require_vec_close(X.log(), xi,
1e-9) call with two checks—verify the components of X.log() are finite (no
NaN/inf) and verify that lie::SE23<double>::exp(X.log()) is numerically close to
X (e.g., require_mat_close(lie::SE23<double>::exp(X.log()), X, 1e-9) or
similar). Keep the rest of the loop (xi, X, dxi) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c01cd828-1c20-4191-ab6b-2e30202ae2f3

📥 Commits

Reviewing files that changed from the base of the PR and between f3499d5 and 48ee484.

📒 Files selected for processing (1)
  • tests/math/lie_groups.cpp

Comment thread tests/math/lie_groups.cpp
…anch cut

Address CodeRabbit: at theta = pi log is not unique, so asserting log(X) == xi can
fail for a correct implementation. Check exp(log(X)) close to X instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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