ROS2 Services#
Every WMX R2 command that is not a trajectory is a service call. Motion, servo power, I/O, EtherCAT diagnostics, engine control, and lifecycle control are all request/response.
The services come from the five nodes started by
wmx_r2_general_nodes.launch.py plus the gripper controller:
Node |
Namespace |
Provides |
|---|---|---|
|
|
Device creation, EtherCAT communication, engine status, WMX parameter import |
|
|
Drives every other node through its lifecycle transitions |
|
|
Servo power, axis configuration, homing, and single-axis motion |
|
|
Digital input and output, by bit and by byte |
|
|
Master and slave status, register read, network scan, hot-connect |
|
|
Gripper open/close over one WMX output bit |
Important
wmx_core_motion_node, wmx_io_node, and wmx_ethercat_node are
managed (lifecycle) nodes. They advertise
their services only while they are active. If ros2 service list
shows nothing under /wmx/axes/, the node is not active — check
/wmx/lifecycle/get_node_states before assuming the node crashed.
wmx_engine_node and wmx_lifecycle_manager_node are ordinary nodes
and are always up.
Service summary#
Service |
Type |
Node |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Every response carries bool success and string message. On the array
services, success is true only if every entry succeeded, and
message concatenates the per-axis or per-entry results.
Engine services#
wmx_engine_node owns the WMX3 engine and nothing else. It does not move
axes.
/wmx/engine/set_engine#
Creates the WMX3 device and starts communication. data: false closes the
device; the managed nodes follow it down within one discovery_period.
wros ros2 service call /wmx/engine/set_engine std_srvs/srv/SetBool "{data: true}"
/wmx/engine/set_communication#
Starts or stops EtherCAT communication on an already open device.
wros ros2 service call /wmx/engine/set_communication std_srvs/srv/SetBool "{data: true}"
/wmx/engine/get_engine_status#
Returns the engine state in message: Idle, Running,
Communicating, Shutdown, or Unknown. Communicating is the
state every controller waits for.
wros ros2 service call /wmx/engine/get_engine_status std_srvs/srv/Trigger "{}"
/wmx/engine/import_and_set_all#
Imports a WMX3 parameter XML into the running engine. The path must be absolute.
wros ros2 service call /wmx/engine/import_and_set_all wmx_r2_message/srv/ImportAndSetAll \
"{path: '/home/admin/workspaces/movensys_ws/install/wmx_r2_package/share/wmx_r2_package/config/wmx_parameters.xml'}"
The same file is normally imported at startup through the launch argument
wmx_param_file; this service is for reloading it without restarting.
/wmx/engine/get_axis_param#
Dumps the active gear ratio, polarity, and command mode of the requested axes as one formatted string per axis. Use it to confirm what the engine actually has, not what the XML says.
wros ros2 service call /wmx/engine/get_axis_param wmx_r2_message/srv/GetAxisParam \
"{axis: [0,1,2,3,4,5]}"
Lifecycle services#
wmx_lifecycle_manager_node watches the engine and drives every managed
node on the graph. While the engine is communicating it brings each node up
to active; when the engine stops, it takes them back to
unconfigured, because their device handles are dead. A node that joins
late or respawns is picked up on the next sweep.
This is not limited to WMX nodes: any managed node in the same namespace is driven the same way.
/wmx/lifecycle/set_node_state#
Drives one node through a transition. An empty node_name applies the
transition to every lifecycle node found. Transitions that take nodes down
are applied in reverse bring-up order.
transition is one of configure, activate, deactivate,
cleanup, shutdown, bringup (configure + activate), or
bringdown (deactivate).
# one node
wros ros2 service call /wmx/lifecycle/set_node_state wmx_r2_message/srv/SetNodeState \
"{node_name: 'wmx_io_node', transition: 'deactivate'}"
# every node
wros ros2 service call /wmx/lifecycle/set_node_state wmx_r2_message/srv/SetNodeState \
"{node_name: '', transition: 'bringdown'}"
/wmx/lifecycle/get_node_states#
Lists every lifecycle node on the graph with its current state, in bring-up order.
wros ros2 service call /wmx/lifecycle/get_node_states wmx_r2_message/srv/GetNodeStates "{}"
The standard CLI works too and bypasses the manager:
wros ros2 lifecycle get /wmx_io_node
wros ros2 lifecycle set /wmx_io_node activate
Parameter |
Default |
Meaning |
|---|---|---|
|
|
Bring-up order; take-down is the reverse |
|
|
Seconds between engine-state sweeps |
Axis services#
wmx_core_motion_node serves both the configuration services and the
manual motion services. axis and data arrays must be the same length.
Danger
start_pos, start_mov, start_vel, start_jog, and
start_home rotate the axes. On a physical robot, complete
Try Your Robot first.
Configuration and power#
Service |
|
|---|---|
|
|
|
ignored |
|
|
|
|
|
ignored |
|
ignored |
# servo on axes 0 and 1
wros ros2 service call /wmx/axes/set_servo_on wmx_r2_message/srv/SetAxes \
"{axis: [0,1], data: [1,1]}"
# clear amplifier alarms
wros ros2 service call /wmx/axes/clear_amp_alarm wmx_r2_message/srv/SetAxes \
"{axis: [0,1], data: [0,0]}"
# reverse the direction of axis 2
wros ros2 service call /wmx/axes/set_axis_polarity wmx_r2_message/srv/SetAxes \
"{axis: [2], data: [-1]}"
/wmx/axes/set_gear_ratio sets the encoder-count-to-user-unit ratio per
axis. This is the parameter that makes one axis user unit equal one radian
at the joint:
wros ros2 service call /wmx/axes/set_gear_ratio wmx_r2_message/srv/SetAxesGearRatio \
"{axis: [0,1], numerator: [8388608.0, 8388608.0], denominator: [360.0, 360.0]}"
/wmx/axes/start_home homes with the HomeType configured in the WMX
parameter file for that axis. The shipped parameter files use
CurrentPos, which makes the current encoder position zero. The service
does not write the home configuration, so a switch-based or Z-pulse setup is
left alone.
/wmx/axes/stop decelerates the axes to a stop. It is the one motion
service that is never blocked, even while a controller owns the axes.
Warning
stop is a controlled deceleration, not an emergency stop. A real
e-stop must be a hardware circuit — see Safety Functions and Responsibility.
Manual motion#
# absolute move
wros ros2 service call /wmx/axes/start_pos wmx_r2_message/srv/StartAxesPose \
"{axis: [0,1], target: [45, -90], velocity: [10, 20], acc: [10, 20], dec: [10, 20]}"
# relative move
wros ros2 service call /wmx/axes/start_mov wmx_r2_message/srv/StartAxesPose \
"{axis: [0,1], target: [10, -10], velocity: [10, 20], acc: [10, 10], dec: [10, 20]}"
# constant velocity until stopped
wros ros2 service call /wmx/axes/start_vel wmx_r2_message/srv/StartAxesVelocity \
"{axis: [0,1], velocity: [10, -10], acc: [10, 20], dec: [10, 20]}"
/wmx/axes/start_jog is a dead-man jog in Position mode: keep calling it
to keep moving, stop calling it to release. The sign of velocity selects
the direction.
while true; do
wros ros2 service call /wmx/axes/start_jog wmx_r2_message/srv/StartAxesVelocity \
"{axis: [0], velocity: [10], acc: [100], dec: [100]}"
sleep 0.05
done
Parameter |
Default |
Meaning |
|---|---|---|
|
|
|
|
|
Axis stops this long after jog refreshes stop arriving |
|
|
Maximum duration of one jog, enforced engine-side |
|
|
Jerk ratio of the jog profile |
|
|
While one is |
|
|
Seconds between re-queries of each controller’s state |
Controller arbitration#
A manual jog must not fight a running trajectory. While any node listed in
motion_controllers is active, wmx_core_motion_node refuses its
own motion services and answers success: false:
Blocked while a controller is active |
Always available |
|---|---|
|
|
The configuration services stay open because joint_state_broadcaster
itself calls set_servo_on when it activates.
I/O services#
addr is the I/O byte address and bit is the index inside that byte
(0–7). All data values are decimal.
Service |
Reads / writes |
|---|---|
|
One bit |
|
Scattered bits, one |
|
One byte |
|
|
|
One output bit |
|
Scattered output bits, together in one SDK call |
|
One output byte |
|
Consecutive output bytes from |
wros ros2 service call /wmx/io/get_in_bit wmx_r2_message/srv/GetIoBit "{addr: 0, bit: 0}"
wros ros2 service call /wmx/io/get_in_bits wmx_r2_message/srv/GetIoBits \
"{addr: [0, 2], bit: [1, 5]}"
wros ros2 service call /wmx/io/get_in_bytes wmx_r2_message/srv/GetIoBytes "{addr: 0, size: 4}"
wros ros2 service call /wmx/io/set_out_bit wmx_r2_message/srv/SetIoBit \
"{addr: 0, bit: 0, data: 1}"
wros ros2 service call /wmx/io/set_out_bits wmx_r2_message/srv/SetIoBits \
"{addr: [0, 2], bit: [1, 5], data: [1, 0]}"
# 15 = 0x0F
wros ros2 service call /wmx/io/set_out_byte wmx_r2_message/srv/SetIoByte "{addr: 2, data: 15}"
wros ros2 service call /wmx/io/set_out_bytes wmx_r2_message/srv/SetIoBytes \
"{addr: 2, data: [15, 14]}"
EtherCAT services#
/wmx/ecat/get_master_info#
Reads master and per-slave status. This is the first call to make when the network does not come up.
wros ros2 service call /wmx/ecat/get_master_info wmx_r2_message/srv/EcatGetMasterInfo \
"{master_id: 0}"
Field |
Values |
|---|---|
|
|
|
|
The response also carries the communication period, the total axis count,
the transmit-delay and packet-loss counters, and one entry per slave in the
parallel slave_* arrays (state, AL status code, vendor/product ID,
input/output address and size, axis count). A slave stuck in Preop with
a non-zero slave_al_status_codes entry is the usual failure.
/wmx/ecat/register_read#
Reads len bytes from a slave ESC register. reg_addr is decimal, in
the range 0x000–0xFFF, with reg_addr + len ≤ 0x1000.
wros ros2 service call /wmx/ecat/register_read wmx_r2_message/srv/EcatRegisterRead \
"{master_id: 0, slave_id: 0, reg_addr: 16, len: 4}"
/wmx/ecat/reset_statistics#
Resets the reference-clock and transmit statistics, then re-scans the network.
wros ros2 service call /wmx/ecat/reset_statistics wmx_r2_message/srv/EcatResetStatistics \
"{master_id: 0}"
/wmx/ecat/scan_network#
Re-scans the network for slaves.
wros ros2 service call /wmx/ecat/scan_network wmx_r2_message/srv/EcatScanNetwork "{master_id: 0}"
/wmx/ecat/start_hotconnect#
Enables dynamic slave discovery. Call it once, after the network has reached
Op.
wros ros2 service call /wmx/ecat/start_hotconnect wmx_r2_message/srv/EcatStartHotconnect \
"{master_id: 0}"
Gripper service#
/wmx/set_gripper#
Served by gripper_controller, which is started only when the manipulator
launch is given use_gripper:=true. The service name comes from the
wmx_gripper_topic parameter (named “topic” for historical reasons — it is
a service).
wros ros2 service call /wmx/set_gripper std_srvs/srv/SetBool "{data: true}" # close
wros ros2 service call /wmx/set_gripper std_srvs/srv/SetBool "{data: false}" # open
data: true drives the configured output bit to 1, false to 0. The
bit is set by the gripper_address: [byte, bit] parameter. The service
returns success: false when the node is not active.
Note
pre_setup_io defaults to false. With it false, configure skips
the gripper power-up sequence and the service then toggles a bit on an
unpowered gripper. The power-up addresses are compiled in, so set
pre_setup_io: true only if your gripper matches them.
Startup sequence#
The order below is what the manipulator and differential launches perform automatically. Run it by hand only when using the general nodes on their own.
# 1. Verify the engine is communicating
wros ros2 service call /wmx/engine/get_engine_status std_srvs/srv/Trigger "{}"
# 2. Set the gear ratio (encoder counts per user unit)
wros ros2 service call /wmx/axes/set_gear_ratio wmx_r2_message/srv/SetAxesGearRatio \
"{axis: [0, 1], numerator: [8388608.0, 8388608.0], denominator: [360.0, 360.0]}"
# 3. Clear any amplifier alarms
wros ros2 service call /wmx/axes/clear_amp_alarm wmx_r2_message/srv/SetAxes \
"{axis: [0,1], data: [0,0]}"
# 4. Enable the servos
wros ros2 service call /wmx/axes/set_servo_on wmx_r2_message/srv/SetAxes \
"{axis: [0,1], data: [1,1]}"
# 5. Home the axes
wros ros2 service call /wmx/axes/start_home wmx_r2_message/srv/SetAxes \
"{axis: [0,1], data: [0,0]}"
sequenceDiagram
autonumber
participant U as You / launch file
participant E as wmx_engine_node
participant L as wmx_lifecycle_manager_node
participant M as wmx_core_motion_node
participant W as WMX3 engine
U->>E: set_engine (data: true)
E->>W: CreateDevice + start communication
W-->>E: Communicating
L->>E: get_engine_status (every discovery_period)
E-->>L: Communicating
L->>M: configure, then activate
Note over M: services /wmx/axes/* appear only now
U->>M: set_gear_ratio
U->>M: clear_amp_alarm
U->>M: set_servo_on
U->>M: start_home
U->>M: start_pos
M->>W: CoreMotion StartPos
W-->>M: motionComplete + inPos
General-node startup, from engine to a moving axis#
Error handling#
Symptom |
Cause |
|---|---|
|
The node is not |
|
A node in |
|
Array services are all-or-nothing in |
|
An |
Service call hangs |
The engine is not communicating. Check
|
Note
Node parameters are read once at startup. ros2 param set is accepted
by rclcpp but changes nothing — edit the config YAML and restart the node.
See also#
ROS2 Topics – published and subscribed topics
ROS2 Actions – the
FollowJointTrajectoryactionwmx_r2_message – message and service definitions
wmx_r2_package – nodes, launch files, and configuration
Troubleshooting – diagnosis by symptom