FleetlessFleetlessdocs
Concepts/Exposing a Robot

Exposing a Robot

This is the model behind everything else in these docs: a robot’s ROS graph is private by default, and a developer decides what part of it becomes an API.

The five kinds of exposed service

Kind Direction What it is
Datapoint Robot → clients One field of a topic, or a whole topic — never several topics at once (if you need that, publish a custom message on its own topic instead). Per field: unit, range, scaling. Optional retention. Send rate is either “max N Hz” or “only on change.”
Publisher Clients → robot Client apps publish messages onto a topic. Configured with a timeout + failsafe message the bridge publishes itself if clients go quiet, plus a user quiet-timeout (see Disconnect Behaviour).
Service Request/response A ROS service call with validated parameters.
Action A job with a lifecycle A ROS action with feedback, progress, result, and cancel.
Camera Robot → clients ROS image topic, RTSP, MJPEG or V4L2 — see Cameras.

Every exposed service gets a slug: stable, chosen by the developer, decoupled from the ROS name. Rename the underlying topic in the robot’s launch file and no client app notices.

Three built-in datapoints, on every robot

  • bridge_state — online/offline plus latency. Build your app’s offline UI on this rather than inferring connectivity from timeouts.
  • robot_details — developer-maintained static key/value metadata (strings, numbers, arrays or JSON objects) — a model name, a serial number, whatever doesn’t come from ROS.
  • bridge_pressure — the bridge’s own bandwidth-shaping state: what the link measures, what each priority tier sent and dropped, and where the video budget stands. See Link Pressure.

None of the three is configured, and each is granted to a role like any other slug.

Configuration is offline-first

You can configure a robot that has never connected. If the bridge is connected, introspection — a browsable view of the robot’s live ROS graph, with type field trees — becomes a shortcut and a template (“adopt this topic”), not a requirement.

Every configuration change goes through draft → publish, with version history. The bridge only ever applies the published version. A configuration is copyable to another robot — copying carries the configuration and its custom type definitions together; a name collision with a differently-defined type on the target is a shown conflict, never a silent choice.

Parameter validation happens on the cloud

For every action, service or publisher parameter, the developer defines checks: min/max, enum, pattern, required. Validation happens at the cloud layer — an invalid value never reaches the bridge. The bridge does its own structural validation too (it has to construct the ROS message anyway), but the semantic rules — the ones a developer wrote — live in the cloud. Rejections are machine-readable and name the field and the rule that failed.

Custom types are per-robot

The console knows every standard ROS type globally. Custom message, service and action types are scoped to one robot — two robots may define custom_msgs/Speed differently. They’re either hand-defined in the console or auto-detected from a connected bridge’s sourced workspace and offered for adoption.

Assets: URDF and meshes

A robot’s URDF and its meshes live in a separate mechanism — the asset store, covered in its own chapter: URDF & Meshes. Assets are not a service kind; they’re immutable, UUID-addressed files, authenticated the same way as every other API call.