Client Libraries
You do not have to hand-roll Cap'n Proto serialization or the transport framing. Public client libraries for Rust, Python, and C++ give you the Rover Nexus message types, and two of them add a ready-made client for the agent's Unix domain socket hop. Using one is optional: you can always implement the contract directly in any language.
Two things a library can provide
A library gives you one or both of these:
- Message types and serialization. Typed structs for every
uplink and command
message plus
encode/decodehelpers that produce Cap'n Proto bytes wire-compatible across all three languages. This layer is transport-neutral: the same bytes flow over Zenoh or the Unix domain socket. - A transport client. A small client that opens the connection to the agent, applies the frame protocol, and hands you publish / subscribe / query methods. The ready-made transport clients speak the Unix domain socket hop.
The libraries
| Library | Language | Gives you | Transport |
|---|---|---|---|
rover_nexus_core (source) |
Rust | Message types + serialization | Bring your own (pairs with the zenoh crate for Zenoh) |
rover-nexus-core-py |
Python | Message types + serialization and an AgentClient transport client |
Unix domain socket |
rover-nexus-core-cpp |
C++ | Message types + serialization | Bring your own |
rover-nexus-client-cpp |
C++ | A transport client layered on rover-nexus-core-cpp |
Unix domain socket |
Which one? Pick by language first, then by transport:
- Same-host robot, want the simplest path: use a Unix domain socket client. In Python that is
AgentClient(bundled inrover-nexus-core-py); in C++ that isrover-nexus-client-cpp. Both handle the socket and framing for you.- Zenoh integration: there is no turnkey Zenoh client. Use a core library's message types with a Zenoh session you create yourself, and publish / subscribe / query the Zenoh topic contract. The Rust
rover_nexus_corecrate plus thezenohcrate is the common pairing.- Another language, or full control: generate types from the Cap'n Proto schema and implement the contract directly.
Quick starts
These are illustrative; each repository ships a complete runnable example.
Python (Unix domain socket)
AgentClient connects to the agent's socket, delivers commands to a handler, and
runs the query round-trips. Passing no argument to a query means "all".
from rover_nexus_core import AgentClient, StatusTelemetry, RobotCommand
client = AgentClient.uds("/run/rover-agent/agent.sock") # the default path
@client.on_command
def on_command(cmd: RobotCommand) -> None:
if cmd.pause:
stop_the_robot()
elif cmd.velocity_cmd is not None:
drive(cmd.velocity_cmd.forward_mps, cmd.velocity_cmd.angular_radps)
client.connect()
client.publish_status(StatusTelemetry(unix_time_ms=0, status="ready"))
features = client.get_features() # request/response query; blocks for the reply
client.run_forever() # deliver commands until the agent disconnects
C++ (Unix domain socket)
rover-nexus-client-cpp adds automatic reconnection and non-throwing results on
top of the rn:: message types.
#include <rover_nexus_client/rover_nexus_client.hpp>
namespace client = rover_nexus::client;
client::Options options;
options.socket_path = "/run/rover-agent/agent.sock"; // the default
client::Client agent(options);
agent.on_command([](const rn::RobotCommand& cmd) {
if (std::get_if<rn::PauseCmd>(&cmd)) { /* stop the robot */ }
});
agent.connect(); // (re)connects in the background
rn::StatusTelemetry status;
status.status = "nominal";
agent.publish_status(status); // returns false if the link is down
Rust (Zenoh, bring your own session)
rover_nexus_core provides the types and serializers; you own the Zenoh session
and publish / subscribe / query the topic contract yourself.
use rover_nexus_core::capnp_messages::{
serialize_robot_uplink_msg, deserialize_robot_command,
};
// Publish uplink (robot -> agent): serialize, then put on a robot/** key.
let bytes = serialize_robot_uplink_msg(&uplink_msg)?;
session.put("robot/telemetry/motion", bytes).await?;
// Receive commands (agent -> robot): subscribe to `command`, decode each sample.
let sub = session.declare_subscriber("command").await?;
while let Ok(sample) = sub.recv_async().await {
let cmd = deserialize_robot_command(&sample.payload().to_bytes())?;
// dispatch on the RobotCommand variant
}
Whichever library you use, review Coordinate Frames so you send and interpret geometry in the frame you expect.
Tools and bridges
These public repositories help you integrate and test against Rover Nexus without writing client code from scratch.
| Repository | What it is |
|---|---|
| rover_nexus_ros2_bridge | A ROS 2 (Humble) workspace that bridges the rover-agent local protocol to a ROS 2 graph, translating Cap'n Proto telemetry/commands to ROS 2 topics, services, and actions, with geodesy conversions and Nav2 goal sequencing. Use it to drive a Rover Nexus robot from an existing ROS 2 / Nav2 stack. See ROS 2 Bridge. |
| robot-sim | A Rust robot motion simulator that connects to the rover-agent over the local messaging contract, emulating an outdoor GPS-guided robot (kinematic motion) so you can exercise fleet management, missions, and commands without physical hardware. |
Schema and other resources
If you prefer to generate types in another language, the Cap'n Proto schema
itself lives in the public
rover_nexus_core crate
(GitLab source). This page is
the canonical reference for where the schema and libraries live. More public
Rover Nexus repos and libraries to help with testing and integration are at
gitlab.com/rover-nexus.