Skip to content

Robot Configuration

robot.toml is the per-robot configuration the agent reads at startup. It declares the robot's transport, ingest and command topics, command policy, and the UI capabilities (services, sensors, settings, and resource producers) the robot advertises to the fleet manager. This page documents every key the agent parses.

File location and loading

  • Path: {state_dir}/robot.toml, where the state directory defaults to /var/lib/rdyn/robot (override with the RDYN_STATE_DIR environment variable). So the default path is /var/lib/rdyn/robot/robot.toml.
  • Read once at startup. The agent loads the file a single time when it starts. Changes take effect on the next agent restart.
  • Format: TOML. All config access goes through the agent's central loader; do not parse config files elsewhere in your own on-host tooling.
  • Unknown keys are ignored silently, so a typo in a key name is dropped rather than reported.
  • No secrets. robot.toml holds no keys, certificates, CA roots, or tokens; those live in separate files referenced by path from agent.toml.

Every section below is optional. A minimal (even empty) robot.toml is valid: the agent then uses local Zenoh with the robot/** uplink wildcard, the command base topic, all commands allowed, and no advertised UI capabilities.

What lives in agent.toml instead

Some settings that relate to the robot are not part of robot.toml. The agent reads them from agent.toml, and keys for them placed in robot.toml are ignored:

  • The robot's identity (robot_id), written into agent.toml during enrollment.
  • Server and signaling URLs.
  • TLS paths (ca_root, device_cert, key_private) and Zenoh router endpoints.

See the agent Configuration reference for those. The local coordinate origin is also not a robot.toml key: it is delivered as onboard settings from the cloud and persisted by the agent. See Coordinate Frames.

Naming convention. The top-level flags and the keys under [zenoh_topics], [zenoh_command_topics], [local_transport], and [allowed_commands] use snake_case. The capability-array fields under [[services]], [[sensors]], [[settings]], and [[resources]] use camelCase (for example capabilityType, displayHint, geometryType). Enum-valued fields are case-insensitive.

System flags (top-level keys)

These keys sit at the top of the file, outside any section.

Key Default What it controls
use_ros2 true Detection-only flag. The agent always uses the local Zenoh Cap'n Proto path regardless of this value; ROS 2 systems run an external bridge onto the same topics. The value is logged at startup and reserved for future use.
mission_catch_up_window_sec 3600 Mission catch-up window, in seconds. At startup the scheduler deletes any persisted mission whose scheduled end time is older than now - window. Default is one hour.
enforce_spatial_directives true Enables the agent-side field rule evaluator. See below.
convert_commands_to_local false Delivers downlink geometry in your local ENU frame instead of WGS84. See below.
allow_remote_config_read false Lets the fleet server fetch this file over the control plane. See below.
allow_remote_config_write false Lets the fleet server overwrite this file over the control plane. See below.
robot_link (unset) Optional URL to the robot's local user interface or OEM UI. Reported to the fleet server at startup and shown in the fleet UI. See below.

enforce_spatial_directives. When true, the agent compares the robot's WGS84 position against stored polygon field rules and, on zone enter/exit, reports status to the server and applies the zone's settings and services to your robot software. Set it to false to disable only the agent-side evaluator: field rules are still persisted and queryable, and any status your robot software publishes itself is still forwarded. (The key name mirrors the wire identifier; the customer-facing concept is "field rules.") See Field Rules.

convert_commands_to_local. When true and a local origin is configured, the agent converts geometry-bearing commands and query replies from WGS84 into your robot's local ENU frame before delivering them. The default passes WGS84 through unchanged. Inbound telemetry is always normalized to WGS84 regardless of this flag. See Coordinate Frames.

Remote config access. When enabled, the fleet server can remotely read (allow_remote_config_read) and/or overwrite (allow_remote_config_write) this file over the control plane. Both default to false, so remote access is strictly opt-in. A remote overwrite replaces the whole file and takes effect on the next agent restart. Because robot.toml holds no secrets, exposing it is low-risk, but it is still the operator's explicit choice.

robot_link. An optional URL pointing at the robot's on-device user interface or OEM UI: a page an operator can open to reach the robot directly. When set, the agent reports it to the fleet server at startup (over the control plane); the server records it against the robot so the fleet UI can link to it. Leave it unset (the default) to report no link. Unlike the flags above, this is a string, not a boolean, and blank/whitespace-only values are treated as unset.

# robot.toml system flags (all shown with their defaults)
use_ros2 = true
# mission_catch_up_window_sec = 3600
# enforce_spatial_directives = true
# convert_commands_to_local = false
# allow_remote_config_read  = false
# allow_remote_config_write = false
# robot_link = "https://192.168.1.50/ui"   # optional; unset by default

[local_transport]

Selects the transport for the robot-software to agent hop on the same host. Absent (the default) means local Zenoh. kind = "uds" switches to a Unix domain socket carrying the same Cap'n Proto payloads.

[local_transport]
kind = "uds"                                    # "zenoh" (default) | "uds"
uds_socket_path = "/run/rover-agent/agent.sock" # optional; this is the default

kind = "uds" requires the agent's local-uds build feature (on by default); otherwise the agent logs a warning and falls back to Zenoh. See Unix Domain Socket.

Your robot software (or the ROS 2 bridge) publishes Cap'n Proto ApplicationToAgent messages to these local Zenoh keys, and the agent subscribes to them. The keys carry no robot id; the agent adds identity when it relays to the cloud.

By default the agent subscribes to a single wildcard key, wildcard_topic = "robot/**", which receives every uplink type. While wildcard_topic is set, the per-type keys are ignored. The per-type keys let you name individual subscriptions; their default topic names (all sub-keys of robot/**) are:

Key Default local key Message type
motion_telemetry_topic robot/telemetry/motion GlobalMotionTelemetry, LocalMotionTelemetry
status_telemetry_topic robot/telemetry/status StatusTelemetry
extras_topic robot/telemetry/extras SensorTelemetry
fault_topic robot/fault Fault
mission_topic robot/mission MissionRunStatus
geometry_topic robot/geometry ReportedFeatureUpdate
path_topic robot/path (reserved; routes are server → robot)
object_topic robot/object ObjectOp
system_health_topic robot/health (retired; see below)
usage_telemetry_topic robot/usage UsageTelemetry
consumable_status_topic robot/consumable ConsumableStatus
wildcard_topic robot/** all types (takes precedence when set)

Because the payload is a self-describing union, the key does not select the message type: the agent dispatches on the union discriminant regardless of which of these keys a message arrives on. The per-type keys only let you split publishers.

system_health_topic no longer carries anything. Host health left the robot-software contract: the agent collects and reports it itself. The subscription still exists so an old configuration keeps parsing, but there is no longer an uplink variant to publish there. See Health Monitoring.

[zenoh_topics]
# Option A: one subscription for everything (the default behavior)
wildcard_topic = "robot/**"

# Option B: name topics per message type (omit wildcard_topic to use these)
# motion_telemetry_topic = "robot/telemetry/motion"
# fault_topic            = "robot/fault"

For the full uplink message catalog and publishing conventions, see Uplink Messages and Telemetry Mappings.

The agent publishes each downlink command as a Cap'n Proto AgentToApplication. A command goes to the base command_topic unless a per-command subtopic is set, in which case it goes to {command_topic}/{subtopic}. Every subtopic is optional.

Key Default Command
command_topic command Base topic; every command with no subtopic set.
set_mode_topic (base) SetRobotMode
velocity_topic (base) VelocityCmd
stop_topic (base) Pause
resume_topic (base) Resume
service_topic (base) InvokeAction
mission_topic (base) ControlMissionRun
mission_command_topic (base) AssignMission
spatial_directive_topic (base) SpatialDirective (field rules)
geometry_topic (base) UpdateFeature
path_topic (base) (reserved; no command routes here)
object_topic (base) Object
setting_topic (base) UpdateSettings
teleop_joy_topic (base) TeleopJoy
agent_text_topic (base) AgentTextRequest
say_text_topic (base) SayText
message_confirmation_topic (base) MessageConfirmation

goto_topic is retired. The NavigateTo command was removed, so nothing routes to this key any more. A robot.toml that still sets it parses fine and the key is ignored. Send a destination as a feature with layerRole = target, or as a mission.

[zenoh_command_topics]
command_topic  = "command"   # base (default)
velocity_topic = "velocity"  # VelocityCmd -> "command/velocity"
stop_topic     = "stop"      # Pause       -> "command/stop"
# keys not listed fall through to the base "command" topic

Subscribe to the base command key (or command/** when you split by subtopic) to receive all commands. See Command Messages.

[allowed_commands]

Gates which commands the fleet manager may send to this robot. Every command defaults to allowed, so you list only the ones you want to restrict by setting them to false. Omitting the section (or restricting nothing) leaves every command allowed and sends no AllowedCommands message at startup. Pause and Resume cannot be restricted.

Recognized keys, all defaulting to true:

set_mode, assign_mission, control_mission_run, invoke_service, update_settings, update_feature, spatial_directive, object, velocity_cmd, teleop_joy, agent_text_request, say_text_request, message_confirmation.

Two keys to note. invoke_service keeps its original name here even though the wire field it maps to is now invoke_action, so existing files keep working. go_to was dropped with the NavigateTo command; a file that still sets it parses and the key is ignored.

# A robot that forbids manual teleop and raw velocity commands.
[allowed_commands]
teleop_joy   = false
velocity_cmd = false

UI capabilities

The [[services]], [[sensors]], [[settings]], and [[resources]] arrays describe what the fleet manager UI renders for this robot. They are bundled into a CapabilitiesManifest sent to the server at startup. Each is a TOML array of tables, so repeat the header to add entries. For the concept and how the cloud matches work to robots, see Capabilities.

Robot software can add to this manifest at runtime by publishing runtimeCapabilities; the runtime manifest is layered on top of what this file declares.

[[services]]

The actions the robot advertises. Each entry becomes an ActionDescriptor in the manifest, invokable with invokeAction. The TOML section and field names are unchanged from earlier versions.

Field Required Purpose
name yes Unique identifier passed back in the invoke-action command.
description yes Human-readable description shown in the UI.
capabilityType yes trigger (one-shot button) or setbool (on/off toggle; alias switch).
requiresRole no Minimum role to invoke: viewer, operator, admin, or owner. Default operator.
confirmationMessage no If set, the UI shows a confirmation dialog with this text before invoking.
dangerLevel no normal, warning, or critical. Affects UI styling. Default normal.
stateKey no Links a toggle to a sensor key whose current bool value reflects the action's state.
[[services]]
name = "start_mowing"
description = "Begin autonomous mowing routine"
capabilityType = "trigger"
requiresRole = "operator"
confirmationMessage = "This will start the blades. Proceed?"
dangerLevel = "warning"

[[services]]
name = "lights"
description = "Toggle work lights"
capabilityType = "setbool"
requiresRole = "viewer"
stateKey = "lights_on"

capabilityType = "missiontype" is retired. It declared a mission type rather than an invokable control and has no replacement. An entry that still uses it parses, but the agent drops it from the manifest and logs a warning, so it will not appear in the UI. Remove those entries.

Events are runtime-only. The manifest also carries a list of event names the robot may emit (see event). robot.toml has no key for it yet, so declare event names by publishing a runtime capabilities manifest from your robot software.

[[sensors]]

Read-only values shown in the UI.

Field Required Purpose
key yes Unique identifier; matches the key the robot publishes in telemetry extras.
label yes Human-readable label shown in the UI.
valueType yes Simple type string, int, number, or bool; or an enumerated type { enum = { options = ["A", "B"] } }.
unit no Unit string displayed after the value (for example %, V).
range no [min, max] used for gauge bounds and validation.
displayHint no UI rendering hint: none, onOff, gauge, text, online, warningLight, temperature, or progress. Default none.
[[sensors]]
key = "batteryPct"
label = "Battery"
valueType = "number"
unit = "%"
range = [0.0, 100.0]
displayHint = "gauge"

[[sensors]]
key = "mode"
label = "Mode"
valueType = { enum = { options = ["IDLE", "AUTO", "MANUAL"] } }
displayHint = "text"

[[settings]]

Configurable parameters the operator can edit from the UI. The agent seeds each default into its local settings store the first time it sees the key (insert-if-not-exists), then tracks updates from either the fleet manager or your robot software and persists them across restarts. Settings are queryable locally and remotely (see Zenoh queryables).

Field Required Purpose
key yes Unique identifier used in settings-update messages.
label yes Human-readable label shown in the UI.
default yes Default value, tagged with its type (see below).
range no [min, max] bounds for numeric values.
step no Step increment for numeric sliders in the UI.

The default is a tagged value. Use the form that matches the type:

default = { type = "string", data = "value" }
default = { type = "int",    data = 42 }
default = { type = "number", data = 1.5 }
default = { type = "bool",   data = true }
default = { type = "enum",   data = { value = "MED", options = ["LOW", "MED", "HIGH"] } }
[[settings]]
key = "maxSpeedMps"
label = "Max speed"
default = { type = "number", data = 1.2 }
range = [0.0, 3.0]
step = 0.1

[[settings]]
key = "cutHeight"
label = "Cut height"
default = { type = "enum", data = { value = "MED", options = ["LOW", "MED", "HIGH"] } }

[[resources]]

Feature/resource channels this robot can produce: geographic features of a given type that Rover Nexus can then use in operations and missions (for example detected pallet locations, or mowed-area coverage).

Field Required Purpose
id yes Stable resource-producer id. The robot references this id when reporting features for the channel.
label no Human-readable label shown in the UI. Defaults to id.
description no Human-readable description shown in the UI.
geometryType yes Geometry the producer emits: point, lineString, polygon, multiPoint, multiLineString, or multiPolygon.
layerRole yes Role of the produced features. One of: allowedArea, preferred, keepout, softExclusion, workArea, target, queue, controlZone, triggerZone, coverage, occupied, reserved, consumed, hazard, blocked, plannedPath.

geometryType and layerRole are case-insensitive and ignore separators, so workArea, work_area, and WorkArea are equivalent.

[[resources]]
id = "pallet_locations"
label = "pallet locations"
description = "Location of detected pallets"
geometryType = "point"
layerRole = "target"

[[resources]]
id = "coverage"
label = "Mowed area"
geometryType = "multiPolygon"
layerRole = "coverage"