Skip to content

feat(falcon): v0.6.0 — WASM component pipeline, meld fuse → synth → ARM ELF#17

Merged
avrabe merged 1 commit into
mainfrom
falcon/v0.6
May 20, 2026
Merged

feat(falcon): v0.6.0 — WASM component pipeline, meld fuse → synth → ARM ELF#17
avrabe merged 1 commit into
mainfrom
falcon/v0.6

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 20, 2026

Summary

v0.6 reworked. Original scope was hardware bring-up on a Cube Orange — hardware wasn't in place, so v0.6 became the WASM component pipeline + Renode emulation: control crates → WASM → meld fusewasm-optsynth → real ARM Cortex-M ELF. Hardware-independent, CI-reproducible.

What's in

  • wasm/falcon-mix-component, wasm/falcon-rate-component — cdylib wrappers exposing relay-mix-quad / relay-rate as scalar-ABI WASM exports. rlib path unit-tested natively (5 tests).
  • wit/falcon-control/{mixer,rate}.wit — WIT worlds in the spar-codegen wit_gen shape.
  • scripts/falcon-wasm-pipeline.sh — reproducible cargo wasm32 → wasm-tools → meld fuse → wasm-opt → synth pipeline; wasmtime as reference oracle.
  • renode/falcon-cortex-m.resc — Renode STM32H743 machine script (runs in Linux CI via renode-bazel-rules).
  • FV-FALCON-PIPELINE-001, FEAT-FALCON-v0.6 reworked.
  • meld + synth cargo install'd as pinned binaries.

Pipeline result

2 components → meld fuse (shared memory) → 4412 B single-memory module
wasm-opt -Os:  4412 B → 4126 B
synth compile: fused module → 1716 B ARM Cortex-M ELF; mixer → 911 B ELF
wasmtime ref:  falcon-mix-total(0,0,0,0.5) = 2.0 ✓   falcon-rate-torque(1.0) > 0 ✓
synth disasm:  elf32-littlearm confirmed
check result
cargo test --workspace 65 suites green (was 61 in v0.5)
bash scripts/falcon-wasm-pipeline.sh PASS
Verification gate ✅ 9/9 artifacts
rivet validate 0 broken cross-references

Tool issues found + tracked

Bring-up surfaced three real tool issues — all investigated and filed upstream:

  • synth#120unmapped vreg panic on f32 division (float::div). falcon-rate-component standalone trips it; the meld-fused module compiles fine. Commented with the falcon repro.
  • synth#124 (filed) — synth verify advertised in CLI but inert without --features verify.
  • meld#172 (filed) — meld fuse defaults to --memory multi, rejected by wasm-opt/synth; pipeline uses --memory shared.

Test plan

  • CI green
  • Verification gate posts ✅ 9/9 sticky comment
  • bash scripts/falcon-wasm-pipeline.sh PASSes locally (needs wasm-tools, meld, synth, wasm-opt on PATH)

