Skip to main content

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.

What is MotorBridge?

v0.3.3 Rust Core Python Binding MotorBridge is a unified motor control stack with pluggable vendor drivers and a C ABI for cross-language integration.

The Problem We Solve

Every motor vendor has a different protocol:
VendorProtocolCAN FormatControl Modes
Damiao (达妙)DM-J4310/4340CAN 2.0MIT, POS_VEL, VEL, FORCE_POS
RobStrideRobStride MITCAN 2.0MIT, Position, Velocity
MyActuatorRMDCAN 2.0Current, Position, Velocity
HighTorqueHT NativeCAN 2.0MIT, POS_VEL, VEL, FORCE_POS
HexfellowHexfellow MITCAN-FDMIT, POS_VEL
Without MotorBridge, you need to:
  • Learn 5+ different protocols
  • Maintain separate codebases per vendor
  • Rewrite control logic when switching motors
  • Build your own debugging tools

MotorBridge Architecture

The diagram above is the readable system map. The text diagram below is kept as a compact terminal-friendly reference.
┌─────────────────────────────────────────────────────────────────────┐
│                          Your Application                            │
│                     (Python / Future: C++, ROS2)                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│    ┌─────────────────────────────────────────────────────────────┐  │
│    │                    Language Bindings                         │  │
│    │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │  │
│    │  │   Python     │  │   C++ (WIP)  │  │  ROS2 (WIP)  │      │  │
│    │  │   Binding    │  │   Binding    │  │   Node       │      │  │
│    │  └──────────────┘  └──────────────┘  └──────────────┘      │  │
│    └─────────────────────────────────────────────────────────────┘  │
│                                │                                     │
│                                ▼                                     │
│    ┌─────────────────────────────────────────────────────────────┐  │
│    │                       C ABI (FFI)                            │  │
│    │              libmotor_abi.so / .dylib / .dll                 │  │
│    │                                                              │  │
│    │  • motor_controller_new_socketcan()                         │  │
│    │  • motor_controller_add_damiao_motor()                      │  │
│    │  • motor_handle_send_mit()                                  │  │
│    │  • motor_handle_get_state()                                 │  │
│    └─────────────────────────────────────────────────────────────┘  │
│                                │                                     │
│                                ▼                                     │
│    ┌─────────────────────────────────────────────────────────────┐  │
│    │                     Rust Core                                │  │
│    │                                                              │  │
│    │  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐           │  │
│    │  │ motor_core  │ │ motor_abi   │ │ motor_cli   │           │  │
│    │  │ (abstractions)│ (FFI layer) │ │ (CLI tools) │           │  │
│    │  └─────────────┘ └─────────────┘ └─────────────┘           │  │
│    │                                                              │  │
│    │  ┌───────────────────────────────────────────────────────┐ │  │
│    │  │                   Vendor Drivers                       │ │  │
│    │  │  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐│ │  │
│    │  │  │ Damiao │ │RobStride│ │MyActuat.│ │HighTorq.│ │Hexfellow││  │
│    │  │  │        │ │        │ │        │ │        │ │        ││ │  │
│    │  │  └────────┘ └────────┘ └────────┘ └────────┘ └────────┘│ │  │
│    │  └───────────────────────────────────────────────────────┘ │  │
│    └─────────────────────────────────────────────────────────────┘  │
│                                │                                     │
│                                ▼                                     │
│    ┌─────────────────────────────────────────────────────────────┐  │
│    │                     Transport Layer                          │  │
│    │                                                              │  │
│    │  ┌────────────┐  ┌────────────┐  ┌────────────┐            │  │
│    │  │ SocketCAN  │  │ SocketCAN-FD│  │  DM Serial │            │  │
│    │  │ (CAN 2.0)  │  │  (CAN-FD)  │  │   Bridge   │            │  │
│    │  └────────────┘  └────────────┘  └────────────┘            │  │
│    └─────────────────────────────────────────────────────────────┘  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Project Structure

motorbridge/
├── motor_core/           # Core abstractions (CanBus, MotorDevice)
├── motor_abi/            # C ABI / FFI layer (cdylib + staticlib)
├── motor_vendors/        # Vendor-specific protocol implementations
│   ├── damiao/          # 达妙 motor protocol
│   ├── robstride/       # RobStride motor protocol
│   ├── myactuator/      # MyActuator RMD protocol
│   ├── hightorque/      # HighTorque native protocol
│   └── hexfellow/       # Hexfellow MIT protocol (CAN-FD)
├── bindings/
│   └── python/          # Python binding (ctypes-based)
├── motor_cli/           # Command-line utilities
├── integrations/
│   └── ws_gateway/      # WebSocket gateway for remote control
└── tools/
└── motorbridge-studio/ # Standalone web control UI repo

Why “Python Binding” Not “SDK”?

A binding is a thin wrapper that exposes a native library to another language via FFI (Foreign Function Interface).
┌─────────────────────────────────────────────────┐
│  Python Code                                    │
│  motor.send_mit(pos, vel, kp, kd, tau)          │
└───────────────────────┬─────────────────────────┘
                        │ ctypes call

┌─────────────────────────────────────────────────┐
│  C ABI (libmotor_abi.so)                        │
│  motor_handle_send_mit(ptr, pos, vel, kp, kd, tau)│
└───────────────────────┬─────────────────────────┘
                        │ native call

┌─────────────────────────────────────────────────┐
│  Rust Core                                      │
│  DamiaoMotor::send_mit_target(...)             │
└─────────────────────────────────────────────────┘
Key characteristics:
  • Logic lives in Rust, not Python
  • Python is a 1:1 mapping to C ABI functions
  • No duplicate implementation
  • Minimal overhead (direct FFI calls)
