Add HPO support in SygnalInterfaceSocketcan via parse-ordering arbitration - #26
Merged
eric-polymath merged 3 commits intoMay 20, 2026
Conversation
…implementation deffered to a separate commit
…ia parse ordering
eric-polymath
deleted the
eric/sygnal_can_interface_hpo_handling_tactical_norefactor
branch
May 20, 2026 21:50
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.
Summary
Wires SygnalHpoInterface (landed in the prior PR) into SygnalInterfaceSocketcan and the ROS 2 node so HPO boards can be commanded and observed end-to-end. Tactical fix for now, proper per-board refactor + multi-protocol PRD deferred.
Detailed change log
Lib:
New HpoId struct + SendHpoCommandResult; constructor extended with optional hpo_ids (defaults to {}, zero behavior change for existing callers).
sendHpoControlEnable / sendHpoControlCommand + get_hpo_interface_states / get_hpo_overall_interface_state accessors.
parse() rewired: HPO parsers run before the existing MCM control-response parser, with a DO NOT REORDER comment block explaining why.
Constructor throws std::invalid_argument if any HPO and MCM share a bus address.
HPO_NUM_INTERFACES corrected from 7 → 5 to match real hardware (DBC defines 7, only 5 are wired). Matches MCM precedent.
ROS 2:
New hpo_endpoints:
int_array parameter (default []).
parse_hpo_id helper + hpo_ids_ member; passes vector through to the socketcan ctor.
Tests:
New always-on sygnal_interface_socketcan_routing_tests (6 cases / 29 assertions): disjoint-address ctor check, HPO/MCM heartbeat routing, HPO control-response non-disturbance of MCM queues.
Existing HPO interface tests updated for the 5-interface array length (17 cases / 74 assertions, green).
Why this works (CAN-ID arbitration mitigation)
Sygnal overloads CAN IDs across device types — 0x161 ControlCommandResponse carries different byte layouts depending on whether MCM or HPO produced it. The only field with stable semantics across layouts is the 7-bit BusAddress. We exploit two invariants:
Routing order :
parse() tries HPO parsers (which filter by bus_address) before SygnalControlInterface::parseCommandResponseFrame (which doesn't filter). Anything addressed to an HPO is claimed first; what reaches the MCM parser by elimination is MCM.
Disjoint bus addresses — enforced at construction time so the routing-by-elimination is sound.
What's deferred
Proper per-board refactor (move MCM control parse/pack into SygnalMcmInterface, delete SygnalControlInterface).
IO board, relay refactor, error-frame surfacing.
Multi-protocol/multi-version PRD (Emerson's thread).
Count8 rolling counter — still hard-coded to 0.
Breaking changes
None — existing two-arg constructor still works; mcm_endpoints param unchanged; legacy MCM behavior untouched.
Test plan
colcon test --packages-select sygnal_can_interface_lib green
colcon build --packages-up-to sygnal_can_interface_ros2 clean
On LEV05: send HPO ControlEnable + ControlCommand, observe heartbeat reflecting the command
Confirm misconfigured hpo_endpoints overlapping an MCM throws at node configure