robonix.primitive.qmzs.arm7aix.arm

primitive package v0.1.0

ARM7AIX 7-DoF arm primitive over a U2CAN serial adapter: measured joint and TCP feedback, joint and TCP targets, plus package-local joint enable/disable extensions.

README primitive-qmzs-arm7aix-rbnx@main

primitive-qmzs-arm7aix-rbnx

Robonix primitive for the ARM7AIX 7-DoF arm driven over a U2CAN USB-to-classic-CAN serial adapter. It exposes the standard Robonix arm topic contracts plus package-local joint enable/disable extensions, and nothing else.

Catalog name: robonix.primitive.qmzs.arm7aix.arm.

arm7aix_controller/main.py is the primitive (lifecycle, ROS 2 topics, motion worker). arm7aix/ is the bundled Python SDK it uses: U2CAN transport, Damiao motor protocol, URDF kinematics, multi-start IK, joint/Cartesian planning and feedback validation. The SDK is inside this package so the primitive has no external driver dependency.

This primitive drives real hardware. Read Safety and CAPABILITY.md before sending a target. A valid target on joint_command or pos_command can enable the motors and move the arm.

Capability surface

Contract Mode Transport Default topic Message
robonix/primitive/arm/joint_states topic_out ROS 2 /arm7aix/joint_states sensor_msgs/msg/JointState
robonix/primitive/arm/end_pose topic_out ROS 2 /arm7aix/end_pose geometry_msgs/msg/Pose
robonix/primitive/arm/joint_command topic_in ROS 2 /arm7aix/joint_command sensor_msgs/msg/JointState
robonix/primitive/arm/pos_command topic_in ROS 2 /arm7aix/pos_command geometry_msgs/msg/Pose
robonix/primitive/arm/joint_enable topic_in ROS 2 /arm7aix/joint_enable std_msgs/msg/Empty
robonix/primitive/arm/joint_disable topic_in ROS 2 /arm7aix/joint_disable std_msgs/msg/Empty

