ROS 2 topics

xparo_ros talks to the rest of your robot through ordinary ROS 2 topics. Any node on the robot can use them, and so can you from a terminal, with no XPARO-specific code.

Every command on this page was run against a live robot. Open a terminal on the robot and source your workspace first:

source /opt/ros/jazzy/setup.bash
source ~/xparo_ws/install/setup.bash

At a glance

Topic and type

Direction

Use it to

/xparo/ask std_msgs/String

in

Ask the project’s AI assistant a question.

/xparo/response std_msgs/String

out

Read the assistant’s answers and other server messages (JSON).

/xparo/run_task std_msgs/String

in

Run a task on this robot without the dashboard.

/xparo/task_result std_msgs/String

out

Get the result of every task run on this robot (JSON).

/xparo/task_updates std_msgs/String

in

Save your own record in the project’s task history.

/bt_xparo_log std_msgs/String

in

Show live node states from your own behaviour tree executor on the dashboard.

/behavior_tree_log nav2_msgs/BehaviorTreeLog

in

Nav2’s behaviour tree log, forwarded to the dashboard automatically. Only subscribed when nav2_msgs is installed.

/joy sensor_msgs/Joy

out

Receive the dashboard’s Teleop controls.

/diagnostics diagnostic_msgs/DiagnosticArray

in and out

Report health to the dashboard; XPARO also publishes its own status.

/rosout rcl_interfaces/Log

in

ERROR and FATAL log lines from every node are collected for the dashboard’s Health & Errors view.

/ros2_bag_control std_msgs/String

in

Start or stop ROS bag recording.

/ros2_bag_control/recording_status std_msgs/String

out

Current recording state.

/ros2_bag_control/recorder_alive std_msgs/Bool

out

Whether a ROS bag recorder is running.

See it for yourself:

ros2 node list              # /xparo_ros with the launch file, /xparo with ros2 run
ros2 node info /xparo_ros   # every topic above, plus the recorder service clients

Ask the AI assistant

Publish a question on /xparo/ask and read the answer on /xparo/response. It is the same assistant as the dashboard’s Ask here…. bar, so the project needs an LLM API key (see Dashboard (project overview)).

# terminal 1: watch for the answer
ros2 topic echo /xparo/response

# terminal 2: ask
ros2 topic pub --once /xparo/ask std_msgs/msg/String "data: 'what can you do'"

The answer arrives as JSON inside a message object. Without an LLM key it looks like this:

data: '{"message": {"bot_response": "No valid API keys available. Please add or check key statuses.", "responded_by": "llm"}}'

Note

xparo_ros converts the question to upper case before sending it. The question is also saved in the project’s Prompts database, linked to this robot.

/xparo/response also carries other messages from the server that xparo_ros does not handle itself, for example a copy of the project sync when the robot connects. Check for the message key when you only want answers.

Run a task from the robot

Every task in the project is synced to the robot whenever it connects and whenever a task is added, edited, copied or deleted. Publishing a task’s ID on /xparo/run_task runs it right here: the robot builds the tree and its input values from its own copy, so no server round trip is needed to start it, and it even works while the robot is offline. The result is still reported to the dashboard (straight away, or when the connection is back).

Find the task ID in the dashboard (each task’s menu on the Tasks page), then:

# terminal 1: watch results
ros2 topic echo --full-length /xparo/task_result

# terminal 2: run it
ros2 topic pub --once /xparo/run_task std_msgs/msg/String \
  "data: '{\"task_id\": \"<task-id>\", \"override_params\": {\"destination\": \"ward_3\"}}'"

override_params is optional. Its keys are the names of the task’s params (the ones you added under Params in the task form); anything you leave out uses that param’s default.

A task the robot has not synced yet (created while it was offline) finishes immediately with the outcome unknown_task:

data: '{"task_id": "does-not-exist", "run_id": null, "success": false, "duration_s": 0.0, "outcome": "unknown_task", "retryable": false, ...}'

