Skip to main content

Python SDK for OpenFlex robotic arm control via CAN bus

Project description

OpenFlex Driver

Developed by Chengdu Changshu Robotics Co., Ltd.

OpenFlex Driver is the Python SDK for OpenFlex / OpenArmX full-body robot control over CAN bus. It provides high-level interfaces for dual arms, head, lift column, and swerve chassis, while also exposing lower-level motor, CAN, calibration, and teleoperation utilities for integration and research workflows.

The package is designed for Linux robots using SocketCAN-compatible CAN adapters and Robstride / CANopen motor controllers.

Features

  • Dual-arm control through Arm and Robot
  • Head control with yaw / pitch joints
  • Lift column control over CANopen CiA402
  • Four-wheel swerve chassis control with steering and driving modules
  • MIT and CSP motor control modes
  • Motor enable / disable, mode switching, status reading, zero calibration
  • CAN interface discovery and setup helpers
  • Automatic and passive zero calibration utilities
  • VR teleoperation / IK interface based on Pinocchio
  • Binary wheel build support with Cython-compiled internal modules

Supported Components

Component Interface Default CAN Notes
Right arm Arm, Robot.right_arm can0 Robstride arm motors, IDs 1-8
Left arm Arm, Robot.left_arm can1 Robstride arm motors, IDs 1-8
Head Head, Robot.head can2 Yaw ID 1, pitch ID 2
Lift column Column, Robot.column can3 CANopen CiA402 node, default ID 16
Chassis driving Chassis can4 UM wheel motors, default IDs 1-4
Chassis steering Chassis can5 RS steering motors, default IDs 5-8

Installation

Install from PyPI:

pip install openflex-driver

For local development:

git clone <your-repository-url>
cd openflex_driver
python3 -m pip install -e .

Requirements

  • Linux with SocketCAN support
  • Python >= 3.9
  • python-can >= 4.0.0
  • PyYAML >= 5.4.0
  • numpy >= 1.21.0
  • pin >= 2.6.0 for teleoperation / IK functionality
  • Cython is required when building wheels from source

CAN Setup

The driver can try to enable CAN interfaces automatically when auto_enable_can=True. For manual setup, use standard SocketCAN commands:

sudo ip link set can0 up type can bitrate 1000000
sudo ip link set can1 up type can bitrate 1000000
sudo ip link set can2 up type can bitrate 1000000
sudo ip link set can3 up type can bitrate 1000000
sudo ip link set can4 up type can bitrate 1000000
sudo ip link set can5 up type can bitrate 1000000

Check available CAN interfaces:

from openflex_driver import get_available_can_interfaces, verify_can_interface

print(get_available_can_interfaces())
print(verify_can_interface("can0"))

Quick Start

Single Arm

from openflex_driver import Arm

arm = Arm(can_channel="can0", side="right")

try:
    arm.enable_arm_motors()
    arm.set_mode("mit")
    arm.move_to_mit(
        motor_id=1,
        position=0.3,
        velocity=0.0,
        torque=0.0,
        kp=20.0,
        kd=1.0,
    )
    status = arm.get_motor_status(motor_id=1)
    print(status)
finally:
    arm.disable_arm_motors()
    arm.close()

Dual Arms and Full Robot

from openflex_driver import Robot

robot = Robot(
    right_arm_can="can0",
    left_arm_can="can1",
)

try:
    robot.enable_right_arm()
    robot.enable_left_arm()
    robot.right_arm.set_mode("mit")
    robot.left_arm.set_mode("mit")

    robot.move_to_mit_right_arm(
        motor_id=2,
        position=0.2,
        kp=20.0,
        kd=1.0,
    )
    robot.move_to_mit_left_arm(
        motor_id=2,
        position=0.2,
        kp=20.0,
        kd=1.0,
    )

    robot.show_arms_status()
finally:
    robot.disable_right_arm()
    robot.disable_left_arm()
    robot.shutdown()

To manage optional full-body components from Robot, pass head_can, column_can, steering_can, and driving_can, then initialize each component according to your hardware startup sequence.