Deferred to v0.7

  • ekf/att/pos crates through the pipeline (gated on synth#120 — they do f32 division)
  • Full Bazel integration via rules_wasm_component
  • Live Renode run in CI
  • synth verify Z3 translation validation (gated on synth#124)

🤖 Generated with Claude Code

…RM ELF

Reworked v0.6. Original scope was hardware bring-up on a Cube Orange;
hardware wasn't in place, so v0.6 became the WASM component pipeline +
Renode emulation — exercises the full meld → wasm-opt → synth
toolchain and produces a real ARM Cortex-M ELF, hardware-independent.

What lands:

WASM components
- wasm/falcon-mix-component, wasm/falcon-rate-component — cdylib
  wrappers exposing relay-mix-quad / relay-rate as scalar-ABI WASM
  exports (#[export_name] kebab names matching the WIT worlds).
  rlib path unit-tested natively against the control crates (5 tests).
- wit/falcon-control/{mixer,rate}.wit — WIT worlds in the shape
  spar-codegen's wit_gen emits from the AADL model.

Pipeline
- scripts/falcon-wasm-pipeline.sh — cargo build wasm32 → wasm-tools
  component embed+new → meld fuse --memory shared → wasm-opt -Os →
  synth compile --cortex-m. wasmtime is the reference oracle.
  Result: 2 components → meld fuse → 4412 B → wasm-opt → 4126 B →
  synth → 1716 B ARM Cortex-M ELF (fused) + 911 B (mixer).
- renode/falcon-cortex-m.resc — Renode STM32H743 machine script;
  runs in Linux CI via renode-bazel-rules.
- meld + synth cargo-installed as pinned ~/.cargo/bin binaries.

Rivet
- FV-FALCON-PIPELINE-001 verification artifact (4 extractable steps).
- FEAT-FALCON-v0.6 reworked pending → approved.

Tool issues found during bring-up — investigated + filed upstream:
- synth#120 — unmapped-vreg panic on f32 division (float::div);
  falcon-rate-component standalone trips it, fused module is fine.
  Commented with the falcon repro.
- synth#124 (filed) — synth verify advertised but inert without
  --features verify.
- meld#172 (filed) — meld fuse --memory multi default rejected by
  wasm-opt/synth; pipeline uses --memory shared --address-rebase.

Verification
- cargo test --workspace: 65 test suites green (was 61 in v0.5)
- bash scripts/falcon-wasm-pipeline.sh: PASS
- python3 scripts/run-falcon-verification.py: ✅ 9/9 artifacts green
- rivet validate: 0 broken cross-references

Deferred to v0.7
- ekf/att/pos crates through the pipeline (gated on synth#120 —
  they do f32 division)
- Full Bazel integration via rules_wasm_component
- Live Renode run in CI
- synth verify Z3 translation validation (gated on synth#124)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

running 13 tests
test tests::altitude_above_setpoint_reduces_thrust ... ok
test tests::altitude_below_setpoint_increases_thrust ... ok
test tests::at_setpoint_with_zero_velocity_gives_hover_thrust ... ok
test tests::degenerate_input_does_not_propagate ... ok
test tests::east_position_error_rolls_right ... ok
test tests::pos_p01_bounds_enforced ... ok
test tests::forward_position_error_pitches_nose_down ... ok
test tests::reset_clears_integral ... ok
test tests::tilt_clamped_to_tilt_max ... ok
test tests::v_setpoint_clamped_to_v_max ... ok
test tests::yaw_held_when_setpoint_is_nan ... ok
test tests::yaw_setpoint_is_followed ... ok
test tests::pos_p01_property ... ok

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 tests::altitude_above_setpoint_reduces_thrust ... ok
test tests::altitude_below_setpoint_increases_thrust ... ok
test tests::at_setpoint_with_zero_velocity_gives_hover_thrust ... ok
test tests::degenerate_input_does_not_propagate ... ok
test tests::east_position_error_rolls_right ... ok
test tests::forward_position_error_pitches_nose_down ... ok
test tests::pos_p01_bounds_enforced ... ok
test tests::reset_clears_integral ... ok
test tests::tilt_clamped_to_tilt_max ... ok
test tests::yaw_held_when_setpoint_is_nan ... ok
test tests::v_setpoint_clamped_to_v_max ... ok
test tests::yaw_setpoint_is_followed ... ok
test tests::pos_p01_property ... ok

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 tests::altitude_above_setpoint_reduces_thrust ... ok
test tests::altitude_below_setpoint_increases_thrust ... ok
test tests::degenerate_input_does_not_propagate ... ok
test tests::east_position_error_rolls_right ... ok
test tests::at_setpoint_with_zero_velocity_gives_hover_thrust ... ok
test tests::forward_position_error_pitches_nose_down ... ok
test tests::pos_p01_bounds_enforced ... ok
test tests::reset_clears_integral ... ok
test tests::tilt_clamped_to_tilt_max ... ok
test tests::yaw_held_when_setpoint_is_nan ... ok
test tests::v_setpoint_clamped_to_v_max ... ok
test tests::yaw_setpoint_is_followed ... ok
test tests::pos_p01_property ... ok

test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.11s

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 tests::deterministic_disturbance_recovers ... ok
test tests::deterministic_hover_settles ... ok
test tests::deterministic_attitude_cascade_passes ... ok
test tests::deterministic_step_response_passes ... ok
test tests::noisy_attitude_cascade_still_passes ... ok
test tests::plant_step_full_preserves_unit_quaternion_and_finite_state ... ok
test tests::plant_step_preserves_unit_quaternion ... ok
test tests::deterministic_mission_passes ... ok
test tests::noisy_step_response_still_passes ... ok
test tests::noisy_mission_still_reaches_waypoint ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

--- scenario: mission ---
samples 12000
final v (m/s NED) [-0.004, +0.000, +0.003]
peak distance error 10.000 m
final distance 0.010 m
RMS distance (steady)0.015 m (last 2s)
convergence time 4.045s
loop wall time 2250 µs
NaN/∞ seen false
outcome PASS
falcon-sitl-hover: PASS

running 3 tests
test tests::idx_wraps_mod_four ... ok
test tests::motor_export_matches_native_mixer ... ok
test tests::total_export_is_sum_of_motors ... ok

test result: ok. 3 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 2 tests
test tests::torque_digest_sign_follows_setpoint ... ok
test tests::step_digest_converges_toward_setpoint ... ok

test result: ok. 2 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 3 tests
test tests::idx_wraps_mod_four ... ok
test tests::motor_export_matches_native_mixer ... ok
test tests::total_export_is_sum_of_motors ... ok

test result: ok. 3 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 2 tests
test tests::torque_digest_sign_follows_setpoint ... ok
test tests::step_digest_converges_toward_setpoint ... ok

test result: ok. 2 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 tests::mix_p01_zero_command_gives_thrust_only ... ok
test tests::high_thrust_with_torque_saturates_gracefully ... ok
test tests::mix_p02_outputs_in_unit_interval ... ok
test tests::mix_p03_pure_pitch_drives_front_and_back_motors_opposite ... ok
test tests::mix_p03_pure_roll_drives_diagonal_motor_pairs_opposite ... ok
test tests::mix_p03_pure_yaw_drives_cw_and_ccw_pairs_opposite ... ok
test tests::nan_input_does_not_propagate ... ok
test tests::negative_thrust_clipped_to_zero ... ok
test tests::mix_p03_property_single_axis ... ok
test tests::mix_p02_property ... ok

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 tests::high_thrust_with_torque_saturates_gracefully ... ok
test tests::mix_p01_zero_command_gives_thrust_only ... ok
test tests::mix_p02_outputs_in_unit_interval ... ok
test tests::mix_p03_pure_pitch_drives_front_and_back_motors_opposite ... ok
test tests::mix_p03_pure_yaw_drives_cw_and_ccw_pairs_opposite ... ok
test tests::mix_p03_pure_roll_drives_diagonal_motor_pairs_opposite ... ok
test tests::nan_input_does_not_propagate ... ok
test tests::mix_p03_property_single_axis ... ok
test tests::negative_thrust_clipped_to_zero ... ok
test tests::mix_p02_property ... ok

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 tests::high_thrust_with_torque_saturates_gracefully ... ok
test tests::mix_p01_zero_command_gives_thrust_only ... ok
test tests::mix_p02_outputs_in_unit_interval ... ok
test tests::mix_p03_pure_pitch_drives_front_and_back_motors_opposite ... ok
test tests::mix_p03_pure_roll_drives_diagonal_motor_pairs_opposite ... ok
test tests::mix_p03_pure_yaw_drives_cw_and_ccw_pairs_opposite ... ok
test tests::nan_input_does_not_propagate ... ok
test tests::negative_thrust_clipped_to_zero ... ok
test tests::mix_p03_property_single_axis ... ok
test tests::mix_p02_property ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s

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 tests::at_zero_error_output_is_zero ... ok
test tests::fresh_pid_has_zero_state ... ok
test tests::out_of_range_dt_clamped_safely ... ok
test tests::negative_error_drives_negative_torque ... ok
test tests::positive_error_drives_positive_torque ... ok
test tests::rate_p02_infinite_setpoint_does_not_propagate ... ok
test tests::rate_p02_nan_input_does_not_propagate ... ok
test tests::output_clamped_to_torque_max ... ok
test tests::rate_p03_step_response_drives_error_to_zero ... ok
test tests::reset_clears_state ... ok
test tests::rate_p02_property ... ok
test tests::rate_p01_anti_windup_holds_integral_at_bound ... ok
test tests::rate_p01_property ... ok

test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s

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 tests::at_zero_error_output_is_zero ... ok
test tests::fresh_pid_has_zero_state ... ok
test tests::negative_error_drives_negative_torque ... ok
test tests::out_of_range_dt_clamped_safely ... ok
test tests::positive_error_drives_positive_torque ... ok
test tests::rate_p02_infinite_setpoint_does_not_propagate ... ok
test tests::output_clamped_to_torque_max ... ok
test tests::rate_p02_nan_input_does_not_propagate ... ok
test tests::rate_p02_property ... ok
test tests::reset_clears_state ... ok
test tests::rate_p03_step_response_drives_error_to_zero ... ok
test tests::rate_p01_anti_windup_holds_integral_at_bound ... ok
test tests::rate_p01_property ... ok

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 tests::fresh_pid_has_zero_state ... ok
test tests::at_zero_error_output_is_zero ... ok
test tests::negative_error_drives_negative_torque ... ok
test tests::out_of_range_dt_clamped_safely ... ok
test tests::positive_error_drives_positive_torque ... ok
test tests::rate_p02_infinite_setpoint_does_not_propagate ... ok
test tests::rate_p02_nan_input_does_not_propagate ... ok
test tests::output_clamped_to_torque_max ... ok
test tests::rate_p03_step_response_drives_error_to_zero ... ok
test tests::reset_clears_state ... ok
test tests::rate_p01_anti_windup_holds_integral_at_bound ... ok
test tests::rate_p02_property ... ok
test tests::rate_p01_property ... ok

test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.60s

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 tests::deterministic_disturbance_recovers ... ok
test tests::deterministic_hover_settles ... ok
test tests::deterministic_attitude_cascade_passes ... ok
test tests::deterministic_step_response_passes ... ok
test tests::noisy_attitude_cascade_still_passes ... ok
test tests::plant_step_full_preserves_unit_quaternion_and_finite_state ... ok
test tests::plant_step_preserves_unit_quaternion ... ok
test tests::deterministic_mission_passes ... ok
test tests::noisy_step_response_still_passes ... ok
test tests::noisy_mission_still_reaches_waypoint ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

--- scenario: step ---
samples 5000
final ω (rad/s) [+0.5007, -0.3003, +0.4006]
peak ω above sp 0.0061 rad/s
overshoot 1.2 %
RMS error (steady) 0.0012 rad/s
convergence time 0.139s
loop wall time 711 µs
NaN/∞ seen false
outcome PASS
--- scenario: disturbance ---
samples 5000
final ω (rad/s) [+0.0000, -0.0042, +0.0000]
peak ω above sp 0.8958 rad/s
recovery time 0.141s after impulse
loop wall time 681 µs
NaN/∞ seen false
outcome PASS
--- scenario: hover ---
samples 5000
final ω (rad/s) [-0.0020, +0.0013, -0.0007]
peak ω above sp 0.7683 rad/s
convergence time 0.175s
loop wall time 729 µs
NaN/∞ seen false
outcome PASS
--- scenario: attitude ---
samples 5000
final ω (rad/s) [-0.0001, +0.0000, +0.0000]
peak attitude err 19.989°
RMS error (steady) 0.029° (last 1s)
convergence time 0.352s
loop wall time 894 µs
NaN/∞ seen false
outcome PASS
--- scenario: mission ---
samples 12000
final v (m/s NED) [-0.004, +0.000, +0.003]
peak distance error 10.000 m
final distance 0.010 m
RMS distance (steady)0.015 m (last 2s)
convergence time 4.045s
loop wall time 2189 µs
NaN/∞ seen false
outcome PASS
falcon-sitl-hover: PASS

running 9 tests
test tests::deterministic_across_ticks_with_same_time ... ok
test tests::fresh_stub_has_zero_time ... ok
test tests::innovation_is_quiet_in_stub ... ok
test tests::tick_passes_time_through ... ok
test tests::tick_returns_identity_quaternion ... ok
test tests::tick_returns_zero_position_and_velocity ... ok
test tests::unit_quaternion_check_rejects_clearly_non_unit ... ok
test tests::tick_innovation_within_healthy_range ... ok
test tests::tick_always_emits_unit_quaternion ... ok

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 tests::deterministic_across_ticks_with_same_time ... ok
test tests::innovation_is_quiet_in_stub ... ok
test tests::fresh_stub_has_zero_time ... ok
test tests::tick_passes_time_through ... ok
test tests::tick_returns_identity_quaternion ... ok
test tests::tick_innovation_within_healthy_range ... ok
test tests::tick_returns_zero_position_and_velocity ... ok
test tests::unit_quaternion_check_rejects_clearly_non_unit ... ok
test tests::tick_always_emits_unit_quaternion ... ok

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 tests::deterministic_across_ticks_with_same_time ... ok
test tests::fresh_stub_has_zero_time ... ok
test tests::innovation_is_quiet_in_stub ... ok
test tests::tick_passes_time_through ... ok
test tests::tick_returns_identity_quaternion ... ok
test tests::unit_quaternion_check_rejects_clearly_non_unit ... ok
test tests::tick_returns_zero_position_and_velocity ... ok
test tests::tick_innovation_within_healthy_range ... ok
test tests::tick_always_emits_unit_quaternion ... ok

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 33 tests
test crc::tests::accumulate_slice_equals_individual ... ok
test crc::tests::empty_input_keeps_seed ... ok
test crc::tests::mavlink_reference_vector_123456789 ... ok
test crc::tests::single_byte_zero ... ok
test crc::tests::order_matters ... ok
test frame::tests::encode_rejects_payload_length_mismatch ... ok
test frame::tests::encode_rejects_too_small_output ... ok
test frame::tests::frame_msg_id_three_bytes_little_endian ... ok
test frame::tests::frame_payload_length_byte_matches ... ok
test frame::tests::frame_starts_with_magic_v2 ... ok
test frame::tests::peek_message_id_finds_heartbeat ... ok
test frame::tests::peek_rejects_v1_magic ... ok
test frame::tests::rejects_bad_crc ... ok
test frame::tests::rejects_truncated_header ... ok
test frame::tests::rejects_truncated_payload ... ok
test frame::tests::rejects_v1_magic ... ok
test frame::tests::rejects_wrong_crc_extra ... ok
test frame::tests::round_trip_heartbeat_through_frame ... ok
test heartbeat::tests::crc_extra_is_fifty ... ok
test heartbeat::tests::custom_mode_little_endian ... ok
test heartbeat::tests::decode_empty_payload ... ok
test heartbeat::tests::decode_rejects_long_payload ... ok
test heartbeat::tests::decode_rejects_short_payload ... ok
test heartbeat::tests::field_offsets_match_spec ... ok
test heartbeat::tests::mav_mode_flag_or_and_contains ... ok
test heartbeat::tests::payload_length_constant ... ok
test heartbeat::tests::round_trip_falcon_default ... ok
test heartbeat::tests::round_trip_gcs_default ... ok
test heartbeat::tests::round_trip_max_values ... ok
test heartbeat::tests::round_trip_zero ... ok
test heartbeat::tests::round_trip_arbitrary ... ok
test frame::tests::encode_parse_round_trip_arbitrary_seq ... ok
test frame::tests::parser_never_panics ... ok

test result: ok. 33 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 33 tests
test crc::tests::accumulate_slice_equals_individual ... ok
test crc::tests::empty_input_keeps_seed ... ok
test crc::tests::mavlink_reference_vector_123456789 ... ok
test crc::tests::order_matters ... ok
test crc::tests::single_byte_zero ... ok
test frame::tests::encode_rejects_payload_length_mismatch ... ok
test frame::tests::encode_rejects_too_small_output ... ok
test frame::tests::frame_msg_id_three_bytes_little_endian ... ok
test frame::tests::frame_payload_length_byte_matches ... ok
test frame::tests::frame_starts_with_magic_v2 ... ok
test frame::tests::peek_message_id_finds_heartbeat ... ok
test frame::tests::peek_rejects_v1_magic ... ok
test frame::tests::encode_parse_round_trip_arbitrary_seq ... ok
test frame::tests::rejects_bad_crc ... ok
test frame::tests::rejects_truncated_header ... ok
test frame::tests::rejects_truncated_payload ... ok
test frame::tests::rejects_v1_magic ... ok
test frame::tests::rejects_wrong_crc_extra ... ok
test frame::tests::round_trip_heartbeat_through_frame ... ok
test heartbeat::tests::crc_extra_is_fifty ... ok
test heartbeat::tests::custom_mode_little_endian ... ok
test heartbeat::tests::decode_empty_payload ... ok
test heartbeat::tests::decode_rejects_long_payload ... ok
test heartbeat::tests::decode_rejects_short_payload ... ok
test heartbeat::tests::field_offsets_match_spec ... ok
test heartbeat::tests::mav_mode_flag_or_and_contains ... ok
test heartbeat::tests::payload_length_constant ... ok
test heartbeat::tests::round_trip_falcon_default ... ok
test heartbeat::tests::round_trip_gcs_default ... ok
test heartbeat::tests::round_trip_max_values ... ok
test heartbeat::tests::round_trip_zero ... ok
test heartbeat::tests::round_trip_arbitrary ... ok
test frame::tests::parser_never_panics ... ok

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 crc::tests::accumulate_slice_equals_individual ... ok
test crc::tests::empty_input_keeps_seed ... ok
test crc::tests::mavlink_reference_vector_123456789 ... ok
test crc::tests::order_matters ... ok
test crc::tests::single_byte_zero ... ok
test frame::tests::encode_rejects_payload_length_mismatch ... ok
test frame::tests::encode_rejects_too_small_output ... ok
test frame::tests::frame_msg_id_three_bytes_little_endian ... ok
test frame::tests::frame_payload_length_byte_matches ... ok
test frame::tests::frame_starts_with_magic_v2 ... ok
test frame::tests::peek_message_id_finds_heartbeat ... ok
test frame::tests::peek_rejects_v1_magic ... ok
test frame::tests::rejects_bad_crc ... ok
test frame::tests::rejects_truncated_header ... ok
test frame::tests::rejects_truncated_payload ... ok
test frame::tests::rejects_v1_magic ... ok
test frame::tests::rejects_wrong_crc_extra ... ok
test frame::tests::round_trip_heartbeat_through_frame ... ok
test heartbeat::tests::crc_extra_is_fifty ... ok
test heartbeat::tests::custom_mode_little_endian ... ok
test heartbeat::tests::decode_empty_payload ... ok
test heartbeat::tests::decode_rejects_long_payload ... ok
test heartbeat::tests::decode_rejects_short_payload ... ok
test heartbeat::tests::field_offsets_match_spec ... ok
test heartbeat::tests::mav_mode_flag_or_and_contains ... ok
test heartbeat::tests::payload_length_constant ... ok
test heartbeat::tests::round_trip_falcon_default ... ok
test heartbeat::tests::round_trip_gcs_default ... ok
test heartbeat::tests::round_trip_max_values ... ok
test heartbeat::tests::round_trip_zero ... ok
test heartbeat::tests::round_trip_arbitrary ... ok
test frame::tests::encode_parse_round_trip_arbitrary_seq ... ok
test frame::tests::parser_never_panics ... ok

test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.40s

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 tests::cross_of_parallel_is_zero ... ok
test tests::ekf_p01_tick_preserves_unit_quaternion ... ok
test tests::ekf_p02_extreme_accel_does_not_produce_nan ... ok
test tests::ekf_p02_zero_accel_does_not_produce_nan ... ok
test tests::ekf_p03_innovation_monotone_with_tilt_disagreement ... ok
test tests::ekf_p04_static_rest_converges_to_gravity_aligned ... ok
test tests::ekf_p05_pure_yaw_gyro_does_not_destabilise_attitude ... ok
test tests::fresh_estimator_is_at_identity ... ok
test tests::normalise_nan_returns_none ... ok
test tests::normalise_zero_returns_none ... ok
test tests::quat_mul_identity_left ... ok
test tests::quat_mul_identity_right ... ok
test tests::rotate_inverse_identity_passes_through ... ok
test tests::ekf_p01_property ... ok
test tests::bias_estimate_bounded ... ok
test tests::ekf_p02_property_sequence ... ok

test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s

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 tests::cross_of_parallel_is_zero ... ok
test tests::ekf_p01_tick_preserves_unit_quaternion ... ok
test tests::ekf_p02_extreme_accel_does_not_produce_nan ... ok
test tests::ekf_p02_zero_accel_does_not_produce_nan ... ok
test tests::ekf_p03_innovation_monotone_with_tilt_disagreement ... ok
test tests::ekf_p04_static_rest_converges_to_gravity_aligned ... ok
test tests::ekf_p05_pure_yaw_gyro_does_not_destabilise_attitude ... ok
test tests::fresh_estimator_is_at_identity ... ok
test tests::normalise_nan_returns_none ... ok
test tests::ekf_p01_property ... ok
test tests::normalise_zero_returns_none ... ok
test tests::quat_mul_identity_left ... ok
test tests::quat_mul_identity_right ... ok
test tests::rotate_inverse_identity_passes_through ... ok
test tests::ekf_p02_property_sequence ... ok
test tests::bias_estimate_bounded ... ok

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 tests::cross_of_parallel_is_zero ... ok
test tests::ekf_p01_tick_preserves_unit_quaternion ... ok
test tests::ekf_p02_extreme_accel_does_not_produce_nan ... ok
test tests::ekf_p02_zero_accel_does_not_produce_nan ... ok
test tests::ekf_p03_innovation_monotone_with_tilt_disagreement ... ok
test tests::ekf_p04_static_rest_converges_to_gravity_aligned ... ok
test tests::ekf_p05_pure_yaw_gyro_does_not_destabilise_attitude ... ok
test tests::fresh_estimator_is_at_identity ... ok
test tests::normalise_nan_returns_none ... ok
test tests::normalise_zero_returns_none ... ok
test tests::quat_mul_identity_left ... ok
test tests::quat_mul_identity_right ... ok
test tests::rotate_inverse_identity_passes_through ... ok
test tests::bias_estimate_bounded ... ok
test tests::ekf_p01_property ... ok
test tests::ekf_p02_property_sequence ... ok

test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.78s

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 tests::phases_are_consistent_with_trajectory_duration ... ok
test tests::quat_error_is_zero_for_identical_quaternions ... ok
test tests::rotate_ned_to_body_identity_passes_through ... ok
test tests::noisy_bench_passes_loose ... ok
test tests::deterministic_bench_passes ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

--- noise=0 (deterministic) ---
samples 5000
RMS error (full) 3.306°
RMS error (steady) 3.312° (last 2.5 s)
peak error 19.804°
final error 3.023°
convergence time 0.68s (first sustained <5°)
estimator wall time 626 µs
NaN/∞ seen false
falcon-ekf-bench: PASS

running 10 tests
test tests::att_p01_quaternion_error_is_unit_for_unit_inputs ... ok
test tests::att_p01_shortest_arc_q_err_scalar_non_negative ... ok
test tests::att_p03_small_angle_within_one_percent ... ok
test tests::degenerate_input_does_not_propagate_nan ... ok
test tests::identity_setpoint_at_identity_gives_zero_rate ... ok
test tests::negative_roll_setpoint_gives_negative_x_rate ... ok
test tests::rate_command_clamped_to_rate_max ... ok
test tests::sqrt_f32_matches_libm_within_tolerance ... ok
test tests::twenty_deg_roll_setpoint_gives_positive_x_rate ... ok
test tests::att_p01_property ... ok

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 tests::att_p01_quaternion_error_is_unit_for_unit_inputs ... ok
test tests::att_p01_shortest_arc_q_err_scalar_non_negative ... ok
test tests::degenerate_input_does_not_propagate_nan ... ok
test tests::att_p03_small_angle_within_one_percent ... ok
test tests::identity_setpoint_at_identity_gives_zero_rate ... ok
test tests::negative_roll_setpoint_gives_negative_x_rate ... ok
test tests::rate_command_clamped_to_rate_max ... ok
test tests::sqrt_f32_matches_libm_within_tolerance ... ok
test tests::twenty_deg_roll_setpoint_gives_positive_x_rate ... ok
test tests::att_p01_property ... ok

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 tests::att_p01_shortest_arc_q_err_scalar_non_negative ... ok
test tests::att_p03_small_angle_within_one_percent ... ok
test tests::att_p01_quaternion_error_is_unit_for_unit_inputs ... ok
test tests::degenerate_input_does_not_propagate_nan ... ok
test tests::identity_setpoint_at_identity_gives_zero_rate ... ok
test tests::negative_roll_setpoint_gives_negative_x_rate ... ok
test tests::rate_command_clamped_to_rate_max ... ok
test tests::sqrt_f32_matches_libm_within_tolerance ... ok
test tests::twenty_deg_roll_setpoint_gives_positive_x_rate ... ok
test tests::att_p01_property ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s

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 tests::deterministic_disturbance_recovers ... ok
test tests::deterministic_hover_settles ... ok
test tests::deterministic_attitude_cascade_passes ... ok
test tests::deterministic_step_response_passes ... ok
test tests::noisy_attitude_cascade_still_passes ... ok
test tests::plant_step_full_preserves_unit_quaternion_and_finite_state ... ok
test tests::plant_step_preserves_unit_quaternion ... ok
test tests::noisy_step_response_still_passes ... ok
test tests::deterministic_mission_passes ... ok
test tests::noisy_mission_still_reaches_waypoint ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

--- scenario: attitude ---
samples 5000
final ω (rad/s) [-0.0001, +0.0000, +0.0000]
peak attitude err 19.989°
RMS error (steady) 0.029° (last 1s)
convergence time 0.352s
loop wall time 892 µs
NaN/∞ seen false
outcome PASS
falcon-sitl-hover: PASS

running 9 tests
test tests::args_default_ports_for_gcs_mode ... ok
test tests::args_default_ports_for_vehicle_mode ... ok
test tests::args_rejects_missing_mode ... ok
test tests::args_rejects_unknown_mode ... ok
test tests::handle_inbound_propagates_bad_crc ... ok
test tests::handle_inbound_rejects_unsupported_message ... ok
test tests::handle_inbound_truncated ... ok
test tests::current_timestamp_is_monotone_within_a_run ... ok
test tests::vehicle_and_gcs_exchange_heartbeats_over_udp ... ok

test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s

[falcon-hello-demo] building release binary...
[falcon-hello-demo] launching gcs on 127.0.0.1:14700
[falcon-hello-demo] launching vehicle (4 Hz × 4s)
[falcon-hello-demo] vehicle sent 13 heartbeat(s)
[falcon-hello-demo] gcs received 13 heartbeat(s)
[falcon-hello-demo] PASS

falcon verification gate (filter: (has-tag "falcon"))

9 artifact(s) matched: FV-FALCON-POS-001, FV-FALCON-PIPELINE-001, FV-FALCON-MIX-001, FV-FALCON-RATE-001, FV-FALCON-EKF-STUB-001, FV-FALCON-MAVLINK-001, FV-FALCON-EKF-001, FV-FALCON-ATT-001, FV-FALCON-WORLD-001

[ PASS] ( 8.33s) FV-FALCON-POS-001: cargo test -p relay-pos
[ PASS] ( 10.64s) FV-FALCON-POS-001: cargo test -p relay-pos --release
[ PASS] ( 0.18s) FV-FALCON-POS-001: PROPTEST_CASES=4096 cargo test -p relay-pos
[ PASS] ( 0.29s) FV-FALCON-POS-001: cargo test -p falcon-sitl-hover
[ PASS] ( 0.42s) FV-FALCON-POS-001: cargo run -q -p falcon-sitl-hover --release -- --scenario mission
[ PASS] ( 0.15s) FV-FALCON-PIPELINE-001: cargo test -p falcon-mix-component
[ PASS] ( 0.15s) FV-FALCON-PIPELINE-001: cargo test -p falcon-rate-component
[ PASS] ( 0.15s) FV-FALCON-PIPELINE-001: cargo test -p falcon-mix-component --release
[ PASS] ( 0.15s) FV-FALCON-PIPELINE-001: cargo test -p falcon-rate-component --release
[ PASS] ( 0.33s) FV-FALCON-MIX-001: cargo test -p relay-mix-quad
[ PASS] ( 0.75s) FV-FALCON-MIX-001: cargo test -p relay-mix-quad --release
[ PASS] ( 0.16s) FV-FALCON-MIX-001: PROPTEST_CASES=4096 cargo test -p relay-mix-quad
[ PASS] ( 0.40s) FV-FALCON-RATE-001: cargo test -p relay-rate
[ PASS] ( 0.77s) FV-FALCON-RATE-001: cargo test -p relay-rate --release
[ PASS] ( 0.67s) FV-FALCON-RATE-001: PROPTEST_CASES=4096 cargo test -p relay-rate
[ PASS] ( 0.06s) FV-FALCON-RATE-001: cargo test -p falcon-sitl-hover
[ PASS] ( 0.04s) FV-FALCON-RATE-001: cargo run -q -p falcon-sitl-hover --release
[ PASS] ( 0.34s) FV-FALCON-EKF-STUB-001: cargo test -p relay-ekf-stub
[ PASS] ( 0.72s) FV-FALCON-EKF-STUB-001: cargo test -p relay-ekf-stub --release
[ PASS] ( 0.15s) FV-FALCON-EKF-STUB-001: PROPTEST_CASES=4096 cargo test -p relay-ekf-stub
[ PASS] ( 0.44s) FV-FALCON-MAVLINK-001: cargo test -p relay-mavlink
[ PASS] ( 1.02s) FV-FALCON-MAVLINK-001: cargo test -p relay-mavlink --release
[ PASS] ( 0.47s) FV-FALCON-MAVLINK-001: PROPTEST_CASES=4096 cargo test -p relay-mavlink
[ PASS] ( 0.40s) FV-FALCON-EKF-001: cargo test -p relay-ekf
[ PASS] ( 0.81s) FV-FALCON-EKF-001: cargo test -p relay-ekf --release
[ PASS] ( 0.85s) FV-FALCON-EKF-001: PROPTEST_CASES=4096 cargo test -p relay-ekf
[ PASS] ( 0.15s) FV-FALCON-EKF-001: cargo test -p falcon-ekf-bench
[ PASS] ( 0.18s) FV-FALCON-EKF-001: cargo run -q -p falcon-ekf-bench --release
[ PASS] ( 0.33s) FV-FALCON-ATT-001: cargo test -p relay-att
[ PASS] ( 0.55s) FV-FALCON-ATT-001: cargo test -p relay-att --release
[ PASS] ( 0.17s) FV-FALCON-ATT-001: PROPTEST_CASES=4096 cargo test -p relay-att
[ PASS] ( 0.06s) FV-FALCON-ATT-001: cargo test -p falcon-sitl-hover
[ PASS] ( 0.04s) FV-FALCON-ATT-001: cargo run -q -p falcon-sitl-hover --release -- --scenario attitude
[ PASS] ( 0.29s) FV-FALCON-WORLD-001: cargo test -p falcon-hello
[ PASS] ( 4.68s) FV-FALCON-WORLD-001: scripts/falcon-hello-demo.sh

✅ Rivet verification gate — falcon

9/9 passed

count
Passed 9
Failed 0
Skipped (no steps) 0

Source of truth: artifacts/verification/FV-FALCON-*.yaml.

@avrabe avrabe merged commit 09fb293 into main May 20, 2026
6 of 7 checks passed
@avrabe avrabe deleted the falcon/v0.6 branch May 20, 2026 05:49
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