Skip to content

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 (or command/** if per-type subtopics are enabled); see Receiving
  • Encoding: Cap'n Proto over Zenoh
  • Envelope: every command is a single RobotCommand union

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 NexusCommand wrapper) and delivers the bare command on the local session.

This page documents every RobotCommand variant. Shared building blocks (geometry, Value, spatial features, enums) live in Common Types.

Coordinate frames. Geometry-bearing commands (for example navigateTo, updateFeature, object) arrive in WGS84 by default. Set convert_commands_to_local = true in the robot configuration to receive that geometry in your robot's local ENU frame instead. velocityCmd and teleopJoy are body-relative and never converted. See Coordinate Frames.

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 RobotCommand unchanged to your robot software. The NexusCommand wrapper is never forwarded; your software only ever sees a bare RobotCommand.

Scheduled missions are held by the agent and fired when due.

The RobotCommand envelope

RobotCommand is a tagged union, so each command is exactly one variant. Time fields are Int64 Unix milliseconds. (The type was formerly named InternalCommand.)

struct RobotCommand {
  union {
    setRobotMode @0 :RobotMode;  # set operating mode: auto, teleop, etc.
    pause @1 :Void;              # pause robot activity, motion, and the current mission
    resume @2 :Void;            # opposite of pause; resume the current activity or mission
    assignMission @3 :MissionCommand;  # a complete mission: path, target, capabilities, settings
    controlMissionRun @4 :ControlMissionRun;  # pause/resume/cancel/abort a specific run
    invokeService @5 :ServiceCall;  # call a capability the robot provides
    updateSettings @6 :List(SettingUpdate);  # set robot settings
    updateFeature @7 :FeatureOp;  # inform the robot of a feature in the world
    spatialDirective @8 :SpatialDirectiveOp;  # inform the robot of a field rule
    object @9 :ObjectOp;          # inform the robot of an object in the world
    navigateTo @10 :Pose;         # command the robot to go to a location
    velocityCmd @11 :VelTwist;    # set the raw trajectory of the robot (teleop only)
    teleopJoy @12 :TeleopJoy;     # joystick command for teleop
    agentTextRequest @13 :AgentTextRequest;  # text request for an on-robot LLM agent
    sayText @14 :SayTextRequest;  # request the robot say something
    messageConfirmation @15 :MessageConfirmation;  # operator confirmation of a robot message
  }
}
Variant Payload Purpose
setRobotMode RobotMode Set the operating mode (auto / teleop / …).
navigateTo Pose Navigate to a target pose.
velocityCmd VelTwist Direct forward/angular velocity.
pause (void) Pause activity and the current mission.
resume (void) Resume the paused activity/mission.
invokeService ServiceCall Invoke an advertised capability.
assignMission MissionCommand Run a complete mission.
controlMissionRun ControlMissionRun Pause/resume/cancel/abort a specific run.
updateSettings List(SettingUpdate) Apply one or more settings.
updateFeature 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.
agentTextRequest AgentTextRequest Text request for an on-robot LLM agent.
sayText SayTextRequest Ask the robot to speak.
messageConfirmation MessageConfirmation Operator confirm/deny of a robot message.

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 pause for a remote pause/halt. Robots still report their physical e-stop state via statusTelemetry.estop.

Motion and mode

setRobotMode: change operating mode

Set the robot to an operating mode. The payload is a RobotMode enum.

setRobotMode @0 :RobotMode;  # manual | auto | teleop | disabled | maintenance

Command the robot to drive to a single target pose. The payload is a Pose union, so the target can be given in either the WGS84 (geoPose) or local (localPose) frame.

navigateTo @10 :Pose;  # a GeoPose or LocalPose, 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. The payload is a VelTwist.

velocityCmd @11 :VelTwist;  # forwardMps, angularRadps

pause and resume

Unit (void) variants. pause halts robot activity and pauses the current mission; resume is its opposite, resuming the current activity or mission. These are a remote pause/halt, not an emergency stop. A robot cannot opt out of receiving them (see allowedCommands).

pause @1 :Void;
resume @2 :Void;

Services and settings

invokeService: call a capability

Invoke a capability the robot advertised in capabilities. For a trigger capability, leave setting unset; for a setBool capability, setting is the desired on/off state.

struct ServiceCall {
  serviceName @0 :Text;
  setting @1 :Bool;
  hasSetting @2 :Bool;
}

The robot may report the resulting state change via the capability's associated stateKey in sensorTelemetry.

updateSettings: change settings

Set one or more robot settings. Each entry must be a setting the robot declared in capabilities or its config. This is always a patch and is applied in order (not idempotent).

updateSettings @6 :List(SettingUpdate);

Each SettingUpdate is a key plus a typed Value. Confirm the applied values by watching currentSettings.

Missions

assignMission: 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 :Feature;    # 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 Feature Optional route/area for the mission.

Scheduling behavior:

  • A mission with a future scheduledStartMs is scheduled by the agent and fired when due, with a fresh runId.
  • 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.

controlMissionRun: control a run

Apply a control action to a specific mission run: pause, resume, cancel, or abort it. This controls the mission lifecycle, not overall motion (use pause / resume for motion). cancel and abort also remove the mission from the robot.

struct ControlMissionRun {
  missionId @0 :Text;
  runId @1 :Text;
  action @2 :MissionRunAction;
}

enum MissionRunAction {
  pause @0;
  resume @1;
  cancel @2;
  abort @3;
}

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.

updateFeature: geometry only

FeatureOp carries a bare Feature (geometry plus identity and classification): no timing or rules. Use spatialDirective when the payload also carries timing/parameters/capabilities for a zone.

struct FeatureOp {
  union {
    upsert @0 :Feature;
    delete @1 :Text;  # id to delete
  }
}

spatialDirective: zone with rules

SpatialDirectiveOp carries a SpatialDirective: a persistent zone, namely a 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.

Operator interaction

These commands let an operator talk to the robot and respond to its prompts. A robot advertises which it accepts via allowedCommands.

agentTextRequest: text to an on-robot agent

A free-text request from the operator, intended for robots that run an on-robot LLM agent. It communicates intent only; the robot must enforce operational safety and is recommended to sanitize inputs. If responseRequired is set, the robot must reply with a message uplink.

struct AgentTextRequest {
  text @0 :Text;
  intent @1 :AgentTextIntent;
  responseRequired @2 :Bool;
}

enum AgentTextIntent {
  observeAndReport @0;        # retrieve data, then respond
  answerQuestion @1;          # do not take action, simply answer
  operatorInstruction @2;     # operator asks the robot to take action
  troubleshootingRequest @3;  # operator requests troubleshooting / diagnosis
  generalMessage @4;          # anything else from operator to robot
}

sayText: speak text

Ask a speech-capable robot to say something. priority is intent and must be enforced by the robot.

struct SayTextRequest {
  text @0 :Text;
  priority @1 :SpeechPriority;
}

enum SpeechPriority {
  low @0;        # say this at the robot's next convenience
  next @1;       # say this ASAP
  interrupt @2;  # interrupt current speech
}

messageConfirmation

The operator's confirm/deny reply to a robot message that was sent with needsConfirmation. confirmationId echoes the id from that message.

struct MessageConfirmation {
  confirmed @0 :Bool;
  confirmationId @1 :Text;
}

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 :RobotCommand;
}

# 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 RobotUplinkMsg data plane and are not part of your robot-software contract.

Error handling

When a command arrives, robot software should:

  1. Validate the command before executing it.
  2. Report errors via a fault or message uplink.
  3. Update missionRunStatus when mission-related commands are processed.

Receiving

Subscribe on the local Zenoh session and deserialize each payload from Cap'n Proto into a RobotCommand. By default the agent publishes every command to the single base topic command. Subscribe there and branch on the RobotCommand union discriminant. The local key does not include the robot id.

Optionally, individual command types can be given their own subtopic in the robot configuration 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 + velocitycommand/velocity), so subscribe to command/** to receive them all. Any of the command variants above (setRobotMode, navigateTo, velocityCmd, pause, resume, invokeService, assignMission, controlMissionRun, updateSettings, updateFeature, spatialDirective, object, teleopJoy, agentTextRequest, sayText, messageConfirmation) can be split out this way.

  • Native: subscribe directly and act on the variant. See Custom Integrations.
  • ROS 2: the bridge delivers these commands onto your ROS 2 topics.