fleetlessfleetlessdocs
Reference/fleetless.yaml/Publishers

📡 Publishers

A publisher is a topic clients may send to. This is where the format’s whole safety story lives.

yaml
publishers:
  drive:
    topic: /cmd_vel
    type: geometry_msgs/msg/Twist
    description: Velocity command. If sending stops, the robot stops.
    message:
      linear: { x: "${linear_speed}", y: 0.0, z: 0.0 }
      angular: { x: 0.0, y: 0.0, z: "${angular_speed}" }
    parameters:
      linear_speed: { type: float64, min_value: -0.5, max_value: 0.5 }
      angular_speed: { type: float64, min_value: -0.25, max_value: 0.25 }
    failsafe:
      timeout_ms: 500
      message: ${stop_twist}
    quiet_timeout_ms: 2000
field type bounds absent means
topic ROS graph name absolute, at most 255 characters required
type ROS type name the middle segment is msg, at most 255 characters required
message message template null refused at any depth required
failsafe.timeout_ms integer 1 to 60000 milliseconds required
failsafe.message message template no placeholder, at any depth required
quiet_timeout_ms integer 0 to 600000 milliseconds required
parameters map of names at most 50 per entry the message has no holes
description text 1 to 2000 characters offered as description: null

Everything but parameters and description is required, and three of those required fields are about stopping rather than sending. message is required here because a publisher with nothing to send is not a publisher.

No client ever names a topic. A caller addresses the entry by its slug, so the topics an app can write to are exactly the ones written in this file.

failsafe is required

The deadline and the message sit in one group because the deadline exists only to trigger the message.

  • timeout_ms — how long the bridge waits for the client’s next send before stepping in.
  • message — what the bridge itself sends when that time runs out. For a drive command, a zero twist.

That is the core of it. A client that crashes, loses its connection, or whose operator closes the window does not leave a robot driving. The failsafe message has to be safe in every state, because it is sent precisely when nobody is watching any more.

The deadline runs on the robot, not in the cloud. So it still fires when the link to the cloud is what failed, which is the case it exists for.

The failsafe message may hold no placeholder, inline or through a shared message. There is no caller left to fill one, and the refusal is failsafe_has_parameters.

quiet_timeout_ms answers a different question

It is how long this publisher must stay silent before another user may send to it. Whoever sends holds the publisher implicitly exclusive, with no session and no lock, so this one number is the whole handover policy.

Too short and two operators fight over one robot. Too long and a crashed client blocks it for everyone for minutes. 0 hands the publisher over the moment a send finishes.

A caller who arrives too early is refused with publisher_busy, and the refusal carries the configured quiet_timeout_ms and the milliseconds left to wait.

One type per publisher

type fixes the shape that message and failsafe.message both have to fill. A second message type therefore needs a second publisher, which is also what lets a role grant one and withhold the other.

The parameter constraints are enforced in the cloud before anything reaches the robot, and are described under Messages & Parameters.