The first four are the standard arm contracts and mirror the Robonix global capabilities/primitive/arm/*.v1.toml definitions. joint_enable and joint_disable are package-local extensions: they are registered by this package only and are not part of the global arm capability catalog.

Feedback is measured joint data: joint_states reports seven joint positions (rad), velocities (rad/s) and torques (Nm); end_pose reports the measured tool pose relative to base_link in metres with an xyzw quaternion. Pose messages have no frame_id field, so the reference frame is fixed by the instance's pose_frame setting. See CAPABILITY.md for message-level semantics.

Not provided by this primitive: gripper or hand control, MIT/impedance or zero-gravity modes, torque commands, teaching playback, MoveL/MoveC/blended paths, action goal handles, per-command completion/cancel responses, and environment collision avoidance. Those SDK capabilities exist but are not exposed through Robonix contracts here.

Hardware

  • Seven revolute joints driven by Damiao servo motors (DM6248P on J1–J2, DM4340P_48V on J3–J5 and DM4310P_48V on J6–J7). Motor IDs, directions, zero offsets, gear ratios, gains and joint limits live in config/arm7aix.yaml.
  • A U2CAN USB serial adapter bridges the host to the arm's classic CAN bus. The host sees a USB CDC serial device; the default is /dev/ttyACM0 at 921600 8N1. The CAN bitrate (1 Mbit/s) is configured on the U2CAN adapter itself with the vendor tool, not by this package.
  • The URDF is models/urdf_description.urdf with root link base_link and tool link tool0.
  • Reference host: Ubuntu 22.04 with ROS 2 Humble. The deployment this package is extracted from was validated on a Jetson Orin NX (aarch64) host.

U2CAN discovery, serial permissions and feedback-timeout troubleshooting are in docs/hardware_setup.md.

Configuration

The primitive receives its instance configuration through Driver(CMD_INIT). Defaults are in config.spec; the deployment manifest may override any key.

Key Default Meaning
sdk_config config/arm7aix.yaml SDK/hardware YAML, relative to the package root by default; an absolute path or a deployment-relative override is accepted
state_topic /arm7aix/joint_states measured joint feedback topic
end_pose_topic /arm7aix/end_pose measured TCP pose topic
joint_command_topic /arm7aix/joint_command joint target input topic
pos_command_topic /arm7aix/pos_command TCP target input topic
joint_enable_topic /arm7aix/joint_enable enable extension input topic
joint_disable_topic /arm7aix/joint_disable disable extension input topic
joint_command_speed_rad_s 0.5 maximum planned joint speed for joint_command
pos_command_linear_speed_m_s 0.15 TCP translation speed limit for pos_command
state_period_sec 0.05 feedback publication period (20 Hz)
feedback_timeout_sec 2.0 maximum wait for fresh seven-axis feedback at activation
pose_frame base_link reference frame for end_pose/pos_command; must equal kinematics.base_link in sdk_config

pos_command_speed_m_s is still read as a deprecated alias when pos_command_linear_speed_m_s is absent; the new key wins if both are set.

The SDK configuration file holds everything that describes the physical arm: serial port, motor IDs and calibration, joint limits, velocity/acceleration/jerk limits, URDF and IK parameters, dynamics, and safety thresholds (following error, torque, temperature). Treat it as machine-specific: verify it against the real arm before the first motion, and do not widen limits just to silence a planner error.

Build / run standalone

Prerequisites:

  • ROS 2 Humble (source /opt/ros/humble/setup.bash; override with RBNX_ROS_SETUP or ROS_DISTRO) and colcon.
  • Robonix source tree registered with rbnx setup <robonix-checkout>, so rbnx path robonix-api and rbnx codegen work.
  • uv and a Python 3.10+ interpreter at /usr/bin/python3.
  • Network access to a Python package index for the build dependencies. On hosts that cannot reach pypi.org, point uv at a reachable mirror, for example export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple.
bash scripts/build.sh        # codegen + ROS 2 IDL overlay + rbnx-build/venv
bash scripts/start.sh        # registers the provider, then awaits Driver(CMD_INIT)

scripts/build.sh generates the Robonix proto/gRPC stubs and the ROS 2 IDL overlay, builds the overlay with colcon, and creates rbnx-build/venv with robonix-api and the dependencies from requirements.txt. scripts/start.sh sources the ROS 2 environment and overlay, then runs python -m arm7aix_controller.main.

Useful overrides: RBNX_BUILD_CLEAN=1 (remove rbnx-build/ first), RBNX_ROS_SETUP=<setup.bash>, RBNX_PACKAGE_ROOT=<package-root>.

The same package can be built and started through the rbnx CLI, which runs the build/start blocks from package_manifest.yaml:

rbnx build -p .              # build only
rbnx start -p .              # start one instance against an Atlas endpoint

In a deployment, rbnx boot does this automatically; the package is not expected to start on its own in production.

Offline validation

Does not open the serial port, CAN bus or hardware:

rbnx validate .
bash -n scripts/*.sh
python3 -m compileall -q arm7aix arm7aix_controller tests
PYTHONPATH=. rbnx-build/venv/bin/python -m unittest discover -s tests -v

The tests use the real bundled URDF and the SDK planner; they do not require a serial port, CAN adapter or connected arm.

Hardware validation

The maintainers exercised this package on the physical ARM7AIX arm with rbnx: provider activation and seven-axis joint feedback (joint_states), joint motion (joint_command) and single-endpoint TCP motion (pos_command). That run used the deployment's own config/arm7aix.yaml; verify the bundled configuration against your arm before the first motion.

Talking to the primitive

Once the provider is active, inspect it and read feedback from a shell with the same ROS 2 environment:

rbnx caps -v                                         # provider must be ACTIVE
rbnx describe --provider arm7aix_controller          # prints CAPABILITY.md
ros2 topic list | grep /arm7aix
ros2 topic echo --once /arm7aix/joint_states
ros2 topic echo --once /arm7aix/end_pose
tail -F rbnx-boot/logs/arm7aix_controller.log

rbnx-boot/logs/ is created in the deployment working directory; the ros2 commands need a shell with the same ROS 2 environment as the provider.

Command examples — each of these can move the arm; clear the workspace and keep the hardware e-stop reachable first:

# Joint target: exactly the seven configured joint names and radians.
ros2 topic pub --once /arm7aix/joint_command sensor_msgs/msg/JointState \
  "{name: [joint1, joint2, joint3, joint4, joint5, joint6, joint7],
    position: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    velocity: [], effort: []}"

# TCP target: position m + xyzw quaternion in the pose frame (single endpoint).
ros2 topic pub --once /arm7aix/pos_command geometry_msgs/msg/Pose \
  "{position: {x: 0.30, y: 0.0, z: 0.25},
    orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}}"

# Enable at the measured positions, or disable all seven drives.
ros2 topic pub --once /arm7aix/joint_enable std_msgs/msg/Empty "{}"
ros2 topic pub --once /arm7aix/joint_disable std_msgs/msg/Empty "{}"

ros2 topic pub --once returning only means the message was published. These are topic streams with no action goal handle or per-command result; confirm outcomes with feedback and the primitive log. See CAPABILITY.md.

Safety

  • Motion is enabled automatically. Activation only connects and reads feedback. The first valid joint_command or pos_command enables all seven drives in POS_VEL and starts moving; there is no motion-enable gate in this primitive. Send joint_enable first if you want to control when drives are energised.
  • joint_disable is not an emergency stop. It cancels pending and active motion and disables the drives, which removes holding torque — the arm may fall under gravity. Confirm mechanical support and site safety first. A hardware emergency stop must remain available and independent.
  • pos_command constrains the endpoint only. It solves IK for one TCP target and moves there in joint space; the intermediate TCP path and orientation angular velocity are not constrained. Do not use it as a straight-line Cartesian motion or a high-rate servo interface. Multi-start IK cannot guarantee reachability outside the workspace, and there is no environment collision map: verify the sweep volume is clear before moving.
  • Self-collision checking is independently controlled by kinematics.self_collision.enabled in the SDK config and is off by default.
  • One target at a time. At most one target executes and one newer target is kept pending; later messages replace the pending target. Do not stream targets faster than the arm can execute them and expect every intermediate point to be visited.
  • Shutdown does not disable the arm. Deactivation stops the current trajectory and holds position, but leaves the drives enabled. Only an explicit joint_disable removes holding torque.
  • Clear the workspace, confirm joint limits and the configured base mounting (installation.base_rpy), and keep the hardware e-stop reachable before enabling or sending any target. Motion faults, rejected targets and planning failures are written to rbnx-boot/logs/arm7aix_controller.log; do not diagnose a missing outcome from the absence of an error message alone.

Repository layout

primitive-qmzs-arm7aix-rbnx/
├── package_manifest.yaml            # package identity + six capabilities
├── config.spec                      # instance config keys, defaults, ranges
├── CAPABILITY.md                    # contract behaviour and safety caveats
├── README.md
├── LICENSE                          # Mulan PSL v2.0
├── capabilities/primitive/arm/      # 4 standard contracts + 2 local extensions
├── arm7aix_controller/
│   ├── __init__.py
│   └── main.py                      # primitive: lifecycle, topics, motion worker
├── arm7aix/                         # bundled Python SDK (no hardware access at import)
├── config/
│   └── arm7aix.yaml                 # default SDK hardware/motion configuration
├── models/                          # URDF + STL meshes
├── scripts/
│   ├── build.sh                     # codegen + ROS 2 overlay + venv
│   └── start.sh                     # source environment, exec primitive
├── tests/                           # offline planner/IK regression tests
└── docs/
    └── hardware_setup.md            # U2CAN bring-up and troubleshooting

Documentation

  • CAPABILITY.md — behaviour of every contract, units, frames, planning and enable/disable semantics, diagnostics.
  • config.spec — every instance configuration key with type, default and range.
  • docs/hardware_setup.md — U2CAN serial setup, permissions, feedback-timeout troubleshooting.
  • config/arm7aix.yaml — the SDK/hardware configuration that must match the physical arm.

License

Mulan Permissive Software License, Version 2 (MulanPSL-2.0). The full text is in LICENSE.