The stage rule still applies: the task’s stage must be one this robot’s xparo_stage accepts, or the result is stage_mismatch.

Note

Known issue in the current package: for runs started on the robot, task inputs mapped From env stay empty, because the robot looks for the environment file in the wrong folder. Inputs mapped as Default value, From task param or Random work. Runs started from the dashboard (Run now, Auto launch) are not affected, because the server fills in those values.

Task results

/xparo/task_result gets one JSON message at the end of every task run on this robot, however it was started (Run now, Auto launch, or /xparo/run_task). The fields are described in Run results. The node also writes a line to its log when a task starts and when it ends:

[INFO] [xparo_ros]: Task 'Deliver medicine' started (run 423eee8ceb45, trigger run_now, time limit 120s)
[INFO] [xparo_ros]: Task 'Deliver medicine' finished: SUCCESS in 11.8s (run 423eee8ceb45)

The trigger is run_now for the dashboard’s Run now, ros_topic for /xparo/run_task, auto_launch for Auto launch tasks and restart_on_failure for a retry.

Save your own task history

Anything published on /xparo/task_updates is saved as a row in the project’s Tasks database, linked to this robot. Use it to record work your own nodes do.

ros2 topic pub --once /xparo/task_updates std_msgs/msg/String \
  "data: '{\"type\": \"door_check\", \"input_data\": {\"door\": \"ward-3\"}, \"output_data\": {\"status\": \"closed\"}}'"

All fields are optional: type (default generic_task), input_data and output_data (any JSON objects) and created_at (ISO time; default now). If the connection is down, the record waits in memory and is sent when the robot reconnects (it is lost if xparo_ros is restarted first).

Show your own behaviour tree live

If you run behaviour trees with your own executor, publish each node’s state change on /bt_xparo_log and the Behaviour page lights up the node with the same name, just like it does for XPARO’s own engine.

ros2 topic pub --once /bt_xparo_log std_msgs/msg/String \
  "data: '{\"node_name\": \"check_door\", \"node_type\": \"Script\", \"prev\": \"RUNNING\", \"curr\": \"SUCCESS\"}'"

Fields: node_name (match it to the node’s name attribute in the tree), node_type, prev and curr (IDLE, RUNNING, SUCCESS, FAILURE), and optionally uid, timestamp and datetime.

Nav2 users get this for free: when nav2_msgs is installed, xparo_ros subscribes to Nav2’s /behavior_tree_log and forwards every event the same way.

Teleop drives /joy

When someone uses Teleop on the Robots Fleet page, xparo_ros publishes the gamepad or keyboard input as sensor_msgs/Joy on /joy, with at least 4 axes and 3 buttons. Point your motor controller (for example teleop_twist_joy) at /joy and the dashboard drives the robot.

ros2 topic echo /joy

Health: /diagnostics and /rosout

The dashboard’s Health & Errors view is built from two standard topics:

  • every diagnostic_msgs/DiagnosticArray published on /diagnostics by any node (warnings and errors become problems on the dashboard), and

  • every ERROR or FATAL line logged by any node (/rosout).

So the usual ROS 2 ways of reporting health just work. xparo_ros also publishes its own status on /diagnostics once per second:

Status name

Meaning

xparo: dashboard connection

connected, or an error while it retries.

xparo: rosbag recorder

Recording state, no recorder running (recording off), or an error if record_bags:=true but the recorder disappeared.

xparo: task engine

idle, the running tasks, or a warning when the last task failed.

xparo: disk usage

Warning from 85 % full, error from 95 %.

ros2 topic echo --once /diagnostics

ROS bag recording

ros2 topic pub --once /ros2_bag_control std_msgs/msg/String "data: 'start'"
ros2 topic pub --once /ros2_bag_control std_msgs/msg/String "data: 'stop'"
ros2 topic pub --once /ros2_bag_control std_msgs/msg/String "data: 'status'"
ros2 topic echo /ros2_bag_control/recording_status

See ROS bag recording for how recording works.