Component Examples

Head

from openflex_driver import Head, JOINT_YAW, JOINT_PITCH

head = Head(can_channel="can2")

try:
    head.connect()
    head.enable()
    head.move_to_mit(motor_id=JOINT_YAW, position=0.2)
    head.move_to_mit(motor_id=JOINT_PITCH, position=-0.1)
    print(head.get_joint_status())
finally:
    head.disable()
    head.disconnect()

Lift Column

from openflex_driver import Column

column = Column(can_interface="can3", node_id=16)

try:
    column.connect()
    column.enable()
    column.switch_to_position_mode()
    column.move_to_user_position(0.15)
    print(column.get_status())
    column.stop_motion()
finally:
    column.disable()
    column.close()

Swerve Chassis

from openflex_driver import Chassis

chassis = Chassis(steering_can="can5", driving_can="can4")

try:
    chassis.connect()
    chassis.enable_all()

    # vx: forward m/s, vy: left m/s, omega: counter-clockwise rad/s
    chassis.set_chassis_velocity(vx=0.2, vy=0.0, omega=0.0)
    chassis.stop_motion()

    print(chassis.get_status_table())
finally:
    chassis.disable_all()
    chassis.close()

Motor Inventory

from openflex_driver import position_motors, velocity_motors

for motor in position_motors():
    print(motor.component, motor.name, motor.can_channel, motor.motor_id)

for motor in velocity_motors():
    print(motor.component, motor.name, motor.can_channel, motor.motor_id)

Public API Overview

Main classes:

  • Arm: one arm controller
  • Robot: full robot controller that owns left / right arms and optional head, column, chassis
  • Head: two-axis head controller
  • Column: lift column controller
  • Chassis: swerve chassis controller
  • MotorConfigLoader: load motor configuration and limits

Common helper APIs:

  • CAN utilities: get_available_can_interfaces, verify_can_interface, enable_can_interface, disable_can_interface
  • Motor management: enable_motor, disable_motor, set_control_mode, get_motor_status_readonly
  • Motor control: mit_motion_control, csp_motion_control, csp_set_speed_limits
  • Calibration: auto_calibrate_zero, move_to_limit, move_to_position_smooth
  • Chassis kinematics: ChassisSpeeds, SwerveDriveKinematics, default_module_positions
  • Teleoperation: TeleopConfig, TeleopInputFrame, OpenArmTeleopController, PinocchioTeleopCore

Build From Source

The package compiles internal _lib modules into .so files during wheel / source distribution builds.

For local builds on a machine that already has build dependencies installed:

python3 -m build --no-isolation

For a clean isolated build, network access is required so Python can install build dependencies declared in pyproject.toml:

python3 -m build

Inspect generated wheels:

unzip -l dist/openflex_driver-*.whl

The helper scripts build_so.py and clean_so.py are local build tools and are excluded from the published source distribution.

Publishing

This repository includes GitHub Actions workflow support under .github/workflows/build.yml.

  • Push to main, master, or linux_*: build wheels and publish to TestPyPI when TEST_PYPI_API_TOKEN is configured.
  • Push a tag like v1.2.0: build wheels and publish to PyPI when PYPI_API_TOKEN is configured.
  • Supported build matrix: Python 3.9, 3.10, 3.11, 3.12 on x86_64 and aarch64.

Before a release:

# Update version in pyproject.toml and src/openflex_driver/__init__.py
git add .
git commit -m "Release v1.2.0"
git tag -a v1.2.0 -m "Release version 1.2.0"
git push
git push origin v1.2.0

Safety Notes

  • Always verify CAN interfaces and motor IDs before enabling motors.
  • Start with low velocity, low torque, and conservative kp / kd values.
  • Keep the robot clear of people and obstacles during calibration and first motion tests.
  • Run active zero calibration only when mechanical limits and emergency stop behavior are verified.
  • Disable motors and close CAN connections when control is finished.

License

This project is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Commercial use requires a separate license from Chengdu Changshu Robotics Co., Ltd. See LICENSE for details.

