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.
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.mdbefore sending a target. A valid target onjoint_commandorpos_commandcan 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 (
DM6248Pon J1–J2,DM4340P_48Von J3–J5 andDM4310P_48Von J6–J7). Motor IDs, directions, zero offsets, gear ratios, gains and joint limits live inconfig/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/ttyACM0at9216008N1. 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.urdfwith root linkbase_linkand tool linktool0. - 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 withRBNX_ROS_SETUPorROS_DISTRO) andcolcon. - Robonix source tree registered with
rbnx setup <robonix-checkout>, sorbnx path robonix-apiandrbnx codegenwork. uvand 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
uvat a reachable mirror, for exampleexport 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_commandorpos_commandenables all seven drives in POS_VEL and starts moving; there is no motion-enable gate in this primitive. Sendjoint_enablefirst if you want to control when drives are energised. joint_disableis 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_commandconstrains 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.enabledin 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_disableremoves 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 torbnx-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.