Skip to main content

ARX-D-CAN Python SDK

面向达妙电机机械臂的通用 Python SDK,支持单臂、双臂、可选夹爪,以及 DM Device、dm-serial、SocketCAN 和 SocketCAN-FD 通信后端。

SDK 不把公共接口绑定到具体产品:

  • ArxDCanArm 控制一条独立 CAN 通道上的单臂;
  • ArxDCanDualArm 组合左右两条独立 CAN 通道;
  • 机型差异全部由 YAML 配置描述。

当前双臂默认配置是 Yunyi V1.0,默认通过原厂 DM Device 的 CH0/CH1 通信。以后增加 其他产品时不需要再创建产品专用 Python 类。

安装

python -m pip install .

底层通信使用 motor-drive-layer==0.5.8。运动学、动力学和末端控制额外需要:

python -m pip install ".[dynamics]"

单臂 API

from arx_d_can import ArxDCanArm

arm = ArxDCanArm(
    model="yunyi_v1_0_right",
    control_mode="pv",
)
arm.connect()

try:
    state = arm.read_state()
    print(state.positions)

    arm.enable()                           # 自动配置构造时选择的模式
    arm.send_joint_positions([0.0] * 7)    # 直接发送,不插值
finally:
    arm.close()

发送接口职责明确分开:

arm.send_joint_positions(target)                 # 发送当前一帧
arm.move_joint_positions(target, seconds=3.0)    # SDK 插值运动
arm.hold_joint_positions(target)                 # 持续刷新最后目标

关节数量不由代码写死,而是来自所选机型配置。当前公开控制模式只有经过验证的 pv 和 mit。模式在创建机械臂时确定,enable() 自动完成配置;使能期间禁止 切换模式。

双臂 API

from arx_d_can import ArxDCanDualArm

robot = ArxDCanDualArm(control_mode="pv")
robot.connect()

try:
    robot.enable()
    robot.send_joint_positions(
        left=[0.0] * 7,
        right=[0.0] * 7,
    )
finally:
    robot.close()

默认构造使用 Yunyi V1.0 左右臂配置。双臂始终是两个独立单臂对象,不会被展平成 一条包含 14 个关节的 CAN 总线:

print(robot.left)
print(robot.right)

robot.move_joint_positions(
    left=[0.0] * 7,
    right=[0.0] * 7,
    seconds=3.0,
)

其他双臂产品可以分别指定左右机型:

robot = ArxDCanDualArm(
    left_model="my_left_arm",
    right_model="my_right_arm",
)

双臂关节命令通过底层常驻发送线程在左右通道并行提交;PV 和 MIT 使用相同的 send_joint_positions() 接口。每条通道内部仍按关节顺序发送,并在左右通道都完成后 进入下一个控制周期,用户不需要自行创建线程。

Examples

示例按使用形态组织,而不是按产品名组织:

arx_d_can/examples/
├── single_arm/             # 通用单臂示例
│   ├── example_01_scan_ids.py
│   ├── example_02_read_state.py
│   ├── example_03_clear_faults.py
│   ├── example_04_send_position.py
│   ├── example_05_gripper_open_close.py
│   ├── example_06_benchmark_read_rate.py
│   ├── example_07_send_joint_trajectory.py
│   ├── example_08_return_zero.py
│   ├── example_09_diagnose_status.py
│   ├── example_10_set_zero_current_position.py
│   ├── example_11_record_and_replay_trajectory.py
│   └── example_12_gravity_compensation.py
└── dual_arm/               # 对应的双臂示例,当前默认 Yunyi
    ├── example_01_scan_ids.py
    ├── example_02_read_state.py
    ├── example_03_clear_faults.py
    ├── example_04_send_position.py
    ├── example_05_gripper_open_close.py
    ├── example_06_benchmark_read_rate.py
    ├── example_07_send_joint_trajectory.py
    ├── example_08_return_zero.py
    ├── example_09_diagnose_status.py
    ├── example_10_set_zero_current_position.py
    ├── example_11_record_and_replay_trajectory.py
    └── example_12_gravity_compensation.py