Contact Us

Chengdu Changshu Robotics Co., Ltd.

Contact Information
📧 Email wangxunyue1@163.com
openarmrobot@gmail.com
📱 Phone/WeChat +86-17746530375
🌐 Website https://openarmx.com/
🌐 Documentation http://docs.openarmx.com/
📍 Address Xiqing District, Tianjin・Daochao Robotics Experience Center (Tomorrow City)・Tianjin Humanoid Robot Center
👤 Contact Person Mr. Wang

Copyright © 2025 Chengdu Changshu Robotics Co., Ltd. All Rights Reserved.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openflex_driver-1.0.0.tar.gz (5.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_aarch64.whl (5.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_aarch64.whl (5.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl (5.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_aarch64.whl (5.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_x86_64.whl (5.1 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_aarch64.whl (5.1 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

File details

Details for the file openflex_driver-1.0.0.tar.gz.

File metadata

  • Download URL: openflex_driver-1.0.0.tar.gz
  • Upload date:
  • Size: 5.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for openflex_driver-1.0.0.tar.gz
Algorithm Hash digest
SHA256 03316069d39408ccfd9770dd55a790535e98a474473bfa1a2f88821179d656d2
MD5 357549acd792c89a2758c60e98f54d35
BLAKE2b-256 eb8d3613515f209562e733eb127872c4b0603a5de225fcd3e32b7ffd26416580

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 b187471c80bc16452b466d64b1f01dec7bb3d106ae4df70a0a48f28b9fc135a6
MD5 9e2ba1e833d0e9db10bc96a446536eb1
BLAKE2b-256 40dc1de34cd4e454c6ffe13f6d6d9e013a427a8a17c4784da782eb31f82a34d0

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp312-cp312-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 eab641cb2d9a12d98ffa8740e136eac02e45b1e25de71af12f40f9663700bc57
MD5 2ccb43070c7a5619bbad3b0a3c1e873a
BLAKE2b-256 756c5f0b555f5b45d4e836225fa8d4680911368f83a4912d192c1edbe158c082

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 0d4a0cde83d17b436753f10241497503077678ff928041dde21e5822fd2f3368
MD5 036377b2496ac86eb23e5803d2c4f590
BLAKE2b-256 90a58a116169f296c55a1210fbe2c4c9d5a1c7ae5d94f0b27e0233214742f0ce

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp311-cp311-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 69167a969d61c3dbadc3d9a27a446ec5d4e3648193874b99b0967ecbb1723a89
MD5 675b768c2b01740ac841ac1e821e511e
BLAKE2b-256 059ead0dfed24776e308f8645d8c00289a32772465cd93e960a8271365d82ed1

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 3db895a92a1181e6a3bb01f84ec2534b052a1e8b70ed78fb5fbf0f16cac971c7
MD5 fb47f31918bea56120d3499027068651
BLAKE2b-256 eaae5db9d5a0a591ee7d44483362bac36ffb7366647ab9cc6e49dc9904a08bcb

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp310-cp310-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 ef70c073c25c86f0529a33a5906e3713daea7c4281825789f007aa548fdbdac8
MD5 03971c349c8fe57e699b2d7fe4497ebf
BLAKE2b-256 000ea7c9f5e3537b31b68f5f4977191d1cc186716869c4b6679db75e90c95e2d

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 98cee2d0f2d44ad42407f4919b91e0156181885092a29764345e3916cd458934
MD5 dbd23502fd6d15da7b08ebab1d7d57e8
BLAKE2b-256 a7e7a178843d57527cbd503c272c33fd1cd372c7209e1e1bdf13be07baf01afe

See more details on using hashes here.

File details

Details for the file openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for openflex_driver-1.0.0-cp39-cp39-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 b1a9c7c8facc319e62c8c7e8ecfcfa5fd2d5577b91570914c04f8ed2ac3a76d4
MD5 681f17285aae46711c52871c9e74dada
BLAKE2b-256 47f0ff5306d136a58de0a72c27c8040406a52b76af1dc8da85ec91b97beab3ea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page