---json {"name": "Servo slider and right-leg preview"} --- ====== Servo slider and right-leg preview ====== Control one servo through the driver's direct angle-command topic using the same ''%%joint_state_publisher_gui%%'' sliders as Marty. The GUI runs alongside RViz. The GUI adapter publishes radian targets and calls an acknowledged enable service; it does not open a second USB/Wi-Fi connection or start another Axiom driver. No trajectory controller is required. {{ :axiom:ros2:ros2-right-leg-preview-91000b4.png?760&nolink |The optional Marty right-leg target preview and joint slider in RViz}} //The preview shows requested joint position, not measured hardware feedback. The model is bundled; it requires no full Marty or Marty driver.// ===== Build and select a board ===== From the repository root on a ROS desktop: # Load the ROS environment and built workspace in this terminal. source scripts/setup_env.sh # Install dependencies declared by the core packages. rosdep install --from-paths src --ignore-src -r -y # Build the updated packages before restarting ROS processes. colcon build --base-paths src --packages-up-to axiom_servo_demo --symlink-install # Load the ROS environment and built workspace in this terminal. source scripts/setup_env.sh Keep the normal driver/discovery running in another prepared terminal: # Start discovery using the selected board configuration. ros2 launch axiom_driver axiom.launch.py Find the board namespace and inspect its devices. Set ''BOARD_NS'' to the actual namespace, such as ''%%/axiom_%%''; the name comes from your inventory, not discovery order: # Inspect messages using the shown type and QoS. ros2 topic echo /axiom_discovery/boards std_msgs/msg/String \ --qos-reliability reliable --qos-durability transient_local \ --qos-depth 1 --full-length --once # Select the full board namespace reported above; this variable is local to this pane. BOARD_NS='PASTE_DISCOVERED_BOARD_NAMESPACE_HERE' # Inspect the selected board's devices and 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 The adapter selects a device only when it is online, fresh, has resolved metadata and advertises a radian ''%%Float64%%'' angle input in ''%%command_topics%%'' and a numeric ''%%enable%%'' operation in ''%%commands%%''. It does not depend on a particular device type name. When several devices match, copy the chosen row's exact ''%%topic%%'' into the ''%%servo%%'' launch argument. This is the relative device root, without the board namespace. The descriptor commands must use the driver's supported numeric formats. A custom ''%%vt%%'' command format is not supported. Enable must accept both ''%%0%%'' and ''%%1%%''. The adapter uses the discovered angle topic, including any escaped action name. ''%%enable_command%%'' selects an alternative enable/disable action name if needed. ===== Start the slider ===== Keep discovery running in **Terminal 1**. Use **Terminal 2** for inventory, status and disable calls. Launch the slider/RViz command in **Terminal 3**; **Terminal 4** is available for topic inspection. The [[:axiom:ros2:getting_started#use_tmux_for_the_ros_consoles|tmux helper]] prepares the four panes. Source ''scripts/setup_env.sh'' in reused panes after a rebuild. Variables and environment changes in one pane do not change the others. Choose demo limits appropriate to the attached mechanism. These limits apply to both the GUI and the adapter; the driver enforces live descriptor limits. The launch default is −90° to +90°; the commands below deliberately use a smaller ±15° demonstration range. Set limits appropriate to your mechanism. The model is a schematic servo body and horn. The demo enables the selected servo once on startup by default. For a visual-only test without an enable request, append ''%%start_enabled:=false%%''. # Select the full board namespace again in this launch terminal. BOARD_NS='PASTE_DISCOVERED_BOARD_NAMESPACE_HERE' # Open the slider and target preview for the selected Axiom. ros2 launch axiom_servo_demo servo_demo.launch.py \ axiom_namespace:="$BOARD_NS" \ lower_limit_deg:=-15.0 upper_limit_deg:=15.0 To select one of several servos, append ''%%servo:=PASTE_DEVICE_TOPIC_ROOT_HERE%%''. The slider, ''%%joint_commands%%'' and driver angle topic all use ROS radians; limit arguments remain degrees. The driver converts to the descriptor's units and integer wire resolution. The old ''%%angle_command%%'' and ''%%command_unit%%'' launch arguments and the angle service implementation have been removed. The joint-slider window and RViz open together. RViz is labelled **Servo target preview (not measured position)**: its model follows the GUI even when the physical output is disarmed, disconnected or has not reached the target. ==== Right-leg hip preview and live toggle ==== To use the hip model of a standalone Marty right leg, append ''%%preview_model:=right_leg%%'': # Select the full namespace of the board carrying this servo. BOARD_NS='PASTE_DISCOVERED_BOARD_NAMESPACE_HERE' # Show the right-leg hip while keeping the existing servo-control workflow. ros2 launch axiom_servo_demo servo_demo.launch.py \ axiom_namespace:="$BOARD_NS" \ preview_model:=right_leg \ lower_limit_deg:=-15.0 upper_limit_deg:=15.0 The package includes only the right-leg URDF geometry and meshes, with no Marty driver or separate Marty installation required. The same single ''%%servo_joint%%'' slider drives the hip/thigh joint. Its parallel linkage follows through the URDF mimic joints, whose calculated positions also appear in ''%%joint_commands%%''; the adapter uses only ''%%servo_joint%%''. The knee and twist axes remain at neutral. This still shows the requested target, not measured hardware position, and uses the model's neutral pose and axis direction without calibrating the physical servo's mounting. **Toggle it while running:** in RViz's **Displays** panel, uncheck or check the **RobotModel** display named **Right leg target preview (not measured position)**. This hides/shows the model immediately while the slider and servo adapter keep running. Hiding the preview does not disable the servo; use the acknowledged disable service below for that. ''%%preview_model:=servo%%'' keeps the original schematic preview and is the default. ''%%rviz:=false%%'' starts without an RViz window while keeping the joint-slider GUI. The [[https://github.com/robotical/axiom-ros2/blob/main/src/axiom_servo_demo/meshes/marty_right_leg/README.md|asset notes]] record the source revision, Apache-2.0 licence and model adaptations. ===== Startup enable, movement and disable ===== ''%%start_enabled%%'' defaults to ''%%true%%''. After selecting a compatible servo, the adapter waits for a valid, fresh slider message and the enable service to become available. It sends one enable request and waits for firmware acknowledgement before arming angle commands. Wait for **Servo enabled; move the slider to send an angle**, then move the slider. There is no separate enable command for this normal startup. The initial slider position is a baseline: the adapter sends no angle on startup or enable, including slider changes made while waiting for the acknowledgement. Enable itself may energise the motor at its existing target according to firmware. Use small changes first. The hardware may move directly to a new target; this demo adds neither a trajectory nor a velocity ramp. The driver service response confirms firmware acknowledgement, not physical completion. With ''%%start_enabled:=false%%'', the adapter stays disarmed until explicitly enabled. For this mode, or to re-enable after a disconnect, failure or explicit disable, wait for the slider and selected-device message, then run in a prepared terminal: # Enable explicitly when startup enabling is off or a later re-enable is needed. ros2 service call /servo_demo/set_enabled std_srvs/srv/SetBool '{data: true}' Once the call succeeds, **move the slider** to send a new angle. Explicit enable and disable requests cancel any pending automatic startup enable. A failed or timed-out startup enable is not retried automatically. Disable before stopping the demo: # Disable the physical output and wait for acknowledgement before stopping. ros2 service call /servo_demo/set_enabled std_srvs/srv/SetBool '{data: false}' Wait for success, then stop the demo with Ctrl+C. A disable request immediately stops new angle dispatch and sends disable after an outstanding request finishes or times out. Stopping the GUI, losing a connection or killing the adapter does not guarantee that hardware torque is disabled. Local disarming means that the adapter stops sending angles; firmware disable is a separate acknowledged write. ===== Inspect the ROS interfaces ===== The driver advertises the exact relative angle topic in ''devices.command_topics''. Prefix it with the selected board namespace. Before starting the slider, ''ros2 topic info'' should show ''std_msgs/msg/Float64'', one driver subscription and no publisher. The slider adds a publisher; the former angle service is absent. For a live check, start this in Terminal 4, then move the slider: # Copy the complete angle input from the selected board's command_topics inventory. ANGLE_TOPIC='PASTE_FULL_SERVO_ANGLE_TOPIC_HERE' # Observe new radian targets; a stationary slider need not publish another value. ros2 topic echo "$ANGLE_TOPIC" std_msgs/msg/Float64 Press Ctrl+C to stop the echo. For direct CLI angle/LED commands and the service migration, see [[:axiom:ros2:output_topics|Servo and LED command topics]]. joint_state_publisher_gui → /servo_demo/joint_commands (JointState, radians) → servo_adapter → driver's discovered Float64 angle topic servo_adapter → discovered enable service driver's servo joint_states → /servo_demo/observed_joint_states (JointState) # Inspect messages using the shown type and QoS. ros2 topic echo /servo_demo/status std_msgs/msg/String \ --qos-reliability reliable --qos-durability transient_local --qos-depth 1 --once # Inspect messages using the shown type and QoS. ros2 topic echo /servo_demo/joint_commands --once # Inspect messages using the shown type and QoS. ros2 topic echo /servo_demo/observed_joint_states --once ''%%status%%'' is retained JSON containing the selected servo root, local ''%%armed%%'' state, ''%%angle_unit: "rad"%%'' and last status message. ''%%set_enabled%%'' returns an acknowledged result. The adapter uses one outstanding enable/disable RPC and at most one pending angle, replacing intermediate slider values with the latest target. It publishes changed radian targets at up to ''%%command_rate_hz%%'' (default 10 Hz, maximum 50 Hz). The driver owns descriptor conversion, latest-target coalescing, wire dispatch and error diagnostics. Publishing an angle topic is not an acknowledgement. Reported feedback is renamed to the demo's ''%%servo_joint%%''; it is never filled in from requested angles. The adapter listens to the selected device's ''%%/joint_states%%'' output. The driver currently creates that standard output for ''%%RoboticalServo%%'' and ''%%RoboticalSoloServo%%''. Another device type may still support the angle topic and enable service without providing this feedback topic. Whether firmware's reported angle represents measured position depends on the board/servo implementation. No feedback is needed to move the slider. ===== Reconnects and troubleshooting ===== Device removal, staleness, replacement, ambiguous selection or an inventory gap longer than 2.5 seconds clears the selection and all pending angles. Slider input older than one second or an enable/disable RPC failure disarms GUI output. Angle-topic rejections are reported by the driver's diagnostics and logs; they do not provide a per-message service response or change the GUI's local armed state. A reconnect never automatically enables or replays the previous angle. Once inventory and the slider are live again, call ''%%set_enabled%%'' and move the slider. Losing the first selected device cancels startup enabling even if it had not yet become ready. Starting a new demo process uses ''%%start_enabled%%'' again. If selection keeps waiting, check ''%%/axiom/devices%%'' for ''%%online%%'', ''%%stale%%'', ''%%metadata_ready%%'' and the advertised command names/descriptors. For rejected angles, inspect driver diagnostics and both the configured and live limits. Matching ROS domains and a sourced, rebuilt workspace are required in all terminals. The launch defaults to using an already-running driver. For headless validation, append ''%%gui:=false rviz:=false start_enabled:=false%%''; publish valid ''%%JointState%%'' messages to ''%%/servo_demo/joint_commands%%'' to supply input. The node's timeout parameters are available through ''%%ros2 run axiom_servo_demo servo_adapter --ros-args%%'' for slower links; the normal launch exposes board/command selection, limits and command rate. Automated tests use synthetic inventories, real ROS topics/services and framed mock firmware. They include the complete slider-adapter/driver command path. Physical operation and the new controller board's live descriptor require hardware acceptance. Stack lights are outside this slider demo. Continue with [[:axiom:ros2:output_topics|direct output topics]] or return to [[:axiom:ros2:start|Axiom with ROS 2]].