单臂示例继续支持 --arm-model,因此同一套示例可以用于其他机械臂:

python -m arx_d_can.examples.single_arm.example_02_read_state \
  --arm-model yunyi_v1_0_right

python -m arx_d_can.examples.single_arm.example_04_send_position \
  --arm-model yunyi_v1_0_right \
  --positions "0,-20,-20,0,0,0,0" \
  --mode pv

双臂示例目前直接使用 Yunyi 默认左右配置:

python -m arx_d_can.examples.dual_arm.example_02_read_state

夹爪

夹爪接口统一使用 0~1000 开合度:

arm.move_gripper(1000)  # 张开
arm.move_gripper(0)     # 闭合

robot.set_grippers(left=500, right=500)
robot.open_grippers()
robot.close_grippers()

Yunyi 夹爪固定使用 MIT 模式,默认 Kp=4.0。堵转检测、接触后的低刚度保持和持续 过载回退由双臂 C++ 安全运行时的常驻线程执行,不需要 Python 控制线程。双臂原生运行 时启用后,单侧原始夹爪命令会被拒绝,避免绕过整机安全状态机。更换自定义末端时可用 ArxDCanDualArm(left_gripper=False, right_gripper=False) 关闭产品夹爪。

read_state() 同时公开结构化夹爪控制状态:

state = robot.read_state()
print(state.left_gripper.opening)
print(state.left_gripper.control_state)
print(state.left_gripper.contact_detected)
print(state.left_gripper.overload)

Yunyi 产品配置

Yunyi 左右臂使用一份产品级配置:

arx_d_can/config/yunyi_v1_0.yaml
├── arms.left
└── arms.right

左右臂仍是两条独立 CAN 通道。为兼容已有代码,通用单臂 API 仍可使用 yunyi_v1_0_left 和 yunyi_v1_0_right 两个机型名,但它们会选择同一份产品配置中 对应的一侧。YAML 只在对象创建时解析,发送热路径不会重复加载配置。

通信后端

transport channel 示例 用途
dm-serial /dev/ttyACM0 达妙串口 USB2CAN
dm-device 0、1 原厂 DM-USB2FDCAN Dual 固件
socketcan can0 Linux 经典 CAN
socketcanfd can0 Linux CAN-FD

Yunyi 默认使用原厂 DM Device,不需要刷写固件,也不需要额外传入通信参数:

motor-drive-layer-install-dm-device --download

python -m arx_d_can.examples.single_arm.example_02_read_state \
  --arm-model yunyi_v1_0_right

ArxDCanArm(model="yunyi_v1_0_left") 默认使用 CH0, ArxDCanArm(model="yunyi_v1_0_right") 默认使用 CH1;ArxDCanDualArm() 默认同时 打开 CH0 和 CH1。dm-serial、SocketCAN 等其他后端只在用户显式覆盖时使用。

Linux SocketCAN 需要先配置接口,例如经典 CAN 1 Mbps:

sudo ip link set can0 down
sudo ip link set can0 type can bitrate 1000000 restart-ms 100
sudo ip link set can0 up
ip -details -statistics link show can0

SocketCAN 速率由 ip link 设置,Python 的 baud 不会修改 Linux CAN 接口。

安全与通信健康

ArxDCanDualArm 在真实 motor-drive-layer Controller 上启用编译进 wheel 的 C++ 安全 运行时。Python 只校验和提交一整批左右臂命令;常驻原生线程使用 steady_clock 执行 看门狗、反馈检查、双臂联动安全保持、故障锁存和失能确认,不依赖 Python GIL。状态为 DISCONNECTED → READY → ENABLED → RUNNING → SAFE_HOLD / FAULT,FAULT 只能通过 检查双通道、TransportHealth、新鲜反馈、电机故障码和物理失能状态的 recover() 回到 READY,不会自动重新使能。 若整个 Python 进程退出,进程内原生线程也会随之终止;SDK 因此在配置阶段同时写入 motor_communication_timeout_ms(Yunyi 默认 500 ms),由电机固件在主机进程消失后 执行最终通信超时失能。

