Skip to main content
Source: bindings/python/examples/README.md

Python Practical Demos

Channel Compatibility (PCAN + slcan + CAN-FD + Damiao Serial Bridge)

  • Linux SocketCAN uses interface names directly: can0, can1, slcan0.
  • For USB-serial CAN adapters, bring up slcan0 first: sudo slcand -o -c -s8 /dev/ttyUSB0 slcan0 && sudo ip link set slcan0 up.
  • Hexfellow examples require CAN-FD path (Controller.from_socketcanfd(...) / CLI --transport socketcanfd).
  • Damiao-only serial bridge transport is also available in CLI (--transport dm-serial --serial-port /dev/ttyACM0 --serial-baud 921600).
  • Full Damiao serial-bridge interface list and command patterns are documented in motor_cli/README.md (section 3.6 in motor_cli/README.zh-CN.md).
  • On Linux SocketCAN, do not append bitrate in --channel (for example can0@1000000 is invalid).
  • On Windows (PCAN backend), can0/can1 map to PCAN_USBBUS1/2; optional @bitrate suffix is supported.
Examples built on the Python SDK.
Chinese version (examples): READMEzh_cn.md Chinese version (Python binding overview): ../README.zh-CN.md

Start Here (Simplest 2 Examples)

If you installed from pip and want a cleaner onboarding path, start with:
  • ../get_started/README.md (English)
  • ../get_started/README.zh-CN.md (Chinese)
If you are new to this repository, start with these two files first:
  • simple_01_motor_control.py: single-motor minimal template (default Damiao, other vendors as commented snippets).
  • simple_02_quad_motor_control.py: minimal 4-motor multi-vendor swing demo (2 Damiao + 1 MyActuator + 1 RobStride).
Recommended order:
  1. Run simple_01_motor_control.py to verify your CAN channel and one motor first.
  2. Then run simple_02_quad_motor_control.py to verify multi-controller / multi-vendor behavior.
Quick start commands:

Parameter Cheat Sheet (for the two simplest scripts)

simple_01_motor_control.py
  • --channel: CAN interface name, e.g. can0, can1, slcan0.
  • --loop: number of control iterations.
  • --dt-ms: control period (ms). Start with 20; if bus is busy, use 30/50.
  • --pos: target position (radians).
  • --vlim: speed limit for POS_VEL.
simple_02_quad_motor_control.py
  • --channel: CAN interface name.
  • --loop: total loop count.
  • --dt-ms: control period (ms), same tuning rule as above.
  • --pos: swing amplitude (radians), used as +pos/-pos.
  • --swing-loop: switch sign every N loops.
  • --rs-dir-sign: -1 means RobStride direction opposite to others; +1 means same.
  • --dm-vlim: Damiao speed limit in POS_VEL.
  • --my-vlim: MyActuator speed limit in POS_VEL.
  • --rs-kp / --rs-kd: RobStride MIT gains.
  1. ../README.zh-CN.md or ../README.md Start here for Python binding installation and base API concepts.
  2. /zh/source/rust-cli/overview or /source/rust-cli/overview Use this for vendor scan commands and ID confirmation.
  3. /zh/source/examples/overview or /source/examples/overview Broader demo index (web/WS/other integration examples).

WS Demo Quick Guide (quad_vendor_binding_ws_demo.py)

This demo is a Python WS bridge for 4 motors (dm1, dm2, my, rs) with a matching web UI. Backend start:
Frontend start (new terminal):
Open browser:
  • http://127.0.0.1:8080/quad_vendor_binding_ws_demo.html
  • WS URL: ws://127.0.0.1:9010
If your IDs are different, pass them on startup:

Key Points Beginners Must Know

  • One Controller instance cannot mix vendors; use separate controllers for mixed-vendor control.
  • os error 105 usually means send rate is too high or another process is also writing to CAN.
  • Streaming control needs periodic sends; single-shot command is often not enough for stable holding.
  • Confirm motor IDs/feedback IDs with scan before running these demos.

