Conversation
`RotorLag` carried no limits, so a caller stepping it with an unclamped command left the state representing a thrust the rotor could not produce — the mixer's clamp, undone one stage downstream. The limits are optional and a model starts without any, so an unbounded lag follows its command exactly as before. `try_with_thrust_limits` takes the same pair the mixer was built with (validating them the same way, reusing `NonFinite` and `InvalidThrustLimits`), and from then on `stepped`, `stepped_over` and `with_thrusts` hold the state inside them. The clamp compares rather than using `Numeric::min`/`max`: the floating-point `min`/`max` return the non-NaN operand, which would turn a NaN command into an infinity at unbounded limits and quietly change the documented "non-finite in, non-finite out" policy. Comparisons leave a NaN alone. `reset` stays the disarmed all-zero state rather than being held to a minimum above zero, and says so; `rate` is a derivative rather than the state and is left unclamped, also said so. The plant tutorial now builds the lag with the mixer's limits, and the error list names the new builder. The suite pins the settle-on-the-limit behavior for both step paths, the refused limits, the with_thrusts clamp, the disarmed reset, and the `wrench` agreement between the limited lag and the mixer's own clamped thrusts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #292.
RotorLagcarried no limits, so a caller stepping it with an unclamped command left the state representing a thrust the rotor could not produce — the mixer's clamp, undone one stage downstream.The API. The limits are optional and a model starts without any, so an unbounded lag follows its command exactly as before:
try_with_thrust_limitsvalidates the pair the wayMultirotorMixer::newdoes (reusingPlantError::NonFiniteandPlantError::InvalidThrustLimits), andminimum_thrust()/maximum_thrust()read them back,NEG_INFINITY/INFINITYwhen unset. From then onstepped,stepped_overandwith_thrustshold the state inside them; each of the three goes through one private clamp helper.Decisions worth a look:
Numeric::min/max. The floating-pointmin/maxreturn the non-NaN operand, so at unbounded limits a NaN command would come back as ±∞ — quietly changing the documented "a command that is not finite comes back not finite" policy. Comparisons leave a NaN alone, and the existing non-finite test still passes.resetstays the disarmed all-zero state, not clamped to a minimum above zero:newstarts there too, and a stopped rotor is not giving thrust. The next step climbs back inside the limits. Documented on both items.rateis not clamped — it is a derivative rather than the state — and its doc now says so.Tests (
tests/suite/plant/rotor_lag.rs, 9 new): a command above the maximum settles exactly on it and never exceeds it on any tick (and vice versa for the minimum), the same forstepped_over, the refused limits,with_thrustsclamped on the way in, the disarmedreset, limits far outside the command leaving the lag identical to the unbounded one tick by tick, and the issue's end-to-end case — a limited lag fed the mixer's clampedrotor_thrustsproduces the mixer's wrench, and fed the raw command it lands exactly on the mixer's clamped thrusts.Evidence. With the clamp temporarily neutered the six limit-dependent tests fail (
a rotor must never give more than its maximum, left[…30.0]vs right[…5.0]); restored, the file is 26/26.cargo test -p multicalc(451 doctests included),--features alloc(539),--all-features --doc(539),-p multicalc-robot-model,cargo clippy -p multicalc --all-targets --features alloc -- -D warnings, andcargo fmt --all --checkare all green.Not done.
demos/left alone: the lag showcases do not discuss limits and the limits demo does not showRotorLag.cargo test --workspacecannot buildtools/embedded-smokeon the host (89 ×cannot find hprintln) — pre-existing, verified by stashing this change.