robot = ArxDCanDualArm(transport="dm-device", control_mode="pv")
robot.connect()
health = robot.safety_health
print(health.state)
print(health.fault_reason)
print(health.left_transport)
print(health.right_transport)
print(health.disable_confirmed)

双臂运行时要求左右关节命令整体接受或拒绝。连接到原生运行时后,不允许通过 robot.left.send_joint_positions() 或 robot.right.send_joint_positions() 绕过批量状态机; 应调用 robot.send_joint_positions(left=..., right=...)。单臂 ArxDCanArm 以及无法直接 批量发送的耦合 MIT 机型继续使用原有 Python 安全路径。

运行实机运动示例时,应先激活 Python 环境再执行 python -m ...。如果必须使用 conda run,需要添加 --no-capture-output:

conda run --no-capture-output -n at python -m \
  arx_d_can.examples.dual_arm.example_04_send_position \
  --left "0,0,0,90,0,0,0" \
  --right "0,0,0,90,0,0,0" \
  --mode pv

普通 conda run -n ... 会缓存子进程输出,并可能在 Ctrl+C 时由 Conda 自己截获 中断,使 Python 的 finally 清理逻辑没有机会完成。运动控制不能依赖这种运行方式。

  • 单次双通道批量发送失败、命令超时或连续反馈失败会进入 SAFE_HOLD;
  • 安全保持失败、设备掉线、反馈严重过期、电机故障或意外失能会锁存 FAULT;左右臂 联动失能,夹爪按产品配置的 gripper_fault_action: hold | disable 保持物体或失能, 保持失败时会继续尝试失能;
  • read_state() 只返回新鲜、完整反馈;
  • read_cached_state() 明确读取最近一次成功反馈;
  • communication_health 提供结构化通信状态;
  • close() 默认停止后台任务、失能电机并关闭总线。
health = arm.communication_health
print(health.healthy)
print(health.consecutive_feedback_failures)
print(health.last_error)

C++ 安全运行时不是安全认证功能。产品仍需要物理急停、电机侧通信超时,以及垂直负载 场景所需的机械制动或防坠机构。

自定义机型

内置机型注册在 arx_d_can/config/models.yaml。增加单臂机型时创建自己的硬件 YAML, 然后注册机型名称即可继续使用全部 single_arm 示例:

from arx_d_can import ArxDCanArm, available_models

print(available_models())
arm = ArxDCanArm(model="my_arm")

本地调试未注册配置时,也可以使用高级参数:

arm = ArxDCanArm(config_path="/path/to/my_arm.yaml")

开发验证

python -m pip install ".[dev]"
python -m pytest --import-mode=importlib --rootdir=tests tests
python -m pip wheel --no-deps . --wheel-dir dist

Metadata

Release files for arx-d-can 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for arx-d-can 0.2.2
File Size Uploaded
arx_d_can-0.2.2.tar.gz 186.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for arx-d-can 0.2.2
File Interpreter ABI Platform
arx_d_can-0.2.2-cp310-cp310-manylinux_2_34_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.34+ x86-64 Details

Total release size: 410.3 kB

Release files / arx_d_can-0.2.2.tar.gz

Download URL arx_d_can-0.2.2.tar.gz
Size 186.4 kB
Tags Source
SHA-256 checksum
How to use checksums
67358b98d267ea8e2538b556bff7325f7bca90a5e53822ca1a45f36f57232bb7
BLAKE2b-256 checksum
How to use checksums
bb9fcb483d82eae9e3b59831e053171d3a2be02a0d5fde9f17aa85276be8a915
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.20

Release files / arx_d_can-0.2.2-cp310-cp310-manylinux_2_34_x86_64.whl

Download URL arx_d_can-0.2.2-cp310-cp310-manylinux_2_34_x86_64.whl
Size 223.9 kB
Tags CPython 3.10 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
1c9bc9e3cc7c863b2341cd17b55ea3d185cba58faacc0629e8bc69f05671778a
BLAKE2b-256 checksum
How to use checksums
bcaf1668635aa08605150c61647d7b39d6c221084abfc9808093b39a4a19e9f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.20

Release history Release notifications | RSS feed

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.0

1 release file

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page