CAN-FD¶
CAN-FD is supported. A bus opened in FD mode uses the kernel's CAN-FD
frame format (CAN_RAW_FD_FRAMES), can carry payloads up to 64 bytes, and
preserves the bit-rate-switch (BRS) and error-state (ESI) flags. Classical CAN
remains the default and is unchanged when FD is off.
Enabling FD¶
The interface itself must be CAN-FD-capable. For a virtual interface:
sudo ip link add dev vcanfd0 type vcan
sudo ip link set vcanfd0 mtu 72 # 72 = sizeof(struct canfd_frame)
sudo ip link set up vcanfd0
TOML config — set fd = true on the bus (see
configs/openarm_canfd.toml):
[bus.main]
kind = "socketcan"
interface = "canfd0"
fd = true
vendor = "damiao"
Rust:
let bus = can_motor_control::SocketCanBus::open("canfd0", /* fd_enabled = */ true)?;
assert!(bus.capabilities().supports_fd);
Python:
import can_motor_control
bus = can_motor_control.SocketCanBus("canfd0", fd=True)
How format is chosen¶
A bus advertises [BusCapabilities]: classical() (8-byte cap) or fd()
(64-byte cap). This is the single source of truth — upper layers (Robot,
Arm, Gripper, MotorGroup) never branch on frame format.
| Layer | Behavior |
|---|---|
SocketCanBus |
Opened with fd=true → sets CAN_RAW_FD_FRAMES, advertises fd(). Sends a frame as canfd_frame iff its FD_FORMAT flag is set, otherwise as a classical can_frame — an FD socket carries both. |
validate_send |
Rejects an FD frame on a classical bus (FdFrameOnNonFdBus). |
MotorCodec::bind_to_bus(caps) |
The codec keys decode/emit decisions off the bound capabilities. |
DamiaoCodec |
Conservative: emits classical 8-byte frames on any bus (those are valid CAN-FD frames). When bound to an FD bus it additionally accepts FD-format state frames on decode; bound classical, it reproduces the v1 byte layout exactly. |
Scope¶
Enabling FD unlocks the FD transport path and FD-frame decode. It does not, by itself, widen Damiao command payloads beyond 8 bytes — Damiao's v1 command/state protocol is 8-byte. A vendor protocol that genuinely needs
8-byte payloads can now build on a working FD transport.
BRS data-phase bitrate is taken from the interface's configured dbitrate; the
BRS flag is preserved on frames but not tuned by this library.
Testing without FD hardware¶
MockCanBus::new_fd(name) (Rust) advertises FD capabilities and loops FD frames
back, so the FD send/receive and codec-gating paths are exercisable in CI
without an FD-capable interface. The SocketCAN FD path itself is validated
against a real or virtual FD interface during hardware bring-up.