---json
{"name": "Servo and LED command topics"}
---
====== Servo and LED command topics ======
Send servo targets and LED colours directly to the Axiom host driver using standard ROS topics. The driver converts the messages to the commands described by the connected device's firmware profile. It uses its existing USB or Wi-Fi connection; no second connection or firmware ROS node is needed.
Complete [[:axiom:ros2:getting_started|Install and connect]], use current host firmware, and leave discovery running. These interfaces are in the current ''main'' source. After pulling driver changes, rebuild, source the workspace and restart the driver and consumers. Existing sensor measurements keep their normal topics.
===== Topics and acknowledged services =====
^ Operation ^ ROS interface ^ Input ^
| Servo ''angle'' or ''set angle'' | Topic under the device's ''commands'' path | ''std_msgs/msg/Float64'', radians |
| Indexed LED colour, descriptor ''f: LEDPIX'' | One topic per pixel, for example ''commands/pixels/pixel_0'' | ''std_msgs/msg/ColorRGBA'', RGB channels from 0 to 1 |
| Three-byte ''color'', ''colour'' or ''rgb'' | Topic named for the descriptor action | ''std_msgs/msg/ColorRGBA'', RGB channels from 0 to 1 |
| Servo enable/disable | Descriptor service | ''axiom_interfaces/srv/DeviceCommand'', usually ''values: [1.0]'' / ''[0.0]'' |
| LED brightness/off, sample rate and other supported configuration | Descriptor service | Numeric arguments in descriptor order and units |
The word ''actions'' in a device descriptor does not require a ROS action server. Continuous targets use topics; the discrete operations above use request/response services. A service success acknowledges the firmware request, not completion of physical motion. Topic publication has no per-message completion response. The driver does not provide a trajectory controller.
{{ :axiom:ros2:ros2-output-control-5bf126e.png?760&nolink |Standard command topics feed the driver; discrete operations use acknowledged services}}
//Board namespaces and sensor-instance names in this reference graph are placeholders. Solid arrows carry target messages; dashed arrows represent service request/response.//
===== Find the actual inputs =====
In a prepared terminal, select the board namespace from ''/axiom_discovery/boards''. Names below are placeholders, not identifiers for a particular board:
# Load the workspace and the same ROS domain/middleware as discovery.
source scripts/setup_env.sh
# Inspect the retained board inventory.
ros2 topic echo /axiom_discovery/boards std_msgs/msg/String \
--qos-reliability reliable --qos-durability transient_local \
--qos-depth 1 --full-length --once
# Set the selected board's complete namespace, including the leading slash.
BOARD_NS='PASTE_DISCOVERED_BOARD_NAMESPACE_HERE'
# Read the devices and their advertised command interfaces.
ros2 topic echo "$BOARD_NS/devices" std_msgs/msg/String \
--qos-reliability reliable --qos-durability transient_local \
--qos-depth 1 --full-length --once
For each online, fresh device with resolved metadata:
* ''command_topics'' lists relative ''topic'', ''message_type'', ''unit'', command ''name'', ''kind'' and the original ''descriptor''. Indexed LEDs also include ''pixel''.
* ''commands'' lists the remaining acknowledged services, with relative ''service'' paths and descriptors.
* ''public_topics'' and ''output_info'' describe measurement outputs. An output-only controller may have no measurement outputs and still expose command inputs.
Prefix the advertised relative paths with the board namespace. A servo example is ''/axiom/roboticalservo_b1_10/commands/angle''. An indexed LED example is ''/axiom/qwiicledstick_b1_20/commands/pixels/pixel_0''. Model, bus, address and action name follow the live descriptor; copy the actual paths. Measurement ''topic_aliases'' do not create command-topic aliases.
# Copy the full servo angle topic from this board's command_topics entry.
ANGLE_TOPIC='PASTE_FULL_SERVO_ANGLE_TOPIC_HERE'
# Inspect the input type, subscriber and QoS.
ros2 topic info "$ANGLE_TOPIC" --verbose
# List acknowledged device services; the old angle service should be absent.
ros2 service list -t
Before a controller publishes, expect one driver subscription and zero publishers on the angle topic. A subscription-only command topic is usable. It does not need to produce a message when inspected with ''ros2 topic echo''.
===== Send a servo target =====
For a slider and preview, use [[:axiom:ros2:servo_slider|the servo demo]]. For direct CLI control, copy this device's enable service and angle topic. Use one command source for the demonstration; stop the slider before sending independent manual targets.
# Copy this servo's full enable-service path from its commands entry.
ENABLE_SERVICE='PASTE_FULL_SERVO_ENABLE_SERVICE_HERE'
# Copy this servo's full Float64 angle-topic path.
ANGLE_TOPIC='PASTE_FULL_SERVO_ANGLE_TOPIC_HERE'
# Enable and wait for a successful firmware acknowledgement.
ros2 service call "$ENABLE_SERVICE" axiom_interfaces/srv/DeviceCommand '{values: [1.0]}'
Choose a small target appropriate to the mechanism and its descriptor limits. Enabling may energise a motor at its existing target. Once enable succeeds:
# Request about five degrees, expressed in ROS radians.
ros2 topic pub --once "$ANGLE_TOPIC" std_msgs/msg/Float64 '{data: 0.0872664626}'
The driver converts radians to the descriptor's units, applies its integer wire resolution and rejects nonfinite or out-of-range values. Units come from the action's ''u'', then the reported ''angle'' attribute's ''u'', defaulting to degrees for existing descriptors. Supported units are ''degrees''/''deg'' and ''radians''/''rad''. Direct angle publication does not enable the servo automatically; the slider demo has its own startup-enable behaviour.
When finished, disable while the driver is still connected:
# Disable this servo and wait for acknowledgement before stopping its driver.
ros2 service call "$ENABLE_SERVICE" axiom_interfaces/srv/DeviceCommand '{values: [0.0]}'
Stopping an echo, publisher or driver is not a firmware disable request.
===== Set an LED colour =====
For indexed LEDs, choose the advertised pixel topic. Indices start at zero and follow the descriptor's ''NX × NY'' ordering. Different pixels use separate topics; multiple LED controllers have separate device roots. A stack light requires a compatible live descriptor before these inputs appear; its PCB name alone does not establish support.
# Copy the full colour topic for the desired pixel or whole-device RGB action.
COLOUR_TOPIC='PASTE_FULL_LED_COLOUR_TOPIC_HERE'
# Set that output to red with normalized RGB components.
ros2 topic pub --once "$COLOUR_TOPIC" std_msgs/msg/ColorRGBA \
'{r: 1.0, g: 0.0, b: 0.0, a: 1.0}'
# Request black on the same output.
ros2 topic pub --once "$COLOUR_TOPIC" std_msgs/msg/ColorRGBA \
'{r: 0.0, g: 0.0, b: 0.0, a: 1.0}'
RGB values must be finite and within 0..1; the driver converts them to bytes. Alpha is ignored because the supported RGB commands have no transparency channel. Device-specific brightness or off operations remain services if the descriptor advertises them; consult their argument lists rather than assuming every LED board has the same controls.
===== Delivery, lifecycle and migration =====
Command subscriptions use **reliable, volatile, keep-last depth 1** QoS. Use a compatible reliable publisher. They do not request a publisher's retained old target when a device reappears. The driver keeps the latest pending target per topic; intermediate values may be coalesced while firmware is busy. Different pixels keep independent pending targets. Identical acknowledged values are deduplicated.
Removed, stale or replaced devices and ended sessions discard pending targets and retire subscriptions. Queued targets older than ''rpc_default_timeout'' expire. Firmware failures appear in driver logs and ''diagnostics''; a failed target is not retried without fresh input. Acknowledged enable/off operations clear earlier pending targets and the deduplication cache for that device. Sensor processing and command writes share the driver worker, so slow output replies can delay measurement processing.
**The former servo-angle and LED-colour services have been removed.** There is no legacy service mode. Update scripts from ''ros2 service call'' / ''DeviceCommand.values'' to the advertised standard-message topics. Servo topic values are radians even when the old service used descriptor degrees. Indexed RGB inputs use ''pixel_0'', ''pixel_1'', etc.; the ROS path cannot end in a numeric-only token such as ''/0''. Enable/configuration services keep their existing contract.
===== Troubleshooting =====
^ Symptom ^ Check ^
| No command input | Current rebuilt driver, correct board namespace, online/fresh metadata, and a supported numeric angle or RGB descriptor. Inspect ''device_metadata'' for unsupported custom formats. |
| Zero publishers on an angle topic | Expected before a controller starts; inspect subscription count. |
| ''ros2 service call'' cannot find angle/colour | Those services were removed. Use ''command_topics'' and the appropriate ROS message type. |
| CLI reports publication but hardware does not respond | Enable state, correct output/pixel, descriptor limits, driver diagnostics and physical board capability. Publication alone is not a firmware acknowledgement. |
| LED has the wrong intensity | Use normalized RGB 0..1, check any separate device brightness setting, and remember alpha is ignored. |
| Echo waits while the slider is stationary | The demo publishes changed targets, not a continuous heartbeat of the same angle. Move the slider after starting the echo. |
Continue with [[:axiom:ros2:servo_slider|Servo slider and right-leg preview]], [[:axiom:ros2:sensors_and_boards|Sensors and multiple boards]] or [[:axiom:ros2:start|the ROS overview]].