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
UplinkMsgto a sub-key ofrobot/**on the local Zenoh session (e.g.robot/telemetry/motion) — see Publishing - Encoding: Cap'n Proto over Zenoh
- Envelope: every payload is a single
UplinkMsgunion
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, andtelemetryExtrasare 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.missionRunStatusis 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
StatusTelemetryvia the optionalbattery/fuelfields.
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
runIdfrom the originating mission command. Scheduled missions are fired by the agent with a freshrunId.
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
telemetryExtrasreadings 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.
- Native: publish directly (the wildcard
robot/**is simplest). See Custom Integrations. - ROS 2: the bridge maps your ROS 2 topics onto these messages. See Telemetry Mappings.
Related
- Command Messages — cloud → robot
- Common Types — shared structs and enums
- Zenoh transport
- Telemetry Mappings
- Client Libraries — the Cap'n Proto schema for these messages, plus language bindings