Skip to content

feat(holistic_fusion): add a heading factor that is defined for every attitude - #55

Merged
nubertj merged 3 commits into
mainfrom
julian/heading_factor
Oct 9, 2026
Merged

nubertj merged 3 commits into
mainfrom
julian/heading_factor

Conversation

@nubertj

@nubertj nubertj commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

The yaw factor constrains the Euler yaw atan2(R(1,0), R(0,0)) of the sensor frame S.
It is undefined when the x-axis of S is vertical, e.g. a humanoid lying on its back.
Close to that attitude, its Jacobian grows like 1/cos(pitch) and couples with roll.

Main change

  • GmsfUnaryExpressionAbsoluteHeading takes the measured orientation R_M_Smeas in the fixed frame M and constrains e_z · Log(R_W_S * (R_W_M * R_M_Smeas)^-1), the rotation about the z-axis of the world.
    • It uses no Euler decomposition, so it is defined for every attitude.
    • To first order, rotations about the horizontal axes of the world leave it unchanged, for the state and for R_W_M. Roll and pitch stay with gravity, also with a tilted M.
    • For equal roll and pitch, it equals the yaw difference.
    • The error is a Rot2, so it wraps around at ±pi.
  • HolisticFusionHolistic::addUnaryHeadingAbsoluteMeasurement follows the holistic yaw measurement. It goes through T_W_M and has the same alignment keyframe requirement. That check is shared in a helper.
  • The yaw factor is unchanged.

Test plan

  • heading_expression_test: yaw difference for equal tilt (including x-axis vertical), first-order invariance to tilt, measurement brought to the world through T_W_M, Jacobians of a tilted M that pull only about world z, numerical Jacobians (including x-axis vertical) and the wrap at ±pi.
  • Built and run through the FlexCode Bazel build. FlexSeam builds and its tests pass with FlexFuser switched to the heading measurement.
  • FlexCode replay or robot run with LIO yaw and position fusion through the heading factor.

🤖 Generated with Claude Code. Co-authored with @nubertj.

@nubertj nubertj self-assigned this Oct 8, 2026
… attitude

The yaw factor constrains the Euler yaw of the sensor frame, which is undefined when its x-axis is vertical.
The heading factor takes the measured orientation and constrains the rotation about the z-axis of the fixed frame
between the estimated and the measured orientation, read from the rotation vector of their offset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nubertj
nubertj force-pushed the julian/heading_factor branch from ee24031 to a9120ca Compare October 8, 2026 01:43
@nubertj
nubertj marked this pull request as ready for review October 8, 2026 20:04
The heading was the rotation about the z-axis of the fixed frame M. With a tilted M, that axis is tilted in the world.
The factor then also pulled on the roll and pitch of the state and of R_W_M, which gravity observes.
The measured orientation is now brought to the world through R_W_M, and the heading is taken about the z-axis of the world.

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

@nubertj nubertj left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

needed a bit more refienemnt, but was addressed already

Comment thread holistic_fusion/include/holistic_fusion/interface/HolisticFusionHolistic.h Outdated
Comment thread holistic_fusion/tests/test_heading_expression.cpp

@nubertj nubertj left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

generally looking good now.

Comment thread holistic_fusion/src/lib/HolisticFusionHolistic.cpp Outdated
Name the heading helper after its input, split the measured world rotation into its own line and move the
alignment keyframe check above its callers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nubertj
nubertj merged commit 481c067 into main Oct 9, 2026
4 checks passed
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