Skip to content

Uplink Messages

Uplink messages carry everything your robot reports — telemetry, status, faults, mission feedback, detected objects, and capabilities. They flow from your robot software → the on-robot agent → the Rover Nexus cloud. Your robot software never talks to the cloud directly; it publishes to the agent, which holds the secure link and relays the data onward.

  • Direction: Uplink (robot → cloud)
  • Topic: publish a tagged UplinkMsg to a sub-key of robot/** on the local Zenoh session (e.g. robot/telemetry/motion) — see Publishing
  • Encoding: Cap'n Proto over Zenoh
  • Envelope: every payload is a single UplinkMsg union

Local keys have no robot id. The keys you publish to on the local Zenoh session identify only the message, not the robot. The agent adds the robot's identity when it relays your data to the cloud.

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

The UplinkMsg envelope

UplinkMsg is a tagged union — each message you publish is exactly one variant. The agent identifies the variant from the message itself, deserializes it, updates its local robot state, and forwards the data to the cloud (rate-limited per message type).

struct UplinkMsg {
  union {
    missionRunStatus @0 :MissionRunStatus;
    motionTelemetry @1 :MotionTelemetry;
    statusTelemetry @2 :StatusTelemetry;
    telemetryExtras @3 :TelemetryExtras;
    eventTelemetry @4 :EventTelemetry;        # Reliable
    uiCapabilities @5 :UiCapabilities;        # Re-sent by agent if needed
    fault @6 :Fault;                          # Reliable
    shape @7 :ReportedShapeOp;                # Reliable
    object @8 :ObjectOp;
    systemHealth @9 :SystemHealth;
    usageTelemetry @10 :UsageTelemetry;
    consumableStatus @11 :ConsumableStatus;   # Values of a consumable on the robot
    currentSettings @12 :List(SettingUpdate); # Snapshot of current settings. Re-sent.
    message @13 :Message;                      # Reliable; a message to show in the Rover Nexus UI
    agentInfo @14 :AgentInfo;                  # Filled by the agent; robot software does not send
    spatialDirectiveStatus @15 :SpatialDirectiveStatus;  # Reported by the agent by default
  }
}
Variant Payload Who sends it Notes
motionTelemetry MotionTelemetry Robot software High-frequency pose/velocity. Marks the robot online.
statusTelemetry StatusTelemetry Robot software Mode, battery/fuel, e-stop, availability. Marks the robot online.
telemetryExtras TelemetryExtras Robot software Arbitrary OEM key/value readings.
missionRunStatus MissionRunStatus Robot software Progress and outcome of a mission run.
fault Fault Robot software Raise/clear a fault. Reliable.
eventTelemetry EventTelemetry Robot software Discrete state transitions. Reliable.
message Message Robot software Human-readable message for the UI. Reliable.
systemHealth SystemHealth Agent (or robot) CPU/mem/disk/temp/signal. Agent fills this by default.
usageTelemetry UsageTelemetry Robot software Cumulative distance/time/counters.
consumableStatus ConsumableStatus Robot software Tank/consumable level.
shape ReportedShapeOp Robot software Report a covered/hazard area. Reliable.
object ObjectOp Robot software Report a detected object.
uiCapabilities UiCapabilities Agent (or robot) Services/sensors/settings the UI shows. Re-sent if needed.
currentSettings List(SettingUpdate) Robot software Snapshot of current settings. Re-sent.
agentInfo AgentInfo Agent only Agent/OS/version info. Robot software does not send this.
spatialDirectiveStatus SpatialDirectiveStatus Agent (or robot) Whether the robot is inside/applying a field rule.

Rate limiting. motionTelemetry, statusTelemetry, and telemetryExtras are coalesced downstream (the latest value wins) and are not rate-bucketed. The other (channel-driven) variants — including those marked Reliable above — are each guarded by a per-type token bucket: under normal load nothing is delayed, but a sustained flood is dropped (never delayed) and logged at most once per second. missionRunStatus is exempt and is never dropped.

Telemetry

motionTelemetry — pose and velocity

High-frequency motion data. Publishing it bumps the robot's last-seen time on Rover Nexus and marks the robot online.

Recommended publish rate: 1 Hz when idle, max 10 Hz in motion. The agent throttles above 10 Hz and always forwards the latest value.

struct MotionTelemetry {
  unixTimeMs @0 :Int64;
  pose @1 :Pose;
  hasPose @2 :Bool;
  velocity @3 :VelTwist;
  hasVelocity @4 :Bool;
  gpsFixType @5 :GpsFixType;  # optional: include for map accuracy/confidence
  hasGpsFixType @6 :Bool;
  gpsSource @7 :GpsSource;
}
Field Type Notes
unixTimeMs Int64 Sample time, epoch ms.
pose / hasPose Pose World pose (lat/lon/alt/heading).
velocity / hasVelocity VelTwist Linear (m/s) and angular (rad/s).
gpsFixType / hasGpsFixType GpsFixType Optional fix quality.
gpsSource GpsSource Origin of the fix (real / simulated / estimated).

statusTelemetry — status and health

General status of the robot. Must be published by robot software. Publishing it bumps the last-seen time and marks the robot online.

Recommended publish rate: 1 Hz.

struct StatusTelemetry {
  unixTimeMs @0 :Int64;
  battery @1 :BatteryStatus;
  hasBattery @2 :Bool;
  mode @3 :RobotMode;
  hasMode @4 :Bool;
  estop @5 :EStop;
  faulted @6 :Bool;
  missionActive @7 :Bool;  # is the robot available to accept missions
  status @8 :Text;         # OEM-defined status string
  fuel @9 :FuelStatus;
  hasFuel @10 :Bool;
  rangeRemaining @11 :Float64;  # meters
  hasRangeRemaining @12 :Bool;
  runtimeRemaining @13 :Float64;  # seconds
  hasRuntimeRemaining @14 :Bool;
}
Field Type Notes
unixTimeMs Int64 Sample time, epoch ms.
battery / hasBattery BatteryStatus Battery state (below).
mode / hasMode RobotMode Current operating mode.
estop EStop Physical e-stop state (always present).
faulted Bool Whether the robot is currently faulted.
missionActive Bool Whether the robot can accept missions. Mission progress is on missionRunStatus.
status Text OEM-defined free-text status string.
fuel / hasFuel FuelStatus Fuel state (below), for combustion platforms.
rangeRemaining / hasRangeRemaining Float64 Estimated remaining range, meters.
runtimeRemaining / hasRuntimeRemaining Float64 Estimated remaining runtime, seconds.

Battery and fuel live here. There is no separate battery or fuel uplink variant. Robots report both on StatusTelemetry via the optional battery / fuel fields.

EStop

The robot's physical e-stop state. There is intentionally no remote e-stop command — see Command Messages. Robots only ever report e-stop state here.

# Signal that the robot has been E-stopped and cannot take commands.
struct EStop {
  unixTimeMs @0 :Int64;
  active @1 :Bool;
  ids @2 :List(Text);   # which e-stop(s) are engaged
}

BatteryStatus

struct BatteryStatus {
  socPct @0 :Float32;  # state of charge, 0 to 100
  voltageV @1 :Float32;
  hasVoltageV @2 :Bool;
  currentA @3 :Float32;
  hasCurrentA @4 :Bool;
  chargeAh @5 :Float32;
  hasChargeAh @6 :Bool;
  capacityAh @7 :Float32;
  hasCapacityAh @8 :Bool;
  designCapacityAh @9 :Float32;
  hasDesignCapacityAh @10 :Bool;
  temperature @11 :Float32;  # Celsius
  hasTemperature @12 :Bool;
  powerSupplyStatus @13 :PowerSupplyStatus;
  powerSupplyHealth @14 :PowerSupplyHealth;
  powerSupplyTechnology @15 :PowerSupplyTechnology;
}

socPct is the only required value; all others use the hasX pattern. See the power supply enums for status/health/ technology values.

FuelStatus

struct FuelStatus {
  levelPct @0 :Float32;  # 0 to 100
  volumeRemaining @1 :Float32;
  hasVolumeRemaining @2 :Bool;
  capacity @3 :Float32;  # how big is the tank
  hasCapacity @4 :Bool;
  volumeUnit @5 :Text;   # liters, gallons, ...
  hasVolumeUnit @6 :Bool;
  efficiency @7 :Float32;  # e.g. miles per gallon
  hasEfficiency @8 :Bool;
  efficiencyUnit @9 :Text;
  hasEfficiencyUnit @10 :Bool;
  isRefueling @11 :Bool;
}

telemetryExtras — custom sensor values

Arbitrary scalar/status values published by the robot/OEM that aren't covered by the standard motion/status messages. Each reading is a key, a typed Value, and an optional per-reading timestamp.

# Robot -> UI: frequent, minimal, just the data.
struct SensorReading {
  key @0 :Text;
  value @1 :Value;
  unixTimeMs @2 :Int64;  # per-reading timestamp
  hasUnixTimeMs @3 :Bool;
}

struct TelemetryExtras {
  unixTimeMs @0 :Int64;
  # Example entries:
  #   "deck_rpm" -> 3120
  #   "hydraulic_temp_c" -> 64.2
  #   "camera_front_ok" -> true
  #   "tilt_deg" -> 18.5
  kv @1 :List(SensorReading);
}

Rates & limits: OEMs may push at their chosen rate, but the server enforces rate caps, a per-message size limit (e.g. ≤64 KB), and a max key/value count (e.g. ≤256 items). To make a reading render nicely in the UI, declare it as a sensor in uiCapabilities.

systemHealth

Host metrics for the robot's computer(s). The agent fills and publishes this once every 5 seconds; robot software may optionally publish its own to override the agent (e.g. for a device the agent can't see).

struct SystemHealth {
  unixTimeMs @0 :Int64;
  deviceId @1 :Text;  # if multiple computers/CPUs: "cpu1", "gpu2", ...
  cpuPct @2 :Float32;
  memPct @3 :Float32;
  diskPct @4 :Float32;
  cpuTemp @5 :Float32;        # Celsius
  signalStrength @6 :Float32; # RSSI
  signalQuality @7 :Float32;  # standard wifi link quality
}

usageTelemetry

Cumulative robot usage statistics. The source of truth must be the robot software that talks to the agent.

struct UsageTelemetry {
  unixTimeMs @0 :Int64;
  totalDistanceM @1 :Float64;
  autoDistanceM @2 :Float64;
  manualDistanceM @3 :Float64;
  uptimeTotalS @4 :Float64;
  driveTimeTotalS @5 :Float64;
  autoTimeTotalS @6 :Float64;
  missionCountTotal @7 :UInt32;
  chargeCyclesTotal @8 :UInt32;
  rebootCount @9 :UInt32;
  lastRebootUnixTimeMs @10 :Int64;  # epoch ms
}

consumableStatus

Level/amount of a consumable carried on the robot (herbicide, water, seed, …).

struct ConsumableStatus {
  unixTimeMs @0 :Int64;
  kind @1 :Text;             # "herbicide", "water", "seed"
  tankId @2 :Text;           # "main", "left", "right", ...
  levelPct @3 :Float32;      # 0–100
  amountRemaining @4 :Float32;  # quantity scalar
  unit @5 :Text;             # unit for amountRemaining
  isCritical @6 :Bool;       # precomputed by the robot if it wants
}

Mission feedback

missionRunStatus — mission feedback

Status of a mission as it progresses, sent from robot to server. Send this periodically while a mission runs. The robot software is responsible for reporting the final state of a mission in status.

struct MissionRunStatus {
  unixTimeMs @0 :Int64;
  missionId @1 :Text;
  runId @2 :Text;
  status @3 :MissionStatus;
  statusMessage @4 :Text;
  hasStatusMessage @5 :Bool;
  progressX100 @6 :UInt16;  # (0..=10000) = percent * 100
  hasProgressX100 @7 :Bool;
  currentPathId @8 :Text;
  hasCurrentPathId @9 :Bool;
  currentTarget @10 :Pose;
  hasCurrentTarget @11 :Bool;
  currentStep @12 :UInt32;  # can be waypoints
  hasCurrentStep @13 :Bool;
  totalSteps @14 :UInt32;
  hasTotalSteps @15 :Bool;
  timeStartedMs @16 :Int64;       # when this mission actually started running on the robot
  hasTimeStartedMs @17 :Bool;
  expectedEndTimeMs @18 :Int64;   # robot's best guess of when it'll be done; can move
  hasExpectedEndTimeMs @19 :Bool;
  timeCompletedMs @20 :Int64;     # set at a terminal state (complete / canceled / error)
  hasTimeCompletedMs @21 :Bool;
  name @22 :Text;                 # if the robot makes/renames a mission
  hasName @23 :Bool;
}
Field Type Notes
missionId Text The mission template id from the command.
runId Text The specific run id. Echo the runId from the missionCommand so the cloud can correlate.
status MissionStatus Lifecycle state.
progressX100 UInt16 Progress as percent × 100 (0..=10000).
currentStep / totalSteps UInt32 Step counters (may be waypoints).
currentPathId / currentTarget Text / Pose What the robot is currently following / heading to.
timeStartedMs / expectedEndTimeMs / timeCompletedMs Int64 Start, estimated end, and terminal time (epoch ms).

Tip. Always echo the runId from the originating mission command. Scheduled missions are fired by the agent with a fresh runId.

Faults, events, and messages

fault

A fault report for a robot system fault. Reliable. Robot software must send active = false when the fault clears, otherwise it persists on Rover Nexus.

struct Fault {
  unixTimeMs @0 :Int64;
  faultId @1 :Text;         # stable code, e.g. "BATTERY_UNDERVOLT"
  source @2 :Text;          # node / sensor
  severity @3 :FaultSeverity;
  active @4 :Bool;          # true on raise, false on clear
  category @5 :Text;        # power, comms, nav, safety, ...
  description @6 :Text;     # short human text
  suggestedAction @7 :Text; # optional remediation hint
}

eventTelemetry

A discrete event transition emitted from robot software. Reliable. The payload is an EventKind union of the supported transitions.

struct EventKind {
  union {
    estopEngaged @0 :Void;
    estopReleased @1 :Void;
    modeChanged @2 :ModeChangedEvent;       # { from, to : RobotMode }
    missionStarted @3 :MissionStartedEvent;  # { missionId }
    missionCompleted @4 :MissionCompletedEvent;  # { missionId }
    faultRaised @5 :FaultRaisedEvent;        # { faultCode, description }
    faultCleared @6 :FaultClearedEvent;      # { faultCode }
  }
}

struct EventTelemetry {
  unixTimeMs @0 :Int64;
  kind @1 :EventKind;
}

message

A human-readable message from the robot to display in the Rover Nexus UI. Reliable. This is not log storage — use your own logging infrastructure for logs.

struct Message {
  unixTimeMs @0 :Int64;
  level @1 :MessageLevel;  # info / warn / error
  message @2 :Text;
}

Spatial reports

shape — reported spatial area

For the robot to report a shape / geographic feature to Rover Nexus (e.g. an area it covered, or a hazard it found). Reliable. The payload is a ReportedShapeOp (upsert or delete). If the scope is world or fleet, the shape is forwarded to all robots in the fleet.

# UplinkMsg.shape payload
struct ReportedShapeOp {
  union {
    upsert @0 :ReportedShape;
    delete @1 :Text;  # id to delete
  }
}

See ReportedShape for the geometry. It uses ReportedLayerRole and carries an expireTimeMs.

object — detected object

Report a tracked object to Rover Nexus. The payload is an ObjectOp (upsert or delete). scope determines whether it is forwarded to other robots in the fleet. See Object for the fields.

# UplinkMsg.object payload
struct ObjectOp {
  union {
    upsert @0 :Object;
    delete @1 :Text;  # id to delete
  }
}

Capabilities and settings

uiCapabilities — services, sensors, and settings

Tells Rover Nexus what the robot can do and what settings it has. The agent sends this on startup based on the robot config; robot software may optionally send its own. The agent re-sends it if needed.

  • services become buttons in the UI.
  • sensors describe which telemetryExtras readings exist and how to display them.
  • settings become editable fields (sent together with a "Save Settings" button).
struct UiCapabilities {
  services @0 :List(ServiceCapability);  # become buttons
  sensors @1 :List(SensorCapability);    # available values + how to display them
  settings @2 :List(SettingDescriptor);  # editable settings
}

# Defines what a robot can do; these become buttons and can be tied to
# missions and areas.
struct ServiceCapability {
  name @0 :Text;         # "start_mowing"
  description @1 :Text;  # "Begin autonomous mowing routine"
  capabilityType @2 :CapabilityType;
  confirmationMessage @3 :Text;  # optional custom warning text
  hasConfirmationMessage @4 :Bool;
  stateKey @5 :Text;     # sensor key associated with this control (display together)
  requiresRole @6 :Role; # minimum role, e.g. operator / admin
  dangerLevel @7 :DangerLevel;  # warning/critical require confirmation
}

# Robot -> UI: once on connect or when config changes.
struct SensorCapability {
  key @0 :Text;    # in-code key (unique)
  label @1 :Text;  # UI label
  valueType @2 :ValueType;
  unit @3 :Text;   # empty string if none
  rangeMin @4 :Float64;  # for gauge coloring / display range
  rangeMax @5 :Float64;
  hasRange @6 :Bool;
  displayHint @7 :DisplayHint;
}

# Robot -> UI: what settings exist and their constraints. The default also
# defines the expected type; validate at ingest that it matches valueType.
struct SettingDescriptor {
  key @0 :Text;
  label @1 :Text;
  valueType @2 :ValueType;
  default @3 :Value;
  range @4 :Range;
  hasRange @5 :Bool;
  step @6 :Float64;
  hasStep @7 :Bool;
}

struct Range { min @0 :Float64; max @1 :Float64; }

See the UI display enums for ValueType, CapabilityType, DangerLevel, DisplayHint, and Role.

currentSettings

A snapshot of the robot's current setting values, as a bare list of SettingUpdate. Re-sent by the agent as needed. Use this to confirm the values the robot is actually running after a settingUpdate command.

# UplinkMsg.currentSettings payload
currentSettings @12 :List(SettingUpdate);

Agent and field rule status

agentInfo

Information about the agent itself. The agent fills and sends this — robot software does not. Re-sent if needed.

struct AgentInfo {
  agentVersion @0 :Text;
  softwareVersion @1 :Text;
  hasSoftwareVersion @2 :Bool;
  osInfo @3 :Text;  # "Ubuntu 22.04 aarch64" — debugging
  hasOsInfo @4 :Bool;
  uptimeS @5 :UInt64;  # seconds since boot — detect frequent reboots
  hasUptimeS @6 :Bool;
}

spatialDirectiveStatus

Robot → server feedback reporting whether the robot is inside a SpatialDirective's zone and applying it. Reported by the agent by default; robot software may report its own.

struct SpatialDirectiveStatus {
  directiveId @0 :Text;
  lastEvalTimeMs @1 :Int64;
  active @2 :Bool;          # currently inside + within time window + applicable
  insideZone @3 :Bool;      # robot's local evaluation
  distanceToZoneM @4 :Float32;  # optional local distance estimate
  hasDistanceToZoneM @5 :Bool;
}

Publishing

Serialize each UplinkMsg to Cap'n Proto and publish it on the local Zenoh session. The topic does not determine the message type — the agent inspects the UplinkMsg union discriminant inside the payload. The per-type topics below exist only so you can split publishers by type; in practice most integrators publish every UplinkMsg on the single wildcard topic robot/** and ignore the per-type topics. The local keys do not include the robot id; the agent adds the robot's identity when it relays to the cloud.

Default topics (the per-type keys are optional and configurable in the robot configuration):

Topic UplinkMsg variant(s) carried
robot/** (wildcard) all variants — recommended
robot/telemetry/motion motionTelemetry
robot/telemetry/status statusTelemetry
robot/telemetry/extras telemetryExtras
robot/fault fault
robot/mission missionRunStatus
robot/event eventTelemetry
robot/geometry shape
robot/object object
robot/health systemHealth
robot/usage usageTelemetry
robot/consumable consumableStatus

Variants without a dedicated key (uiCapabilities, currentSettings, message, agentInfo, spatialDirectiveStatus) are published on the wildcard topic.