Documentation Index
Fetch the complete documentation index at: https://motorbridge.seeedstudio.com/llms.txt
Use this file to discover all available pages before exploring further.
motorbridge
Unified CAN motor control stack with a vendor-agnostic Rust core, stable C ABI, and Python/C++ bindings.
Chinese version: README.zh-CN.md
Companion Repos
Transport Legend
[STD-CAN]: classic CAN path (socketcan/pcan)
[CAN-FD]: dedicated FD path (socketcanfd)
[DM-SERIAL]: Damiao serial-bridge path (dm-serial)
Current status:
[CAN-FD] has been integrated as an independent transport path.
- No motor model is officially marked as CAN-FD validated in this repository yet.
Current Vendor Support
- Damiao:
- models:
3507, 4310, 4310P, 4340, 4340P, 6006, 8006, 8009, 10010L, 10010, H3510, G6215, H6220, JH11, 6248P
- modes:
scan, enable, disable, MIT, POS_VEL, VEL, FORCE_POS, set-id, set-zero
- RobStride:
- models:
rs-00, rs-01, rs-02, rs-03, rs-04, rs-05, rs-06
- modes:
scan, ping, enable, disable, MIT, POS_VEL, VEL, parameter read/write, set-id, zero
- host/feedback default:
0xFD (with 0xFF/0xFE fallback probing)
- model selection is required for real hardware use: use the actual
rs-00..rs-06 model for limits/logging; parameter read/write uses the common RobStride section 4 runtime table
- note: torque/current control is currently parameter-level only (
write-param on iq_ref/limits), not a first-class unified mode
- MyActuator:
- models:
X8 (runtime string; protocol is ID-based)
- modes:
scan, enable, disable, stop, set-zero, status, current, vel, pos, version, mode-query
- HighTorque:
- models:
hightorque (runtime string; native ht_can v1.5.5)
- modes:
scan, read, mit, pos-vel, vel, stop, brake, rezero
- Hexfellow:
- models:
hexfellow (runtime string; CANopen profile)
- modes:
scan, status, enable, disable, pos-vel, mit (via socketcanfd)
Update (2026-04): Damiao / RobStride Capability Convergence
- Damiao production baseline now covers:
scan / enable / disable / MIT / POS_VEL / VEL / FORCE_POS / set-id / set-zero.
- RobStride production baseline now covers:
scan / ping / enable / disable / MIT / POS_VEL / VEL / parameter read-write / set-id / zero.
- RobStride RS00-RS06 keep the same unified control command shape. Runtime parameter read/write uses the common section 4 table (
0x7005..0x702E); --model remains the physical model hint for limits/logging.
- RobStride default host/feedback path is
0xFD; scan now tries 0xFD,0xFF,0xFE,0x00,0xAA by default.
- RobStride
feedback_id / host_id is host-side addressing, not the motor device_id; scan hits report the motor ID as probe / device_id.
- In RobStride
pos-vel, --vel/--kd/--tau are intentionally ignored and reported as warnings (no hard error).
Architecture
Layered Runtime View
Workspace Topology (Latest)
Python Binding Surface (v0.1.7+)
Quick Start
Build:
Bring up CAN:
sudo ip link set can0 down 2>/dev/null || true
sudo ip link set can0 type can bitrate 1000000 restart-ms 100
sudo ip link set can0 up
ip -details link show can0
Quick CAN restart (Linux):
# default: can0 / 1Mbps / restart-ms=100 / loopback off
IF=can0; BITRATE=1000000; RESTART_MS=100; LOOPBACK=off
sudo ip link set "$IF" down 2>/dev/null || true
if [ "$LOOPBACK" = "on" ]; then
sudo ip link set "$IF" type can bitrate "$BITRATE" restart-ms "$RESTART_MS" loopback on
else
sudo ip link set "$IF" type can bitrate "$BITRATE" restart-ms "$RESTART_MS" loopback off
fi
sudo ip link set "$IF" up
ip -details link show "$IF"
Damiao CLI:
cargo run -p motor_cli --release -- \
--vendor damiao --channel can0 --model 4340P --motor-id 0x01 --feedback-id 0x11 \
--mode mit --pos 0 --vel 0 --kp 20 --kd 1 --tau 0 --loop 50 --dt-ms 20
[STD-CAN]
Hexfellow CLI:
cargo run -p motor_cli --release -- \
--vendor hexfellow --transport socketcanfd --channel can0 \
--model hexfellow --motor-id 1 --feedback-id 0 \
--mode status
[CAN-FD]
RobStride CLI:
cargo run -p motor_cli --release -- \
--vendor robstride --channel can0 --model rs-06 --motor-id 127 \
--mode vel --vel 0.3 --loop 40 --dt-ms 50
For RobStride, replace --model rs-06 with the actual motor model (rs-00 through rs-06) for limits/logging. read-param / write-param uses the common section 4 runtime table.
HighTorque CLI (native ht_can v1.5.5):
cargo run -p motor_cli --release -- \
--vendor hightorque --channel can0 --model hightorque --motor-id 1 \
--mode read
RobStride CLI parameter read:
cargo run -p motor_cli --release -- \
--vendor robstride --channel can0 --model rs-06 --motor-id 127 \
--mode read-param --param-id 0x7019
MyActuator CLI:
cargo run -p motor_cli --release -- \
--vendor myactuator --channel can0 --model X8 --motor-id 1 --feedback-id 0x241 \
--mode status --loop 20 --dt-ms 50
Unified scan (all vendors):
cargo run -p motor_cli --release -- \
--vendor all --channel can0 --mode scan --start-id 1 --end-id 255
Focused RobStride scan (Rust CLI and Python CLI use the same host-id defaults):
cargo run -p motor_cli --release -- \
scan --vendor robstride --channel can0 --start-id 1 --end-id 127 \
--feedback-ids 0xFD,0xFF,0xFE,0x00,0xAA
motorbridge-cli scan \
--vendor robstride --channel can0 --start-id 1 --end-id 127 \
--feedback-ids 0xFD,0xFF,0xFE,0x00,0xAA
Experimental Windows Support (PCAN-USB)
Linux remains the primary target. Windows support is experimental and currently backed by PEAK PCAN (PCANBasic.dll).
- Install PEAK PCAN driver + PCAN-Basic runtime on Windows.
- Channel mapping:
can0 -> PCAN_USBBUS1
can1 -> PCAN_USBBUS2
- Optional bitrate suffix:
@<bitrate> (for example can0@1000000).
Validation commands on Windows:
# Scan Damiao IDs
cargo run -p motor_cli --release -- --vendor damiao --channel can0@1000000 --model 4340P --motor-id 0x01 --feedback-id 0x11 --mode scan --start-id 1 --end-id 16
# Move motor #1 (4340P) to +pi rad (~180 deg)
cargo run -p motor_cli --release -- --vendor damiao --channel can0@1000000 --model 4340P --motor-id 0x01 --feedback-id 0x11 --mode pos-vel --pos 3.1416 --vlim 2.0 --loop 1 --dt-ms 20
# Move motor #7 (4310) to +pi rad (~180 deg)
cargo run -p motor_cli --release -- --vendor damiao --channel can0@1000000 --model 4310 --motor-id 0x07 --feedback-id 0x17 --mode pos-vel --pos 3.1416 --vlim 2.0 --loop 1 --dt-ms 20
macOS PCAN Runtime (PCBUSB)
This project supports PCAN on macOS via MacCAN’s PCBUSB runtime.
On macOS, PCANBasic.dll is not used.
1. Prerequisites
- A PEAK-compatible USB-CAN adapter recognized by macOS.
motorbridge source built on macOS.
- Bundled archive in this repo:
third_party/pcan/macos/macOS_Library_for_PCANUSB_v0.13.tar.gz.
- Or download directly from GitHub:
2. Quick install from bundled archive (recommended)
Use the helper script from repo root:
# user-local install (no sudo, recommended)
./scripts/setup_pcbusb_macos.sh --user-local
# system install (uses package install.sh, requires sudo)
./scripts/setup_pcbusb_macos.sh --system
If you use --user-local, run motor_cli with:
DYLD_LIBRARY_PATH=$HOME/.local/lib ./target/release/motor_cli ...
3. Manual install PCBUSB (system-wide)
If you want to download manually first:
mkdir -p /tmp/motorbridge-pcan && cd /tmp/motorbridge-pcan
curl -L -o macOS_Library_for_PCANUSB_v0.13.tar.gz \
https://raw.githubusercontent.com/tianrking/motorbridge/main/third_party/pcan/macos/macOS_Library_for_PCANUSB_v0.13.tar.gz
Then install:
tar -xzf macOS_Library_for_PCANUSB_v0.13.tar.gz
cd PCBUSB
sudo ./install.sh
The installer places:
libPCBUSB.dylib into /usr/local/lib
PCBUSB.h into /usr/local/include
4. Optional user-local install (no sudo)
If your user cannot write to /usr/local, use a local runtime path:
mkdir -p ~/.local/lib ~/.local/include
cp PCBUSB/libPCBUSB.0.13.dylib ~/.local/lib/
ln -sf ~/.local/lib/libPCBUSB.0.13.dylib ~/.local/lib/libPCBUSB.dylib
cp PCBUSB/PCBUSB.h ~/.local/include/
Then run motor_cli with:
DYLD_LIBRARY_PATH=$HOME/.local/lib ./target/release/motor_cli ...
5. Verify runtime loading
python3 - <<'PY'
from can.interfaces.pcan.basic import PCANBasic
PCANBasic()
print("PCBUSB load OK")
PY
If using user-local install:
DYLD_LIBRARY_PATH=$HOME/.local/lib python3 - <<'PY'
from can.interfaces.pcan.basic import PCANBasic
PCANBasic()
print("PCBUSB load OK")
PY
6. Build motorbridge CLI
cargo build -p motor_cli --release
7. Channel mapping on macOS (PCAN backend)
can0 maps to PCAN_USBBUS1
can1 maps to PCAN_USBBUS2
- Optional bitrate suffix is supported (example:
can0@1000000)
8. Scan motors (Damiao)
./target/release/motor_cli \
--vendor damiao --channel can0 --mode scan --start-id 1 --end-id 16
If using user-local PCBUSB:
DYLD_LIBRARY_PATH=$HOME/.local/lib ./target/release/motor_cli \
--vendor damiao --channel can0 --mode scan --start-id 1 --end-id 16
9. Control example (Damiao MIT)
Replace motor-id and feedback-id with your scan hits.
./target/release/motor_cli \
--vendor damiao --channel can0 --model 4310 \
--motor-id 0x02 --feedback-id 0x12 \
--mode mit --pos 0 --vel 0 --kp 20 --kd 1 --tau 0 \
--loop 50 --dt-ms 20
10. Troubleshooting
load PCBUSB failed ...:
- Install PCBUSB with
install.sh, or export DYLD_LIBRARY_PATH for local install.
No CAN backend for current platform:
- Use a build that includes the macOS PCAN backend.
hits=0 on scan:
- Check wiring, power, termination resistor, and CAN bitrate.
Linux USB-CAN (slcan) Quick Guide
Linux uses SocketCAN interface names directly (for example can0, slcan0).
Do not pass bitrate suffix in Linux channel names (for example can0@1000000 is invalid on Linux SocketCAN).
Bring up an slcan adapter as slcan0:
sudo slcand -o -c -s8 /dev/ttyUSB0 slcan0
sudo ip link set slcan0 up
ip -details link show slcan0
Then use slcan0 as CLI channel:
cargo run -p motor_cli --release -- --vendor damiao --channel slcan0 --mode scan --start-id 1 --end-id 255
Damiao Dedicated CAN-FD Transport (socketcanfd)
Use this Linux-only transport when you want an independent CAN-FD path without changing existing classic CAN or dm-serial behavior.
# Bring up CAN-FD interface first
scripts/canfd_restart.sh can0
# Damiao over dedicated socketcanfd transport
cargo run -p motor_cli --release -- --vendor damiao \
--transport socketcanfd --channel can0 \
--model 4310 --motor-id 0x04 --feedback-id 0x14 \
--mode mit --verify-model 0 --ensure-mode 0 \
--pos 0.5 --vel 0 --kp 20 --kd 1 --tau 0 --loop 80 --dt-ms 20
[CAN-FD] (transport integrated; motor verification matrix pending)
Damiao Serial Bridge Quick Guide (dm-serial)
Use this path only when your Damiao adapter exposes a serial bridge (for example /dev/ttyACM1) and you want to run Damiao through that private transport:
# Damiao scan over serial bridge
cargo run -p motor_cli --release -- --vendor damiao \
--transport dm-serial --serial-port /dev/ttyACM1 --serial-baud 921600 \
--model 4310 --mode scan --start-id 1 --end-id 16
# Damiao MIT over serial bridge
cargo run -p motor_cli --release -- --vendor damiao \
--transport dm-serial --serial-port /dev/ttyACM1 --serial-baud 921600 \
--model 4310 --motor-id 0x04 --feedback-id 0x14 \
--mode mit --verify-model 0 --ensure-mode 0 \
--pos 0.5 --vel 0 --kp 20 --kd 1 --tau 0 --loop 80 --dt-ms 20
[DM-SERIAL]
CAN Debugging (Professional Playbook)
For deterministic troubleshooting of Linux slcan and Windows pcan, use:
Interpretation:
vendor=damiao id=<n> means one Damiao motor is online at motor ID <n>.
vendor=robstride ... probe=<n> ... device_id=<n> means one RobStride motor responded at motor/device ID <n>.
- In RobStride output,
feedback_id / host_id such as 0xFD or 0xFE is not the motor ID.
vendor=hightorque ... [hit] id=<n> ... means one HighTorque motor responded via native ht_can v1.5.5.
vendor=myactuator id=<n> means one MyActuator motor responded.
hits=<k> at the end of each scan block is the count of discovered devices.
ABI and Bindings
- C ABI:
motor_controller_new_socketcan(channel)
motor_controller_new_dm_serial(serial_port, baud) (Damiao-only serial bridge; cross-platform, e.g. /dev/ttyACM0 or COM3)
- Damiao:
motor_controller_add_damiao_motor(...)
- Hexfellow:
motor_controller_add_hexfellow_motor(...) (CAN-FD path via socketcanfd)
- RobStride:
motor_controller_add_robstride_motor(...)
- MyActuator:
motor_controller_add_myactuator_motor(...)
- HighTorque:
motor_controller_add_hightorque_motor(...)
- Python:
Controller(channel="can0")
Controller.from_dm_serial("/dev/ttyACM0", 921600) (Damiao-only)
Controller.add_damiao_motor(...)
Controller.add_hexfellow_motor(...)
Controller.add_robstride_motor(...)
Controller.add_myactuator_motor(...)
Controller.add_hightorque_motor(...)
- C++:
Controller("can0")
Controller::from_dm_serial("/dev/ttyACM0", 921600) (Damiao-only)
Controller::add_damiao_motor(...)
Controller::add_hexfellow_motor(...)
Controller::add_robstride_motor(...)
Controller::add_myactuator_motor(...)
Controller::add_hightorque_motor(...)
Unified mode IDs for ABI/Bindings (ensure_mode):
1 = MIT
2 = POS_VEL
3 = VEL
4 = FORCE_POS
Unified control units:
- position:
rad
- velocity:
rad/s
- torque:
Nm
Vendor-specific protocol naming/mapping and unsupported operations are documented in:
RobStride-specific ABI/binding helpers include:
robstride_ping
robstride_set_device_id
robstride_get_param_*
robstride_write_param_*
Example Entry Points
- Cross-language index:
examples/README.md
- C ABI demo:
examples/c/c_abi_demo.c
- C++ ABI demo:
examples/cpp/cpp_abi_demo.cpp
- Python ctypes demo:
examples/python/python_ctypes_demo.py
- Python SDK docs:
bindings/python/README.md
- C++ binding docs:
bindings/cpp/README.md
Release and Package Matrix
A) GitHub Releases (binary assets)
| Asset | Install / Usage | Platform | Primary Audience | Included Capability |
|---|
motorbridge-abi-<tag>-linux-x86_64.deb | sudo apt install ./motorbridge-abi-<tag>-linux-x86_64.deb | Linux x86_64 | C/C++ users (Ubuntu/Debian) | libmotor_abi + headers + CMake config |
motorbridge-abi-<tag>-linux-*.tar.gz | extract and link manually | Linux x86_64/aarch64 | C/C++ users (non-deb or cross env) | Same ABI payload as .deb |
motorbridge-abi-<tag>-windows-x86_64.zip | extract and link/import | Windows x86_64 | C/C++ users | motor_abi.dll/.lib + headers + CMake config |
motor-cli-<tag>-<platform>.tar.gz/.zip | run bin/motor_cli | Linux/Windows | Field debug / production tooling | Full unified CLI (scan, mode control, id ops, etc.) |
motorbridge-*.whl, motorbridge-*.tar.gz | pip install ./... | depends on wheel tag | Offline Python install from Release assets | Python SDK + motorbridge-cli |
B) PyPI / TestPyPI (Python package channel)
| Channel | Publish Trigger | Python Versions | Platform Matrix | Package Type |
|---|
| TestPyPI | Actions -> Python Publish -> repository=testpypi | 3.10 / 3.11 / 3.12 / 3.13 / 3.14 | Linux (x86_64, aarch64), Windows (x86_64), macOS (arm64) | wheel + sdist |
| PyPI | tag vX.Y.Z or manual repository=pypi | 3.10 / 3.11 / 3.12 / 3.13 / 3.14 | Linux (x86_64, aarch64), Windows (x86_64), macOS (arm64) | wheel + sdist |
Install from PyPI:
Fallback source install:
pip install --no-binary motorbridge motorbridge
C) Functional Scope by Distribution Type
| Distribution Type | Typical Use | What You Can Do |
|---|
ABI package (.deb/.tar.gz/.zip) | C/C++ integration | Call stable C ABI, use C++ RAII wrapper, embed into native robotics stack |
| Python package (wheel/sdist) | Python app/tooling | Use Controller/Motor/Mode APIs and motorbridge-cli |
motor_cli binary package | Ops / factory / debugging | Direct CAN operations without Python runtime |
D) Additional Automated Distribution Channel
| Channel | CI Workflow | Output |
|---|
| APT repository (GitHub Pages) | .github/workflows/apt-repo-publish.yml | https://<owner>.github.io/<repo>/apt |
Notes:
.deb is currently Linux x86_64 oriented; other Linux targets should use ABI .tar.gz.
- macOS x86_64 wheels are intentionally not produced in current matrix.
- Device matrix reference:
docs/en/devices.md.
- Distribution channel automation guide:
docs/en/distribution_channels.md.