Skip to content

Report a degenerate orientation from a checked state derivative (#286) - #353

Open
maskjelly wants to merge 1 commit into
kmolan:mainfrom
maskjelly:fix/rigid-body-checked-derivative
Open

maskjelly wants to merge 1 commit into
kmolan:mainfrom
maskjelly:fix/rigid-body-checked-derivative

Conversation

@maskjelly

Copy link
Copy Markdown

Closes #286.

RigidBody::state_derivative answers a state whose four orientation numbers normalize to nothing with an all-zero derivative, and an integrator reads that as a body at rest — the run quietly freezes in place and keeps going rather than stopping.

The API.

let derivative = body.try_state_derivative(&state, applied_wrench)?;   // Err(DegenerateOrientation)
let derivative = body.state_derivative(&state, applied_wrench);        // zeros, unchanged
  • New DynamicsError::DegenerateOrientation (#[non_exhaustive], so additive), with its Display arm.
  • try_state_derivative carries the same arithmetic, a # Errors section, and an example pinning both the valid path and the error.
  • The infallible state_derivative keeps its signature and its zeros, now delegating to the checked one. Its doc and its integrator example say explicitly what a degenerate state does there — the note sits in the loop example a caller copies, not only in the prose above it — and point at the checked twin.

Numeric path unchanged by construction: the valid-state computation moved verbatim into the checked variant; the only new branch is the error return. The existing goldens (a_free_tumble…, stepped_agrees…) pass untouched.

Tests (tests/suite/dynamics/rigid_body.rs, 3 new): the error on exact zeros and on 1e-320 (a subnormal whose squared norm underflows to nothing, so it normalizes to no direction just the same), the infallible zeros for that same state, and element-wise agreement between the two variants on five valid states — the ones the file already runs, plus one whose orientation numbers have drifted 1.1× off unit length, which both scale back before reading.

Evidence. With the error path temporarily stubbed back to Ok(zeros) the pinning test fails (left: Ok([…0.0…]), right: Err(DegenerateOrientation)) and the doctest fails; restored, cargo test -p multicalc (451 doctests included), --features alloc (540), --all-features --doc (540), cargo clippy -p multicalc --all-targets --features alloc -- -D warnings, and cargo fmt --all --check are all green.

Not done. Demos left untouched: demos/examples/basics/rigid_body_dynamics.rs calls state_derivative inside Rk4 closures and makes no claim that a degenerate orientation is impossible; the checked twin is there if they want it. free_joint_from_state_vector's pre-existing "all zero" wording was left alone (out of scope).

…an#286)

`RigidBody::state_derivative` answers a state whose four orientation
numbers normalize to nothing with an all-zero derivative, and an
integrator reads that as a body at rest — so the run quietly freezes in
place and keeps going rather than stopping. A state this broken is not a
case to paper over.

`try_state_derivative` is the checked twin: the same arithmetic, with
the reason coming back as `DynamicsError::DegenerateOrientation`. The
infallible call keeps its signature and its zeros, now delegating to the
checked one, and both its doc and the loop example spell out what a
degenerate state does there and point at the checked twin — the note sits
in the example a caller copies, not only in the prose above it.

The suite pins the error on exact zeros and on a subnormal whose squared
norm underflows to nothing, pins the infallible zeros for the same state,
and asserts the two variants agree element-wise on five valid states,
including one whose orientation numbers have drifted off unit length.
@maskjelly
maskjelly requested a review from kmolan as a code owner September 16, 2026 21:04

This branch has not been deployed

No deployments
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.

Return an error from RigidBody::state_derivative for a degenerate orientation

1 participant