Command Messages
Command messages tell your robot what to do — set a mode, drive to a point, run a mission, apply a setting, push a zone, or stream teleop input. They flow from the Rover Nexus cloud → the on-robot agent → your robot software. Your robot software subscribes to the agent, not to the cloud directly.
- Direction: Downlink (cloud → robot)
- Topic: subscribe on the local Zenoh session to
command(orcommand/**if per-type subtopics are enabled) — see Receiving - Encoding: Cap'n Proto over Zenoh
- Envelope: every command is a single
InternalCommandunion
Local keys have no robot id. Your robot software subscribes to an un-scoped local key — the agent has already stripped the cloud routing (and the
NexusCommandwrapper) and delivers the bare command on the local session.
This page documents every InternalCommand variant. Shared building blocks
(geometry, Value, spatial features, enums) live in
Common Types.
How commands reach your robot
A command originates at the fleet manager. On the server → agent hop it is
wrapped in a NexusCommand that carries a
per-command UUID. The agent acknowledges the UUID (see
RobotAck), persists assets it needs
(missions, features, objects, settings), and forwards the inner
InternalCommand unchanged to your robot software. The NexusCommand wrapper
is never forwarded — your software only ever sees a bare InternalCommand.
Scheduled missions are held by the agent and fired when due.
The InternalCommand envelope
InternalCommand is a tagged union — each command is exactly one variant. Time
fields are Int64 Unix milliseconds.
struct InternalCommand {
union {
setMode @0 :RobotMode; # set operating mode: auto, teleop, etc.
goTo @1 :GoToCmd; # go to a location
velocityCmd @2 :VelocityCmd; # set the raw trajectory of the robot
stop @3 :Void; # pause; stop activity and pause the current mission
resume @4 :Void; # opposite of stop; resume current activity/mission
invokeService @5 :InvokeServiceCmd; # call a capability the robot provides
setMissionRunStatus @6 :SetMissionRunStatusCmd; # set a mission's run status
missionCommand @7 :MissionCommand; # full mission: path, target, capabilities, settings
feature @8 :FeatureOp; # inform the robot of a feature in the world
object @9 :ObjectOp; # inform the robot of an object in the world
settingUpdate @10 :List(SettingUpdate); # set robot settings
deleteMission @11 :DeleteMissionCmd; # delete a mission from the robot
spatialDirective @12 :SpatialDirectiveOp; # inform the robot of a field rule
teleopJoy @13 :TeleopJoy; # joystick command for teleop
}
}
| Variant | Payload | Purpose |
|---|---|---|
setMode |
RobotMode |
Set the operating mode (auto / teleop / …). |
goTo |
GoToCmd |
Navigate to a target pose. |
velocityCmd |
VelocityCmd |
Direct linear/angular velocity. |
stop |
(void) | Pause activity and the current mission. |
resume |
(void) | Resume the paused activity/mission. |
invokeService |
InvokeServiceCmd |
Invoke an advertised capability. |
missionCommand |
MissionCommand |
Run a complete mission. |
setMissionRunStatus |
SetMissionRunStatusCmd |
Pause/resume/stop a specific run. |
deleteMission |
DeleteMissionCmd |
Remove a mission from the robot. |
settingUpdate |
List(SettingUpdate) |
Apply one or more settings. |
feature |
FeatureOp |
Upsert/delete a bare spatial feature. |
spatialDirective |
SpatialDirectiveOp |
Upsert/delete a zone with rules. |
object |
ObjectOp |
Upsert/delete a tracked object. |
teleopJoy |
TeleopJoy |
Teleop joystick state. |
No remote e-stop. There is intentionally no remote-EStop command. Emergency stop is a physical safety function and must not be triggered over the wire. Use
stopfor a remote pause/halt. Robots still report their physical e-stop state viastatusTelemetry.estop.
Motion and mode
setMode — change operating mode
Set the robot to an operating mode. The payload is a
RobotMode enum.
setMode @0 :RobotMode; # manual | auto | teleop | idle
goTo — navigate to a target
Command the robot to drive to a single target pose.
struct GoToCmd {
target @0 :Pose; # lat/lon/alt/heading — see Common Types
}
velocityCmd — direct velocity
Set the raw trajectory of the robot. Typically used for low-level/closed-loop control where the cloud (or an API client) drives velocity directly.
struct VelocityCmd {
linearMps @0 :Float32; # meters / second
angularRps @1 :Float32; # radians / second
}
stop / resume — pause and resume
Unit (void) variants. stop halts robot activity and pauses the current
mission; resume is its opposite — it resumes the current activity or mission.
These are a remote pause/halt, not an emergency stop.
stop @3 :Void;
resume @4 :Void;
Services and settings
invokeService — call a capability
Invoke a capability the robot advertised in
uiCapabilities.
For a trigger capability, leave setting unset; for a setBool capability,
setting is the desired on/off state.
struct InvokeServiceCmd {
serviceName @0 :Text;
setting @1 :Bool;
hasSetting @2 :Bool;
}
The robot may report the resulting state change via the capability's associated
stateKey in telemetryExtras
or as an eventTelemetry.
settingUpdate — change settings
Set one or more robot settings. Each entry must be a setting the robot declared
in uiCapabilities
or its config. This is always a patch and is applied in order (not idempotent).
settingUpdate @10 :List(SettingUpdate);
Each SettingUpdate is a key plus a
typed Value. Confirm the applied values
by watching currentSettings.
Missions
missionCommand — deploy a mission
A complete mission order from the fleet manager: one asset, one-time use. It may carry mission parameters (settings applied at the start), capabilities to fire or enable, and at most one spatial feature (a path, waypoints, or coverage area).
struct MissionCommand {
missionId @0 :Text; # mission template UUID, from the fleet manager
runId @1 :Text; # run id, from the scheduler on the robot agent
name @2 :Text; # display name
userId @3 :Text; # who deployed the mission
detail @4 :Text; # description for the user's benefit
scheduledStartMs @5 :Int64; # epoch ms
expectedEndTimeMs @6 :Int64; # epoch ms; can be a deadline
hasExpectedEndTimeMs @7 :Bool;
missionParameters @8 :List(SettingUpdate); # settings applied at the start of this step
capabilities @9 :List(MissionCapability); # features/services this mission uses or calls
feature @10 :SpatialFeature; # path to follow, waypoints, or coverage area
hasFeature @11 :Bool;
}
# A capability to fire or enable during a mission step, with timing.
struct MissionCapability {
name @0 :Text;
timing @1 :CapabilityTiming;
value @2 :Bool;
}
| Field | Type | Notes |
|---|---|---|
missionId |
Text |
Mission template UUID. |
runId |
Text |
Run id assigned by the agent scheduler. Echo this back in missionRunStatus. |
scheduledStartMs |
Int64 |
Epoch ms. A future time is scheduled by the agent; a past time runs immediately. |
expectedEndTimeMs |
Int64 |
Optional deadline / expected completion. |
missionParameters |
List(SettingUpdate) |
Settings applied at mission start. |
capabilities |
List(MissionCapability) |
What to fire/enable, with CapabilityTiming. |
feature / hasFeature |
SpatialFeature |
Optional route/area for the mission. |
Scheduling behavior:
- A mission with a future
scheduledStartMsis scheduled by the agent and fired when due, with a freshrunId. - A mission with a past start time is forwarded immediately.
- Missions fired too far past their start time may be skipped.
Report progress and the final outcome with
missionRunStatus.
setMissionRunStatus — control a run
Set the status of a specific mission run — e.g. pause, resume, or stop it. This
controls the mission lifecycle, not overall motion (use stop/resume for
motion).
struct SetMissionRunStatusCmd {
missionId @0 :Text;
runId @1 :Text;
status @2 :MissionStatus; # see Common Types
}
deleteMission — remove a mission
Delete a mission from the robot so it can no longer be controlled or referenced (including a scheduled one).
struct DeleteMissionCmd {
missionId @0 :Text;
}
Spatial assets
These three commands push world knowledge to the robot. All use
upsert/delete operation wrappers
with idempotent upserts (re-sending an id overwrites; delete removes by id).
The agent persists these so the robot can recover them offline and via
queryables.
feature — geometry only
FeatureOp carries a bare SpatialFeature
(a Shape or a Route) — pure geometry, no timing or rules. Use
spatialDirective when the payload also
carries timing/parameters/capabilities for a zone.
struct FeatureOp {
union {
upsert @0 :SpatialFeature;
delete @1 :Text; # id to delete
}
}
spatialDirective — zone with rules
SpatialDirectiveOp carries a SpatialDirective:
a persistent zone — a spatial feature plus timing, zone parameters, and
capabilities to apply while in or at the zone. The robot reports whether it is
applying a field rule via
spatialDirectiveStatus.
struct SpatialDirectiveOp {
union {
upsert @0 :SpatialDirective;
delete @1 :Text; # id to delete
}
}
object — push a tracked object
ObjectOp carries a tracked Object (a
person, vehicle, obstacle, …). The cloud can push objects the robot should know
about; the robot can also report objects it detects (see
object uplink).
struct ObjectOp {
union {
upsert @0 :Object;
delete @1 :Text; # id to delete
}
}
Teleoperation
teleopJoy — teleoperation input
Teleoperation joystick state sent from the cloud to the robot. Your robot
software subscribes to the command topic and applies it to motion control.
sessionId is unique per teleop takeover/session.
# Sources: "webrtc-ui", "local-gamepad", "api-client:<id>".
struct TeleopJoy {
sourceId @0 :Text;
sessionId @1 :Text;
axes @2 :List(Float32);
buttons @3 :List(Bool);
timestampMs @4 :Int64;
}
Tip. Treat teleop as a safety-critical, latency-sensitive stream. Apply a watchdog: stop the robot if teleop samples stop arriving. See Teleoperation for the full session flow and video.
NexusCommand and acknowledgements
These types exist only on the server → agent hop and the agent's status reporting back to the server. Your robot software never sees them — they are documented here so integrators understand the command lifecycle and the acks the agent emits on your behalf.
# Server -> agent wrapper carrying a per-command UUID (16 raw bytes on the wire).
struct NexusCommand {
id @0 :Data;
command @1 :InternalCommand;
}
# Lifecycle of a NexusCommand.
enum AckStatus {
sent @0;
agentReceived @1;
agentRejected @2;
robotReceived @3;
robotRejected @4;
robotStateConfirmed @5;
}
# Agent/robot -> server status report for a previously sent NexusCommand.
# commandId echoes NexusCommand.id.
struct RobotAck {
commandId @0 :Data;
status @1 :AckStatus;
reason @2 :Text;
hasReason @3 :Bool;
receivedAtMs @4 :Int64;
}
RobotAck travels on a dedicated agent → server control channel
(AgentTelemetry), alongside the connectivity Heartbeat. These are separate
from the UplinkMsg data plane and are not part of your robot-software contract.
Error handling
When a command arrives, robot software should:
- Validate the command before executing it.
- Report errors via a
faultormessageuplink. - Update
missionRunStatuswhen mission-related commands are processed.
Receiving
Subscribe on the local Zenoh session and deserialize each payload from Cap'n
Proto into an InternalCommand. By default the agent publishes every command to
the single base topic command — subscribe there and branch on the
InternalCommand union discriminant. The local key does not include the robot
id.
Optionally, you can give individual command types their own subtopic so they fan
out onto distinct topics. A command whose subtopic is not configured stays on the
base topic; when a subtopic is configured the command publishes to
{base}/{subtopic} (e.g. base command + velocity → command/velocity), so
subscribe to command/** to receive them all. The configurable keys (in the
robot configuration):
| Config key | InternalCommand variant(s) |
|---|---|
command_topic (base) |
all commands by default |
set_mode_topic |
setMode |
goto_topic |
goTo |
velocity_topic |
velocityCmd |
stop_topic |
stop |
resume_topic |
resume |
service_topic |
invokeService |
mission_topic |
setMissionRunStatus, deleteMission |
mission_command_topic |
missionCommand |
spatial_directive_topic |
spatialDirective |
geometry_topic |
feature |
object_topic |
object |
setting_topic |
settingUpdate |
teleop_joy_topic |
teleopJoy |
- Native: subscribe directly and act on the variant. See Custom Integrations.
- ROS 2: the bridge delivers these commands onto your ROS 2 topics.
Related
- Uplink Messages — robot → cloud
- Common Types — shared structs and enums
- Mission Commands and Teleoperation — task guides
- Capabilities
- Client Libraries — the Cap'n Proto schema for these messages, plus language bindings