The robotics surface lives in its own subpath import. You construct one Robotics client per (tenant, robot). Then you open scoped publications and subscriptions. The client holds a single MoQT session and connects lazily on the first call. It reconnects automatically and replays every publication and subscription on reconnect. Your code does nothing on a link flap.

Import

Construct a client

RoboticsOptions

string
required
Relay host or full URL: "relay.clutchcall.dev" or "https://relay.clutchcall.dev". Every namespace derives from it.
string
required
The robot that this client speaks for. The SDK uses it to build robot/<id> (telemetry) and robot/<id>/ctl (commands).
string
Bearer token for the relay session, scoped to (tenant, robotId).
string
Base64 SHA-256 of the relay’s cert, for pinned WebTransport in the browser.
WebTransportFactory
Inject a custom WebTransport factory (Node polyfill / tests).
(e: Error) => void
The SDK calls this when the underlying relay session closes with an error.

Methods

publishTelemetry(spec)

Open a robot → cloud track under robot/<id>. Returns a RoboticsPublication.
string
required
Track name under the telemetry namespace, for example "odom", "battery_state".
string
required
Full ROS 2 message type, for example "nav_msgs/msg/Odometry". The SDK prefixes it on the wire.
QoS
QoS profile (below). Omit for the best-effort default.

publishCommand(spec)

Open a cloud → robot track under robot/<id>/ctl. The spec shape is the same as publishTelemetry. Returns a RoboticsPublication.

subscribeTelemetry(spec, onMessage)

Receive robot → cloud frames from robot/<id>. The callback gets the raw CDR payload and the wire type name. Use the type name to check and route messages.
string
required
Track name to subscribe under the telemetry namespace.
(cdr: Uint8Array, typeName: string) => void
required
The SDK invokes this for each delivered message. cdr is the opaque payload. typeName is the prefix decoded from the wire.

subscribeCommand(spec, onMessage)

Receive cloud → robot frames from robot/<id>/ctl. The shape is the same as subscribeTelemetry. The robot (or the on-robot bridge) makes this call to receive teleop commands.

close()

Close the underlying MoQT session and all publications / subscriptions. The call is idempotent.

Handles

RoboticsPublication

Returned by publishTelemetry / publishCommand.
method
Send one typed message. cdr is the raw CDR (or the bytes that match your typeName). The SDK prepends the type-name prefix and opens a fresh MoQT group per message. priority (TypeScript) overrides the QoS default for this single frame: 0 highest, 255 lowest. The call returns immediately. The MoQT layer handles ordering and reliability.
method
Stop publishing this track.

RoboticsSubscription (TypeScript)

subscribeTelemetry / subscribeCommand resolve when the subscription is attached. In the TypeScript SDK, the resolved handle exposes close() to stop receiving. In Python / Go, the returned subscription object exposes the same method.
Keep the subscription handle alive for as long as you want frames. In garbage-collected languages, the handle owns the delivery callback. If the handle is collected, the engine can call into freed memory. Drop the publication handle (or call close) to stop publishing.

QoS profile

The default profile matches ROS 2’s SensorDataQoS (best-effort, volatile, keep-last). See Details → QoS → lanes for the full capability mapping.

Events & lifecycle

  • Connection state — the client shows the relay session lifecycle (Connecting · Connected · Reconnecting · Closed · Failed). In TypeScript, pass onState via the underlying options. In other SDKs, the connect callback reports state codes. Auto-reconnect with capped backoff re-attaches every track on its own.
  • Late join — a subscriber that joins after a publisher immediately receives the relay’s retained group window (sized by depth, latched by transient_local).
  • ErrorsonError (TypeScript) fires on relay close with a reason string. Individual publish/subscribe calls reject if the session cannot be established.

Wire frame (for non-SDK peers)

If you bridge a non-SDK device, send the same envelope so that SDK subscribers can demux it:
The CDR payload is opaque. The prefix is the only contract. Every SDK encodes and decodes this frame identically.
  • Details — wire model, lanes, transports.
  • Cookbook — short task snippets.
  • Recipes — full worked examples.