feat(ops243): add internal hardware trigger - #221
Conversation
Updated the Raspberry Pi retest checklist to clarify merging requirements and added a note about regression testing the sound trigger.
There was a problem hiding this comment.
Pull request overview
Adds an opt-in OPS243 internal hardware-trigger strategy for rolling-buffer capture, threading new configuration flags through the kiosk script and server so installations without the external sound-trigger module can still capture I/Q history (while keeping sound-trigger as the default).
Changes:
- Add OPS243 driver support for configuring, waiting on, parsing, and re-arming the internal speed-trigger rolling-buffer dump (firmware-gated to v1.3.1).
- Extend server/kiosk CLI plumbing with
--trigger hardwareplus hardware-mode defaults/overrides (threshold, magnitude, pre-trigger split) and corresponding validation. - Add focused tests and documentation for the new trigger mode and its operational constraints.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_start_kiosk.py | Verifies kiosk CLI forwarding behavior for hardware trigger defaults and overrides. |
| tests/test_server.py | Adds server CLI parsing/forwarding tests for hardware trigger mode and its constraints. |
| tests/test_rolling_buffer.py | Registers/validates the new trigger strategy and adds behavior tests for accept/reject/re-arm flows. |
| tests/test_ops243.py | Adds focused OPS243 command-ordering, validation, re-arm, and recovery tests for internal triggering. |
| src/openflight/server.py | Adds hardware trigger CLI flags/validation and threads trigger kwargs into monitor startup. |
| src/openflight/rolling_buffer/trigger.py | Implements HardwareTriggeredCapture strategy around board-managed trigger + host-side validation + re-arm. |
| src/openflight/rolling_buffer/monitor.py | Configures OPS243 internal trigger on connect when trigger_type == "hardware". |
| src/openflight/rolling_buffer/init.py | Exposes HardwareTriggeredCapture from the rolling_buffer package. |
| src/openflight/ops243.py | Implements firmware validation, internal-trigger configuration, re-arm, and UART recovery behavior. |
| scripts/start-kiosk.sh | Adds kiosk flag parsing and forwarding for hardware-trigger-specific settings. |
| README.md | Documents the new opt-in hardware trigger mode and links to the new guide. |
| docs/rolling_buffer_spin_detection.md | Clarifies the default sound-trigger pipeline and references the new hardware trigger option. |
| docs/hardware-trigger.md | New guide describing command ordering, defaults, and retest expectations for internal triggering. |
| docs/CHANGELOG.md | Adds an Unreleased changelog entry describing the new hardware trigger mode and constraints. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This is great, and much needed. However we are waiting on Omnipresence for a way to update OPS radars to this version that doesn't require their extra device. Will ping them again to see if this is a realistic ask. |
|
So do we have the hex file to flash with the new firmware? |
Send an email to Rob at customerservice@omnipresense.com. He will be able to get you the file once it's public and help you find the correct model SEGGER. |
|
Review note: Correcting my earlier version of this comment: I claimed boards reporting 1.5.2 would be blocked today. AN-010 rev AE Table 9 shows the OPS243-A line runs 1.2.3 → 1.3.1, with the |
|
Docs suggestion for
Also worth a warning: AN-013 says never press Erase — it wipes factory settings and persistent memory, which is where Not blocking; the code change is unaffected. |
Possible cheap path. The OPS243's I/O is 3.3 V (this repo already wires Pi GPIO straight to J3 with no level shifter), and the XMC4500/4700 speaks SWD, which OpenOCD supports via its in-tree Caveats: XMCFlasher won't drive a CMSIS-DAP probe, so this is OpenOCD-only and off the vendor-supported path. Unverified on this board: BMI/boot-mode handling (J-Link does it automatically) and whether the part is read-protected. J2 is a keyed fine-pitch header, so it needs a proper cable — worth asking OmniPreSense for the pinout. Vendor-blessed alternative: the SEGGER J-Link EDU Mini, which AN-013 links directly (adafruit.com/product/3571, $75.95). Worth 30 minutes on a spare board. I wouldn't try it on the only radar in a build. |
Email sent! |
|
Instructions on how to apply the firmware update: |
What does this PR do?
Adds an opt-in OPS243 internal hardware-trigger capture strategy for rolling-buffer mode.
--trigger hardwarewith hardware-mode defaults of a 25 mph outbound threshold,SM25,S#6, and 30 ksps.GC.--sound-pre-triggerbehavior.Why was this required?
The existing rolling-buffer path depends on the external SEN-14262 sound-trigger edge. The OPS243 can perform the speed-trigger decision internally, allowing installations with the internal trigger wiring to capture the rolling I/Q history without requiring the sound-trigger module.
This is opt-in so existing installations continue to use sound mode unchanged. Hardware mode is intentionally limited to the OPS243 trigger path; unrelated experimental analysis, replay, board-diagnostic, clock, and UI work is not included.
Automated tests
PYTHONPATH=src uv run --no-sync pytest tests/ -q: 1,352 passed, 8 skipped, 17 warningsuv run --no-sync ruff check src/openflight/: passeduv run --no-sync pylint src/openflight/ --fail-under=9: passed, 9.72/10cd ui && npm run build: passedcd ui && npm run lint: passedThe focused tests cover command ordering, firmware and parameter validation, dump-boundary filtering, dump parsing, re-arm behavior and recovery, accepted/rejected captures, strategy selection, and CLI forwarding.
Manual (human) testing
Hardware testing was performed with an OPS243 running firmware v1.3.1.
SM25setting.S#6produced the best ball/club parsing compared withS#4andS#8.Initial with ball.jsonlsession recorded 18 hardware-trigger shot outputs with zero logged errors.swing_only_no_ball.jsonlsession recorded 4 accepted no-ball outputs with zero logged errors, documenting the limitation above.hit-0005andhit-0006produced usable ball/club outputs. The rail-adjacent energy in the I/Q view was the club passing close to the sensor and did not prevent useful output parsing.Checklist