Commissioning and First Motion#
Warning
Do not start this procedure until Robot Parameter Configuration and Validation is complete and the same configuration has run cleanly in Simulation and HIL. This is stage 4 of the The simulation-first workflow. The purpose of this procedure is to discover wrong parameters with the robot moving slowly and by small amounts, which is the only cheap way to find them.
Before the first command, confirm that the separate safety measures described in Safety Functions and Responsibility are installed and tested — in particular a hardwired emergency stop that removes drive power independently of this software.
Preconditions#
Check |
Requirement |
|---|---|
Parameter review |
Robot Parameter Configuration and Validation completed; the joint↔axis table written down |
Simulation |
The same URDF and MoveIt configuration planned and executed correctly |
HIL |
The real WMX runtime loaded your parameter file and executed a trajectory against the simulated bus with no errors |
Workspace |
The robot is clear of people, fixtures, cabling, and the ground plane through its full expected travel — not just its current pose |
Emergency stop |
A hardwired E-stop that removes drive power is installed, reachable from the operating position, and has been function-tested this session |
Mechanical |
Payload and tooling removed or fully secured; brakes, if fitted, verified to hold |
Recovery |
You know how to clear an alarm and how to restore power after an E-stop |
Stage 4A — Bring the axes up without commanding motion#
Start only the general nodes. This path uses no planner, no MoveIt, and no Servo, so nothing can generate a trajectory while you are still checking feedback.
sudo --preserve-env=PATH \
--preserve-env=AMENT_PREFIX_PATH \
--preserve-env=COLCON_PREFIX_PATH \
--preserve-env=PYTHONPATH \
--preserve-env=LD_LIBRARY_PATH \
--preserve-env=ROS_DISTRO \
--preserve-env=ROS_VERSION \
--preserve-env=ROS_PYTHON_VERSION \
--preserve-env=ROS_DOMAIN_ID \
--preserve-env=RMW_IMPLEMENTATION \
bash -c "source /opt/ros/${ROS_DISTRO}/setup.bash && source $HOME/workspaces/movensys_ws/install/setup.bash && \
ros2 launch wmx_r2_package wmx_r2_general_nodes.launch.py"
Confirm the engine and the bus, then read back the parameters the engine actually holds:
ros2 service call /wmx/engine/get_status std_srvs/srv/Trigger # expect "Communicating"
ros2 service call /wmx/ecat/get_network_state \
wmx_r2_message/srv/EcatGetNetworkState # expect every drive present
ros2 service call /wmx/params/get wmx_r2_message/srv/GetWmxParams \
"{index: [0,1,2,3,4,5]}" # gear ratio, polarity, mode
Checkpoint. The gear ratio, polarity, and command mode in the response must match the table you built in Robot Parameter Configuration and Validation. Stop here if they do not.
Now watch the feedback with the servos still off and move each joint by hand where the mechanics allow it:
ros2 topic echo /wmx/axis/state
Check |
Expected |
|---|---|
|
all |
|
plausible values, and stable when nothing is moving |
Joint numbering |
moving physical joint N by hand changes |
Direction |
moving a joint in the URDF’s positive direction increases
|
Magnitude |
a hand-moved 90° rotation changes |
Note
This hand-check catches swapped axes, inverted polarity, and wrong gear ratios before any motor is energized. It is the highest-value step in the whole procedure. On a robot whose joints cannot be back-driven, defer these three checks to stage 4B and use the smallest steps in the table.
Stage 4B — One axis, low speed, small step#
Enable one axis only. Leave every other axis off.
ros2 service call /wmx/axis/clear_alarm wmx_r2_message/srv/SetAxis \
"{index: [0], data: [0]}"
ros2 service call /wmx/axis/set_on wmx_r2_message/srv/SetAxis \
"{index: [0], data: [1]}"
Command a small relative move. The units are radians, and the velocity and
acceleration are rad/s and rad/s² (this holds only because
AxisGearRatioDenominator is 2π — see Robot Parameter Configuration and Validation):
# +0.05 rad (≈2.9°) at 0.05 rad/s with gentle ramps
ros2 topic pub --once /wmx/axis/position/relative wmx_r2_message/msg/AxisPose \
"{index: [0], target: [0.05], velocity: [0.05], acc: [0.1], dec: [0.1]}"
Warning
The examples in ROS2 Topics use values such as
velocity: [5.0] to illustrate the message format. Those are not
commissioning values. For a first move use velocity ≤ 0.05 rad/s and
acceleration ≤ 0.1 rad/s², and increase only after each check below
passes.
Work through this sequence for the axis, repeating each step in both directions:
# |
Check |
How |
|---|---|---|
1 |
Joint numbering |
Command |
2 |
Direction |
Command |
3 |
Travel distance |
Command |
4 |
Home position |
Move the joint to a known mechanical reference (a machined face, a
scribed mark, a mechanical stop approached slowly). Compare
|
5 |
Feedback agreement |
With the axis stationary, |
6 |
Range of travel |
Approach each end of the intended travel in small steps at low speed, confirming the mechanical range matches the URDF limits. Remember that WMX soft limits are disabled in the shipped parameter files. |
Disable the axis before moving to the next one:
ros2 service call /wmx/axis/set_on wmx_r2_message/srv/SetAxis \
"{index: [0], data: [0]}"
Checkpoint. Do not proceed to multi-axis motion until every axis has passed checks 1–6 individually.
Stage 5 — Multi-axis motion#
Only after every axis has passed individually:
Enable all axes and command each one in turn from a single node, still at commissioning speeds, confirming no cross-talk.
Bring up the planner (
moveit.launch.py) and plan — but do not execute — a short motion. Confirm in RViz that the planned path matches the physical robot’s current pose.Execute one short, slow, coordinated motion well inside the workspace, with a hand on the E-stop.
Increase speed toward the configured limits in steps, re-checking following error at each step.
Stage 6 — Trajectory execution#
Run the trajectory examples in Trajectory Planning, keeping MoveIt’s velocity and acceleration scaling low for the first runs and raising it once tracking is confirmed.
Keyboard jogging — speeds, steps, and stopping behavior#
keyboard_teleop is a convenience tool for driving MoveIt Servo. It is
not a commissioning tool: it needs the whole planner stack up, it moves the
end effector rather than one axis, and its speeds are set in servo.yaml
rather than per command. Use the /wmx/axis/position/relative procedure
above for stages 4A and 4B, and keyboard jogging afterwards.
The key mappings are in Keyboard Jogging. The quantities that matter
for safety are below, as configured for the CR3A in
movensys_manipulator_moveit_config/config/dobot_cr3a/servo.yaml.
Mode |
Configured value |
Meaning |
|---|---|---|
JOINT ( |
|
One keypress requests full-scale jog velocity for that joint until the command times out. |
TWIST — linear |
|
Maximum commanded end-effector linear speed. |
TWIST — angular |
|
Maximum commanded end-effector angular speed. |
POSE |
0.01 m per keypress |
Each keypress shifts an absolute target by 10 mm. The target is then streamed continuously at ~50 Hz, so the arm drives to it and holds it. |
Command rate |
|
Servo emits a command roughly every 25 ms (~40 Hz). |
Mechanism |
Behavior |
|---|---|
Command timeout |
|
Per-keypress travel |
JOINT mode: roughly 0.5 rad/s for ~0.1 s, i.e. on the order of 0.05 rad (≈3°) per keypress, reduced by the smoothing filter. Measure it on your robot rather than relying on this estimate. |
POSE mode |
Does not time out. |
Joint-limit margin |
|
Singularity |
Servo scales velocity down above condition number 17 and stops above 30. |
Collision |
|
|
Restores the terminal and shuts the |
|
Same handler as |
Danger
``q`` and ``Ctrl+C`` are not emergency stops.
Both do exactly one thing: they terminate the keyboard_teleop process.
Motion then stops only as a side effect — Servo stops receiving commands
and halts after its 0.1 s timeout.
Neither one:
removes power from the motors — the servos stay enabled and holding,
engages the mechanical brakes,
triggers STO or any drive-level safe stop,
stops the WMX engine or EtherCAT communication,
has any redundancy, monitoring, or guaranteed stopping time,
affects anything else that is commanding the robot. A
move_grouptrajectory already in flight continues to completion.
They depend on the operating system scheduling a process, on ROS 2 middleware delivery, and on the correct behavior of the software you are in the middle of commissioning. An emergency stop must be a hardwired circuit that removes drive power independently of all of it. See Safety Functions and Responsibility.
To stop motion deliberately from ROS 2, disable the servos — which is a controlled stop, still not an emergency stop:
ros2 service call /wmx/axis/set_on wmx_r2_message/srv/SetAxis \
"{index: [0,1,2,3,4,5], data: [0,0,0,0,0,0]}"
Warning
Known limitation — ``keyboard_teleop`` forces simulated time.
keyboard_teleop sets use_sim_time to true unconditionally in
its node options; there is no launch argument to turn it off. On a physical
robot run without a /clock publisher, the node’s clock does not advance,
so the timestamps on its jog messages are not real time. Confirm the arm
responds as expected in HIL before relying on keyboard jogging on hardware,
and prefer the /wmx/axis/position/relative procedure above for
commissioning.
Record what you verified#
Commissioning results are per robot, not per model. Two units of the same model can differ in encoder zero, motor orientation, and mechanical range. Record, for each axis: the ROS 2 joint name, the WMX axis index, the EtherCAT position, the gear ratio numerator, the polarity, the measured travel for a known command, the home offset, and the measured mechanical range. Keep it with the parameter file — it is what makes the next commissioning, or the next service visit, a check rather than a rediscovery.