Files

  • simple_01_motor_control.py: simplest single-motor template (default Damiao; includes commented vendor switch snippets)
  • simple_02_quad_motor_control.py: simplest 4-motor multi-vendor demo with fixed-rate loop and swing target
  • python_wrapper_demo.py: minimal Damiao MIT loop
  • damiao_maintenance_demo.py: Damiao maintenance flow (clear_error / set_zero_position / set_can_timeout_ms / request_feedback)
  • damiao_register_rw_demo.py: Damiao register read/write (f32 + u32 + optional store_parameters)
  • damiao_dm_serial_demo.py: Damiao serial-bridge transport demo (Controller.from_dm_serial)
  • dm_serial_01_calibration_demo.py: SOP-01 dm-serial maintenance/calibration flow
  • dm_serial_02_control_modes_demo.py: SOP-02 dm-serial normal control loop (4 modes, no calibration/config writes)
  • dm_serial_03_status_demo.py: SOP-03 dm-serial status-only monitor
  • dm_serial_04_enable_setzero_no_delay_demo.py: SOP-04 dm-serial stress repro (set_zero then immediate control)
  • dm_serial_05_setzero_timing_ab_test.py: SOP-05 dm-serial set-zero settle-time A/B test
  • dm_serial_06_recover_no_reboot_demo.py: SOP-06 dm-serial software recovery (no host reboot)
  • dm_serial_07_enable_setzero_enable_rotate_demo.py: SOP-07 dm-serial robust sequence (disable -> set_zero -> enable -> control)
  • dm_serial_08_negative_enable_setzero_guard_demo.py: SOP-08 dm-serial negative test (enable state set_zero should be rejected by core guard)
  • dm_serial_leader_monitor_demo.py: Damiao dm-serial leader monitor (enable-all + selected-ID full state stream)
  • robstride_wrapper_demo.py: RobStride ping / read-param / mit / vel demo
  • quad_vendor_pos_binding_demo.py: 4-motor sync position demo via Python binding (no ws_gateway)
  • quad_vendor_binding_ws_demo.py: Python binding WS bridge backend (for web UI control)
  • quad_vendor_binding_ws_demo.html: simple web UI for quad_vendor_binding_ws_demo.py
  • hexfellow_canfd_demo.py: Hexfellow CAN-FD demo (mit / pos-vel only)
  • full_modes_demo.py: Damiao full-mode demo
  • pid_register_tune_demo.py: Damiao register tuning
  • scan_ids_demo.py: Damiao fast scan (legacy helper)
  • pos_ctrl_demo.py: Damiao one-shot target position
  • multi_motor_ctrl_demo.py: Damiao multi-motor control with -id / -pos one-to-one mapping
  • mit_pos_switch_demo.py: two-phase mode switch demo (MIT then POS_VEL) for multi-motor targets
  • pos_repl_demo.py: Damiao interactive position console

Quick Run

Damiao:
Damiao maintenance:
Damiao register rw:
Damiao dm-serial:
SOP-01 dm-serial calibration:
SOP-02 dm-serial normal control (no calibration/config writes):
SOP-03 dm-serial status monitor:
SOP-05 dm-serial set-zero settle-time A/B test:
SOP-06 dm-serial software recovery without reboot:
SOP-07 dm-serial robust set-zero + control sequence:
SOP-08 dm-serial negative test (enable then set_zero, expect guard reject):

dm-serial Timing Notes (Set-Zero Sequence)

  • Observed issue: running set_zero_position() and immediately calling ensure_mode(...) can trigger register 10 not received timeouts.
  • Root cause pattern: this is typically a dm-serial timing window (bridge latency + motor internal state switch), not a normal control-mode logic bug.
  • Core guard rule: set_zero_position() is accepted only after disable().
  • Core settle rule: after set_zero_position(), a fixed 20 ms settle is applied in core (not exposed as Python argument).
  • Recommended sequence for robust control:
    1. disable (or disable_all)
    2. set_zero_position
    3. enable (or enable_all)
    4. ensure_mode
    5. run control loop
  • If the timeout state is triggered, try software recovery first (disable -> clear_error -> enable -> retry) before rebooting host/device.
Damiao dm-serial leader monitor (selected IDs full-state stream):
RobStride:
RobStride read parameter:
Hexfellow (CAN-FD only):
Unified vendor scan via CLI:
Multi-motor pos-vel (example: motor 4 and 7, positions mapped by order):
MIT/POS_VEL switch demo (POS_VEL-only run for motor 4 and 7, target -3):

Damiao Coverage Note

Damiao examples now cover the full high-level SDK usage surface:
  • Control modes: mit / pos-vel / vel / force-pos
  • Transport paths: Controller(channel) + Controller.from_dm_serial(...)
  • Maintenance ops: clear_error, set_zero_position, set_can_timeout_ms, request_feedback
  • Register APIs: get/write f32, get/write u32, store_parameters
  • Scan helper and tuning workflows

Scope Notes

  • Current v0.5.0 examples align with the hardened ABI, Python closed-handle guards, and CoreController cleanup behavior.
  • For browser control, prefer the packaged ws_gateway; for script-level bring-up, use the Python binding examples directly.