Configuring Your Robot
Overview
Configuration can be updated at any time while the robot is connected, including ROS topic names and video parameters. There are two places in the webapp to do this:
- Robot Setup page—available during initial setup
- Edit Robot page—available at any time after setup
Both pages show the same live panel: video settings, the ROS topic names, audio, metrics, pose streaming, and custom commands. Changes take effect on the connected robot immediately. A few settings are not in that panel yet, noted where they appear below.
When the CTRL+R agent is installed, a configuration file is saved locally on the robot at:
/etc/ctrlr_agent/config.jsonThe sections that apply to a robot are:
- Core—These parameters should not be changed. They are essential for identifying the robot.
- Robot—These parameters relate to your robot's video feed.
- ROS Topics—These topics are used by the agent to communicate with your robot's ROS stack.
- Position—Controls whether the robot reports its location, and where that location comes from. Off by default.
- Metrics—Controls whether the agent streams CPU and battery usage to the webapp. On by default.
- Audio—Microphone and speaker settings, covered in Two-way Audio.
The file also carries a Custom Commands section (see Custom Commands) and an RTSP section, which is only used by IP camera devices rather than robots.
Robot Parameters
| Parameter | Default |
|---|---|
| Image Format | Jpeg |
| Resolution | 640×480 |
| Video Source | Ros |
| Image Encoding | BGR |
Image Encoding only applies when Image Format is Raw. If your camera driver publishes rgb8 and the video looks colour-swapped, it needs to be RGB. It is not shown in the webapp panel today, so it is read from the config file on the robot.
ROS Topics
These topics are used by the agent to communicate with your robot's ROS stack. All of them are editable from the live config panel except Velocity 2, which is read from the config file on the robot.
| Parameter | Default | Description |
|---|---|---|
| Camera Rawsensor_msgs/Image | /camera/image_raw | Raw camera frames |
| Camera JPEGsensor_msgs/CompressedImage | /camera/image_raw/compressed | Compressed camera frames |
| Velocitygeometry_msgs/Twist | /cmd_vel | Movement commands published by the agent |
| Velocity 2geometry_msgs/Twist | /cmd_vel_2 | Secondary movement channel, published when the operator uses the right stick |
| Nav Goalgeometry_msgs/PoseStamped | /ctrlr/nav/goal | Autonomous navigation goals |
| Nav Cancelstd_msgs/Empty | /ctrlr/nav/cancel | Cancel active navigation |
| Nav Homestd_msgs/Empty | /ctrlr/nav/home | Send robot home |
| Nav Statusstd_msgs/String | /ctrlr/nav/status | Navigation status published by the robot |
| Posegeometry_msgs/PoseWithCovarianceStamped | /amcl_pose | Robot's live pose, streamed back to the webapp (off by default) |
Pose streaming is disabled by default. Enable it by setting ros.pose_enabled to true. The agent then subscribes to ros.pose_topic and forwards the robot's pose to the webapp, throttled to 5 Hz. The default source is Nav2's /amcl_pose; set ros.pose_msg_type to geometry_msgs/PoseStamped if your robot publishes pose without covariance.
The agent expects exactly three string values from the nav status topic: "started", "completed", or "failed". Anything else is ignored with a warning.
When Your Robot Doesn't Match the Defaults
The defaults above are conventions, not guarantees. Manufacturers name things differently, and a robot you have never connected before will often publish its camera or accept movement on topics of its own. This is normal. Expect to spend a little time on the first robot of a given model, and none on the ones after it.
Work through it in two steps: find out what the robot actually offers, then decide which of the two fixes you need.
Step 1: See what the robot publishes
On the robot, with your ROS environment sourced, list every topic along with its message type:
ros2 topic list -t # ROS 2
rostopic list -v # ROS 1That gives you the real names. To inspect one topic in detail, including its type (message format) and whether anything is actually listening to it:
ros2 topic info /cmd_vel # ROS 2
rostopic info /cmd_vel # ROS 1The two things to look for: the topic the robot publishes camera frames on, and whether the robot subscribes to anything of type geometry_msgs/Twist. A Twist subscriber is the robot telling you it accepts standard movement commands.
Two more commands answer questions the topic list cannot. hz tells you whether a topic is actually publishing or merely advertised, which separates a dead camera from a misconfigured one. echo prints a real message, and some settings can only be found this way:
ros2 topic hz /camera/image_raw # publishing? how fast?
ros2 topic echo /camera/image_raw --once # read one real message
rostopic hz /camera/image_raw # ROS 1
rostopic echo -n1 /camera/image_raw- The camera's encoding field (
rgb8,bgr8and so on) appears in the message but not in the type. That is the value for Image Encoding. - A pose message carries a frame name inside it. Navigation goals only work against the
mapframe, so this is worth checking before wondering why a robot ignores its destination.
If you need to know which program owns a topic, so you can tell the manufacturer's driver apart from the navigation stack:
ros2 node list
ros2 node info /<node_name>
rosnode list # ROS 1
rosnode info /<node_name>Step 2: Pick the fix
If the message types match but the names differ, you are done in about a minute. Type the robot's real topic names into the live config panel on the Robot Setup or Edit Robot page. Nothing is installed on the robot and nothing is written by hand. For example, a robot publishing video to /front_camera/image_raw just needs that value in the Camera Raw field. This covers most robots.
If the robot does not accept Twist at all, remapping will not help, because the problem is the shape of the message rather than its address. This happens with arms, with some car-like robots, and with manufacturers that ship their own motion API. The fix is a small translator node that runs on the robot: it subscribes to the Twist topic the agent publishes to, converts each message into whatever the robot expects, and publishes that. It is usually a short script, and it is the same piece of work whether you write it yourself or we build it as part of onboarding.
Whatever you work out here is saved with the robot, in the webapp and in its config file, so it survives restarts and you never repeat it for that machine. When you add the second robot of the same model, you already know its topic names and reuse the same values, which turns an afternoon of investigation into a few minutes of typing. Fleets get faster to expand as you go, because the unknowns are per model rather than per robot.
Position Reporting
Position reporting is what puts a robot on the map in Eagle Eye and Command HQ. It is off by default, and is not exposed in the webapp config panel yet, so these values come from the config file on the robot. Turn it on with position.enabled, then choose where the position comes from with position.source:
| Source | Where position comes from | Requires |
|---|---|---|
map (default) | Reuses the existing ROS pose subscription, so the robot is placed using its map-frame pose | ros.pose_enabled set to true. ROS 2 only. |
gps | Subscribes to a sensor_msgs/NavSatFix topic, set by position.gps_topic (default /gps/fix) | A GPS receiver publishing NavSatFix. ROS 2 only. |
