> ## 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.

# Python Examples Overview

## 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](/zh/source/python/examples/overview)
> Chinese version (Python binding overview): [../README.zh-CN.md](/zh/source/python/overview)

## 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:

```bash theme={null}
# 1) single motor (safest first step)
PYTHONPATH=bindings/python/src LD_LIBRARY_PATH=$PWD/target/release:${LD_LIBRARY_PATH} \
python3 bindings/python/examples/simple_01_motor_control.py \
  --channel can0 --loop 120 --dt-ms 20 --pos 1.0 --vlim 1.0

# 2) quad motor swing
PYTHONPATH=bindings/python/src LD_LIBRARY_PATH=$PWD/target/release:${LD_LIBRARY_PATH} \
python3 bindings/python/examples/simple_02_quad_motor_control.py \
  --channel can0 --pos 1.0 --loop 240 --dt-ms 20 --swing-loop 60
```

### 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.

### What to Read Next (recommended order)

1. [../README.zh-CN.md](/zh/source/python/overview) or [../README.md](/source/python/overview)
   Start here for Python binding installation and base API concepts.
2. [/zh/source/rust-cli/overview](/zh/source/rust-cli/overview) or [/source/rust-cli/overview](/source/rust-cli/overview)
   Use this for vendor scan commands and ID confirmation.
3. [/zh/source/examples/overview](/zh/source/examples/overview) or [/source/examples/overview](/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:

```bash theme={null}
cd /path/to/rust_dm
python3 -m venv .venv-ws
source .venv-ws/bin/activate
pip install websockets
export PYTHONPATH=$PWD/bindings/python/src
export LD_LIBRARY_PATH=$PWD/target/release:${LD_LIBRARY_PATH}
python3 bindings/python/examples/quad_vendor_binding_ws_demo.py \
  --bind 127.0.0.1 --port 9010 --channel can0 --dt-ms 20
```

Frontend start (new terminal):

```bash theme={null}
cd /path/to/rust_dm/bindings/python/examples
python3 -m http.server 8080
```

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:

```bash theme={null}
python3 bindings/python/examples/quad_vendor_binding_ws_demo.py \
  --channel can0 \
  --dm1-id 0x01 --dm1-fid 0x11 --dm1-model 4340P \
  --dm2-id 0x07 --dm2-fid 0x17 --dm2-model 4310 \
  --my-id 1 --my-fid 0x241 --my-model X8 \
  --rs-id 127 --rs-fid 0xFE --rs-model rs-06
```

### 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:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/python_wrapper_demo.py \
  --channel can0 --model 4340P --motor-id 0x01 --feedback-id 0x11 \
  --pos 0 --vel 0 --kp 20 --kd 1 --tau 0 --loop 20 --dt-ms 20
```

Damiao maintenance:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/damiao_maintenance_demo.py \
  --channel can0 --model 4340P --motor-id 0x01 --feedback-id 0x11 \
  --can-timeout-ms 1000 --set-zero 0
```

Damiao register rw:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/damiao_register_rw_demo.py \
  --channel can0 --model 4340P --motor-id 0x01 --feedback-id 0x11 \
  --read-f32-rid 21 --read-u32-rid 10 --store 0
```

Damiao dm-serial:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/damiao_dm_serial_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x01 --feedback-id 0x11 --mode mit --loop 40 --dt-ms 20
```

SOP-01 dm-serial calibration:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_01_calibration_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --set-zero 0 --can-timeout-ms 1000
```

SOP-02 dm-serial normal control (no calibration/config writes):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_02_control_modes_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --mode pos-vel --pos 0.8 --vlim 1.0 --loop 100 --dt-ms 20
```

SOP-03 dm-serial status monitor:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_03_status_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --loop 100 --dt-ms 50
```

SOP-05 dm-serial set-zero settle-time A/B test:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_05_setzero_timing_ab_test.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --settle-list-ms 0,50,100,200 --rounds 10 --ensure-timeout-ms 500
```

SOP-06 dm-serial software recovery without reboot:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_06_recover_no_reboot_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --attempts 6 --timeout-ms 800
```

SOP-07 dm-serial robust set-zero + control sequence:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_07_enable_setzero_enable_rotate_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --target-pos 3.0 --vlim 1.0 \
  --loop 50 --dt-ms 20 --ensure-timeout-ms 800 \
  --post-setzero-ms 0
```

SOP-08 dm-serial negative test (`enable` then `set_zero`, expect guard reject):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_08_negative_enable_setzero_guard_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  --motor-id 0x04 --feedback-id 0x14 --ensure-timeout-ms 800
```

## 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):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/dm_serial_leader_monitor_demo.py \
  --serial-port /dev/ttyACM0 --serial-baud 921600 --model 4310 \
  -id 0x04 0x07 --loop 10000 --dt-ms 20 --hold-mode mit-zero
```

RobStride:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/robstride_wrapper_demo.py \
  --channel can0 --model rs-06 --motor-id 127 --mode ping
```

RobStride read parameter:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/robstride_wrapper_demo.py \
  --channel can0 --model rs-06 --motor-id 127 --mode read-param --param-id 0x7019
```

Hexfellow (CAN-FD only):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/hexfellow_canfd_demo.py \
  --channel can0 --motor-id 0x01 --feedback-id 0x00 --mode mit --loop 20 --dt-ms 50
```

Unified vendor scan via CLI:

```bash theme={null}
PYTHONPATH=bindings/python/src python3 -m motorbridge.cli scan \
  --vendor all --channel can0 --start-id 0x01 --end-id 0xFF
```

Multi-motor `pos-vel` (example: motor `4` and `7`, positions mapped by order):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/multi_motor_ctrl_demo.py \
  --channel can0 --model 4310 --mode pos-vel \
  -id 4 7 -pos 0.8 -0.6 -vlim 1.2 1.2 --loop 200 --dt-ms 20
```

MIT/POS\_VEL switch demo (POS\_VEL-only run for motor `4` and `7`, target `-3`):

```bash theme={null}
PYTHONPATH=bindings/python/src python3 bindings/python/examples/mit_pos_switch_demo.py \
  --channel can0 --model 4310 -id 4 7 \
  --trajectory -3 \
  --mit-hold-loops 0 --pos-hold-loops 50 \
  --dt-ms 20 --print-state 1
```

## 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.4.1 examples align with the hardened ABI, Python closed-handle guards, `CoreController` cleanup behavior, and Damiao gateway telemetry fixes.
* For browser control, prefer the packaged `ws_gateway`; for script-level bring-up, use the Python binding examples directly.