The motor_abi crate compiles to a shared library:
# motor_abi/Cargo.toml
[lib]
crate-type = ["cdylib", "staticlib"]  # Dynamic + Static library
Python loads it via ctypes:
# abi.py
lib = ctypes.CDLL("libmotor_abi.so")

# Bind function signature
lib.motor_handle_send_mit.argtypes = [c_void_p, c_float, c_float, 
                                       c_float, c_float, c_float]
lib.motor_handle_send_mit.restype = c_int32

# Call it
lib.motor_handle_send_mit(motor_ptr, 0.5, 0.0, 30.0, 1.0, 0.0)
This is zero-copy for primitive types - floats and ints pass directly between Python and Rust.
AspectSDKBinding (MotorBridge)
Logic locationIn the SDK itselfIn Rust core
LanguagePure PythonRust + Python wrapper
PerformancePython overheadNear-native speed
Memory safetyPython GCRust ownership
Other languagesN/ASame ABI for C++, etc.
DeploymentPure PythonNeed native library
MotorBridge is a Binding because:
  • The “SDK” is the Rust core (motor_core + vendor drivers)
  • Python is just one interface to that core
  • Future: C++, ROS2 nodes will use the same ABI

Why Rust for the Core?

RequirementRust Advantage
Real-time controlNo garbage collection pauses
Memory safetyNo buffer overflows, use-after-free
Deterministic timingPredictable execution for control loops
Zero-cost abstractionsHigh-level code, low-level performance
Cross-platformLinux, macOS, Windows support
CAN integrationNative SocketCAN bindings

Core Components

Controller

Manages CAN interface and motor lifecycle:
from motorbridge import Controller

# SocketCAN (most common)
with Controller("can0") as ctrl:
    # ctrl manages the CAN socket
    # ctrl tracks all registered motors
    # ctrl handles cleanup on exit
    pass

# CAN-FD (for Hexfellow)
ctrl = Controller.from_socketcanfd("can0")

# DM Serial Bridge (达妙专用)
ctrl = Controller.from_dm_serial("/dev/ttyACM0", 921600)
It is recommended to bind each Controller to motors from one vendor. While the Python API allows mixing different vendors, mixed usage depends on the underlying ABI implementation and may have compatibility limitations.

Motor

Handle to a single physical motor:
# Add a Damiao motor
motor = ctrl.add_damiao_motor(
    motor_id=0x01,      # Command CAN ID
    feedback_id=0x11,   # Feedback CAN ID  
    model="4340P"       # Motor model string
)

# Control commands
motor.send_mit(pos=0.5, vel=0.0, kp=30.0, kd=1.0, tau=0.0)

# Read state
state = motor.get_state()

Mode

Control mode determines how the motor responds:
from motorbridge import Mode

motor.ensure_mode(Mode.MIT, timeout_ms=1000)
ModeParametersUse Case
MITpos, vel, kp, kd, tauFull impedance control
POS_VELpos, vlimPosition with speed limit
VELvelPure velocity control
FORCE_POSpos, vlim, ratioForce-limited position

MotorState

Real-time feedback structure:
@dataclass
class MotorState:
    can_id: int          # Motor CAN ID
    arbitration_id: int  # CAN arbitration ID
    status_code: int     # Error/status code (0 = OK)
    pos: float           # Position (radians)
    vel: float           # Velocity (rad/s)
    torq: float          # Torque (Nm)
    t_mos: float         # MOSFET temperature (°C)
    t_rotor: float       # Rotor temperature (°C)

Transport Options

TransportVendorsConstructor
SocketCANAll except HexfellowController("can0")
CAN-FDHexfellow (required)Controller.from_socketcanfd("can0")
DM SerialDamiao onlyController.from_dm_serial("/dev/ttyACM0", 921600)

CLI Tools

The project includes command-line utilities:
# Scan for motors
motorbridge-cli scan --vendor all --channel can0

# Enable and test
motorbridge-cli run --vendor damiao --motor-id 0x01 --mode enable

# Dump registers
motorbridge-cli id-dump --motor-id 0x01 --rids 7,8,9,10

Integrations

WebSocket Gateway

Control motors over WebSocket (useful for browser/remote apps):
# Start gateway (installed with pip wheel)
motorbridge-gateway -- --bind 127.0.0.1:9002
From source tree, you can still run:
cargo run -p ws_gateway -- --bind 127.0.0.1:9002

Motor Calibration

Tool for motor calibration routines:
cd ../motorbridge-studio
npm install
npm run dev

Comparison with Alternatives

FeatureVendor LibrariesMotorBridge
Multi-vendor❌ One per vendor✅ Unified API
Protocol details❌ Exposed✅ Abstracted
Type safety⚠️ Varies✅ Full type hints
CLI tools❌ Usually none✅ Built-in
Real-time safe⚠️ Python GC✅ Rust core
Other languages❌ Python only✅ C ABI for any language
Documentation⚠️ Varies✅ Comprehensive

Quick Start

1

Install Python Package

pip install motorbridge
2

Configure CAN Interface

sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up
3

Run Your First Program

from motorbridge import Controller, Mode

with Controller("can0") as ctrl:
    motor = ctrl.add_damiao_motor(0x01, 0x11, "4340P")
    ctrl.enable_all()
    motor.ensure_mode(Mode.MIT, 1000)
    motor.send_mit(0.5, 0.0, 30.0, 1.0, 0.0)
    print("Motor running!")

What Can You Build?

Next Steps

Quick Start Guide

Get your first motor running in 5 minutes

API Reference

Complete API documentation

Tutorials

Step-by-step practical guides

Best Practices

Production-ready patterns