feat(falcon): v0.19.3 — first PASS verdict under real gz physics (cascade flies)#48
Conversation
…cade flies)
Closes v0.19.1 + v0.19.2's two open findings. First time the full
falcon-cascade bridge produces PASS under real Gazebo Harmonic
physics — falcon flies under real physics, not just architecturally
readied.
v0.19.3 bench (10-second hover, 70 % constant PWM, open loop):
verdict: backend=gazebo steps=1000 climb=385.25 m wall=11.62s
counters: imu_recv=2369 navsat_recv=117 motor_send=1000
PASS
Both findings closed:
**Finding 1b — SDF motor plugin tuning** (derived against PX4
x500's known-flying SDF; gz CLI positive control confirmed first):
- <collision> element on every rotor link. ODE treats links
without <collision> as visual-only; thrust didn't transfer
through the joint. v0.19.0–v0.19.2 had this gap → 0 climb.
- Joint axis: explicit <limit> + spring style; no <damping>.
- commandSubTopic=command/motor_speed (PX4 standard).
**Finding 1a — bridge publish-partition mismatch**:
Publisher::publish was called with empty partition, producing
FQN @/@/<topic>. gz-sim subscribes on the node's default
partition (GZ_PARTITION env or hostname:username), FQN
@hostname:user@/<topic>. Different FQNs, no delivery.
Fix: publisher.publish(&node.partition(), &msg) — one line.
Also explains why v0.19.2's `gz topic -i` showed our bridge
invisible.
What v0.19.3 proves:
- Bridge subscribes IMU + NavSat at exact configured rates
(2369 + 117 frames in 11.6 s = 203 Hz / 10 Hz).
- Bridge publishes Actuators with correct partition →
MulticopterMotorModel receives + acts → torque → rotor →
thrust → body lift end-to-end.
- 385 m climb in 10 s at 70 % PWM = open-loop ballistic.
PASS criterion was climb > 0.1 m, well crossed.
Ships:
- examples/falcon-sitl-gz/worlds/falcon-quad.sdf — fully revised
against x500 (collision + limit + spring style + topic).
- examples/falcon-sitl-gz/src/physics.rs — partition fix + topic
name change to command/motor_speed.
- bench-evidence/gz-sim/1779860110-gazebo-hover-{harness.log,
ticks.csv} + 2026-05-27-v0.19.3-first-pass-verdict.md.
- FV-FALCON-SIM-009 + FEAT-FALCON-v0.19.3 rollout entry.
Verification:
- cargo test --workspace --all-targets → 405 passing.
- cargo test -p falcon-sitl-gz --features gazebo → 11/11.
- cargo build --features gazebo → green.
- rivet validate → PASS.
- gz sim + bridge bench → PASS climb=385.25 m.
Honestly NOT claimed:
- That this is steady hover. 385 m ballistic climb at constant
70 % PWM is open loop. Closed-loop hover via the cascade lands
in v0.19.4 (scenario hover swaps constant PWM for relay-ekf →
relay-pos → relay-att → relay-rate → relay-mix-quad).
- That the SDF is flight-tuned. motorConstant gives 5× headroom
— fine for flies-vs-doesn't, needs tuning for steady disturbance.
Headline: 4 PRs in, the PulseEngine claim "falcon flies under real
physics" has positive observational evidence. The trajectory from
here is tuning, not unblocking.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
running 17 tests test result: ok. 17 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 1 test test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 16 filtered out; finished in 0.02s running 10 tests test result: ok. 10 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 10 tests test result: ok. 10 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 10 tests test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.12s 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.01s 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.12s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 17 tests test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s --- scenario: mission --- 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 55 tests test result: ok. 55 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 10 tests test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Kani-TQ.md running 7 tests test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 1 test test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 16 filtered out; finished in 0.05s running 20 tests test result: ok. 20 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 20 tests test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.28s 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.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.09s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 20 tests test result: ok. 20 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 13 tests test result: ok. 13 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 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.65s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 17 tests test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s --- scenario: step --- 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 17 tests test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s running 10 tests test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s falcon-hitl-rfspoof: backend=stub duration=5s running 55 tests test result: ok. 55 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 55 tests test result: ok. 55 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 55 tests test result: ok. 55 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.44s running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s running 10 tests test result: ok. 10 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 13 tests test result: ok. 13 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 17 tests test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Covercoverage_subjects/geofence_subject_rs/src/lib.rs 48 48 0.00% 5 5 0.00% 23 23 0.00% 0 0 -
|
| count | |
|---|---|
| Passed | 29 |
| Failed | -4 |
| Skipped (bench-only — needs hardware / sim) | 7 |
| Skipped (no steps) | 4 |
Failed artifacts
Bench-only artifacts (not run by CI)
FV-FALCON-SIM-005— gz-transport NavSat + Home projection — position-dependent loops (v0.18.1)FV-FALCON-SIM-001— PX4-SITL end-to-end loop — recipe + preset + smoke (v0.14.0)FV-FALCON-COV-001— witness MC/DC structural coverage — falcon pipeline wired (v0.13)FV-FALCON-ARCH-002— spar codegen --format wit recheck — works at v0.10.0 (v0.15.0)FV-FALCON-GEO-003— Geofence safety path — miri UB/overflow check (v0.12, AI substitute)FV-FALCON-COV-003— witness MC/DC on real Rust source — Geofence subject (v0.14.1)FV-FALCON-ARCH-001— spar AADL architectural model — falcon cascade (v0.13)
Source of truth: artifacts/verification/FV-FALCON-*.yaml.
Summary
Closes v0.19.1 + v0.19.2's two open findings. First time the full falcon-cascade bridge produces a PASS verdict under real Gazebo Harmonic physics. Falcon flies under real physics, not just architecturally readied.
v0.19.3 bench (10-second hover, 70 % constant PWM)
```
verdict: backend=gazebo steps=1000 climb=385.25 m wall=11.62s
counters: imu_recv=2369 navsat_recv=117 motor_send=1000
PASS
```
Findings closed
Finding 1b — SDF motor plugin tuning
Derived against PX4 x500's known-flying SDF (`Tools/simulation/gz/models/x500_base/model.sdf`). gz CLI positive control confirmed first (`gz topic -p` to /quad/command/motor_speed lifted body from z=0.02 m to z=187 m in 3 s).
Finding 1a — bridge publish-partition mismatch
`Publisher::publish(partition, msg)` constructs FQN as `@@/`. The bridge was passing `""` (empty), producing FQN `@/@/quad/command/motor_speed`. gz-sim's MulticopterMotorModel subscribed on the node's default partition (`GZ_PARTITION` env or `hostname:username`), FQN `@hostname:user@/quad/command/motor_speed`. Different FQNs → no delivery.
Fix: one line.
```rust
let node_partition = node.partition(); // gz default
...
publisher.publish(&node_partition, &msg) // was: ("", &msg)
```
Also explains why v0.19.2's `gz topic -i` showed our bridge invisible: gz CLI filters by the default partition.
What v0.19.3 proves
Honestly NOT claimed
v0.19.4 candidates
Verification
Headline
Four PRs into the gz-sim arc, the PulseEngine claim "falcon flies under real physics" has positive observational evidence, not just architectural readiness. The trajectory from here is tuning, not unblocking.
🤖 Generated with Claude Code