axiomatic_adapter
An Adapter Library and socketcan bridge for Axiomatic eth-can interface
README
Axiomatic Adapter
Library and Adapter for the Axiomatic CAN-ETH converter.
For more information on the decoding/endcoding and product, see the links below:
https://www.notion.so/polymathrobotics/Axiomatic-CAN-to-Ethernet-Converter-08e078d8914f40d6b7cd99ebf39fe1b0
https://products.axiomatic.com/viewitems/connectivity/ethernet-can-converters
Usage
Socketcan-Axiomatic Bridge
ros2 run axiomatic_adapter axiomatic_socketcan_bridge [CAN_INTERFACE_NAME] [IP_ADDRESS] [PORT] [OPTIONAL]--retry-connection[-r] [OPTIONAL]--max-retry-attempts [OPTIONAL]--verbose[-v] [OPTIONAL]--no-tcp-nodelay
# Examples
# generic example to bridge vcan0 with axiomatic using 192.168.50.34:4000
ros2 run axiomatic_adapter axiomatic_socketcan_bridge vcan0 192.168.50.34 4000
# this will continue retrying to connect forever and not exit on first failure. It will also print more detailed logs
ros2 run axiomatic_adapter axiomatic_socketcan_bridge vcan0 192.168.50.34 4000 -r -v
# this will attempt to reconnect a max number of 100 times before failing
ros2 run axiomatic_adapter axiomatic_socketcan_bridge vcan0 192.168.50.34 4000 -r --max-retry-attempts 100
# disable TCP_NODELAY (re-enable Nagle's algorithm). Default is on; only use if
# you are pushing bulk traffic where throughput matters more than per-frame latency.
# See the Library section below for the full tradeoff discussion.
ros2 run axiomatic_adapter axiomatic_socketcan_bridge vcan0 192.168.50.34 4000 --no-tcp-nodelay
Library
// construct the adapter
std::string ip_address = "192.168.0.34";
std::string port = "4000";
std::chrono::milliseconds receive_timeout_ms(100);
// the two functions passed in are the receive and error callback functions, receive timeout has a default
polymath::can::AxiomaticAdapter adapter(
ip_address,
port,
[](std::unique_ptr<const CanFrame> /*frame*/) { /* No-op */ },
[](polymath::can::AxiomaticAdapter::socket_error_string_t /*error*/) { /*do nothing*/ },
receive_timeout_ms,
/*tcp_nodelay=*/true // optional, defaults to true; see below
);
// open the socket
adapter.openSocket();
// start the reception thread. At this point, it's running
adapter.startReceptionThread();
// on shutdown/destruction, thread will join and socket will close
tcp_nodelay parameter
Controls whether TCP_NODELAY is set on the socket after a successful connect.
Defaults to true.
true(default): Nagle’s algorithm is disabled. Each CAN frame leaves the host as its own TCP segment. The converter’s delayed-ACK behaviour otherwise interacts with Nagle to produce 30–450 ms inter-segment stalls under sustained CAN traffic, which breaks UDS-style request/response timing (flash sessions, control loops). This is the right choice for any latency-sensitive workload.false: Nagle’s algorithm stays enabled. The kernel may coalesce many small CAN frames into fewer, larger TCP segments. This lowers packets-per-second on the network and reduces per-segment header overhead (~40 bytes IP+TCP per ~24 byte CAN frame payload), at the cost of much higher worst-case latency per individual frame. Useful only if you are pushing bulk data where overall throughput matters more than per-frame latency, or if the network path / receiving device cannot keep up at high PPS.
If you have any doubt, leave it at the default.
KNOWN ISSUES
Axiomatic-specific heartbeat messages are not handled and are deliberately skipped. Using TCP, this does not cause issues. In future updates heartbeat messages should be consumed and sent as needed
Axiomatic-specific status messages are ignored and deliberately skipped. In future revisions this should be handled and reported as necessary.
CAN FD is not supported
Only TCP mode is supported; no UDP support (heartbeats are required for UDP support)