feat(falcon): v0.3.0 — rate PID + closed-loop pure-Rust SITL#14
Conversation
The inner control loop closes. v0.2's EKF estimates attitude, v0.3's
new rate PID drives commanded body rates, a pure-Rust rigid-body
plant integrates dynamics — full closed loop converges in-process,
deterministic given a seed, runs in CI without a Gazebo install.
What lands:
Crates
- relay-rate — body-rate PID stabilizer. 3-axis, no_std + no_alloc.
Clamp-and-hold anti-windup (RATE-P01). NaN-safe input handling
(RATE-P02). Step-response convergence on a pure-integrator plant
within 2 s with <0.01 rad/s steady-state error (RATE-P03 surrogate).
Defaults tuned for a 500 g, 10-inch quad at 1 kHz. 13 unit +
proptest cases.
Example
- examples/falcon-sitl-hover — pure-Rust closed-loop SITL bench.
Rigid-body plant (rotational dynamics + quaternion integration)
+ v0.2 EKF + v0.3 rate PID, three scenarios:
step: setpoint [0.5,-0.3,0.4] rad/s → converges in 0.139 s
with 1.2 % overshoot, 0.0012 rad/s RMS-steady
disturbance: 1 rad/s impulse recovered in 0.141 s
hover: initial rates [0.7,-0.5,0.3] → settled in 0.175 s
CLI: --scenario, --noise σ, --quiet. 5 integration tests.
Rivet
- FV-FALCON-RATE-001 — v0.3 verification artifact with 5 extractable
fields.steps. Brings the falcon gate from 4 → 5 artifacts (13 → 18
steps).
- FEAT-FALCON-v0.3 bumped pending → approved, achieved metrics inline.
Verification posture
- cargo test --workspace: 55 test suites green (was 52 in v0.2)
- python3 scripts/run-falcon-verification.py: ✅ 5/5, 18/18 steps green
- cargo run -p falcon-sitl-hover --release: PASS on all 3 scenarios
- rivet validate: 0 broken cross-references
Scope notes — what slipped to v0.4
- Gazebo Harmonic SITL: pure-Rust SITL ships now because it runs in CI
without Gazebo install + produces byte-identical results given a seed.
Gazebo lockstep proper makes more sense once relay-att joins (v0.4)
for a full hover.
- Lean Lyapunov formal proof on the rate loop — v0.4 with rules_lean.
- Kani bounded-overflow on PID arithmetic — v0.4.
- tokio-rs/loom on host bridge — v0.5 once the bridge exists.
- rerun.io .rrd evidence — v0.4 with the SITL hookup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
running 16 tests test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 16 tests test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 16 tests test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.66s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 5 tests test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s --- noise=0 (deterministic) --- running 13 tests test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 13 tests test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 13 tests test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.50s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 5 tests test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s --- scenario: step --- running 9 tests test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s [falcon-hello-demo] building release binary... running 9 tests test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 9 tests test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 9 tests test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 33 tests test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 33 tests test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 33 tests test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.33s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s falcon verification gate (filter: (has-tag "falcon"))5 artifact(s) matched: FV-FALCON-EKF-001, FV-FALCON-RATE-001, FV-FALCON-WORLD-001, FV-FALCON-EKF-STUB-001, FV-FALCON-MAVLINK-001[ PASS] ( 6.77s) FV-FALCON-EKF-001: cargo test -p relay-ekf ✅ Rivet verification gate — falcon5/5 passed
Source of truth: |
Summary
The inner control loop closes. v0.3 adds a body-rate PID stabilizer and a pure-Rust closed-loop SITL bench that drives the v0.2 EKF + v0.3 PID against a rigid-body plant and verifies convergence on three scenarios — all deterministic, all in CI.
What's in
crates/relay-rate— 3-axis body-rate PID with clamp-and-hold anti-windup. no_std + no_alloc. 13 unit + proptest cases.examples/falcon-sitl-hover— pure-Rust closed-loop SITL bench. Plant + EKF + rate PID closed-loop; 3 scenarios (step / disturbance / hover); 5 integration tests.FV-FALCON-RATE-001— v0.3 verification artifact, 5 extractable steps.FEAT-FALCON-v0.3bumpedpending→approvedwith achieved metrics inline.Achieved on this branch
[0.5, -0.3, 0.4]rad/s[0.7, -0.5, 0.3]cargo test --workspacecargo test -p relay-ratecargo test -p falcon-sitl-hovercargo run -p falcon-sitl-hover --releaserivet validateTest plan
cargo run -p falcon-sitl-hover --releaselocally prints PASS for all 3 scenariosAfter merge
Scope note — Gazebo slipped to v0.4
Gazebo Harmonic SITL was originally scoped for v0.3, but pure-Rust SITL ships now because it:
Real Gazebo lockstep arrives with v0.4 where the full attitude cascade (
relay-att) makes a real hover meaningful. The pure-Rust SITL stays in tree as the fast-iteration test rig.Other v0.3 items pushed to v0.4: Lean Lyapunov proof of rate loop (needs rules_lean wiring), Kani bounded-overflow check, tokio-rs/loom on host bridge (no bridge yet), rerun.io evidence (lands with Gazebo).
🤖 Generated with Claude Code