Contracts for a bringup with no launch file
Needs first: Project layout · the contract walkthrough
Write a contract for a bringup that has no launch/ directory when you want
its image sized from what it creates, or its QoS declared, without adding a
launch file.
A bringup with no launch/ runs the nodes its system.toml lists in
[[component]] rows, and the build generates its launch file from those rows.
A contract normally sits beside the launch file it describes, but a generated
launch file lives under build/, where you cannot author anything. So you
write the contract beside system.toml instead, as system.contract.yaml, and
the build carries it to the generated launch file.
Before you start
- A bringup with
system.toml, at least one[[component]]row, and nolaunch/directory, that builds. If the bringup has alaunch/directory, this page does not apply: writelaunch/<stem>.contract.yamlbeside the launch file instead. - The name each node registers its endpoints on, written as an absolute name at the call site.
Steps
- Find each node’s name. In the generated launch file, a node’s name is
its
[[component]]row’sname, so that is the key you use undernodes:.
[[component]]
pkg = "native_listener"
class = "native_rs_listener::Listener"
name = "listener"
[[component]]
pkg = "native_c_listener"
class = "native_c_listener::Listener"
name = "listener"
[[component]]
pkg = "cpp_listener"
class = "cpp_listener::Listener"
name = "listener"
-
Write
system.contract.yamlbesidesystem.toml. Keynodes:by thenamefrom step 1 and each endpoint by its local name; wire it undertopics:to the absolute name the code registers:version: 1 nodes: listener: sub: chatter: qos: history: keep_last depth: 1 topics: /chatter: type: std_msgs/msg/String sub: [listener/chatter]For a C or C++ node, state the depth its call site passes: a C or C++ registration whose depth differs from the contract’s is refused (Declare QoS in a contract).
-
Build the image.
nros build linuxThe build generates the launch file and copies your contract beside it. In a workspace, both are under
build/nros/launch/<bringup>/launch/:ls build/nros/launch/<bringup>/launch/system.contract.yaml system.launch.xmlFor a single package that holds its own
system.toml, the directory is<package>/build/nros/launch/<package>/. The copy is rewritten only when your file changes, and deleted when you delete yours. -
Check the resolve line. It reports the counts the contract produced:
nros build: resolved → <workspace>/build/<bringup>__linux/resolved.toml (max_cbs <n>, nodes <n>, digest <digest>)(entity counts not derived; configured defaults kept)means some component is not described: see Fix a contract refusal.
Example
examples/linux/rust/listener
is a single-package Rust listener with no launch/. Its system.toml holds
the [[component]] row from the Rust tab above and an [image.linux], and
its system.contract.yaml is the file from step 2. The code registers the
subscription on /chatter, the absolute name the contract states:
#![allow(unused)]
fn main() {
node.create_subscription_for_callback_name::<StringMsg>("on_chatter", "/chatter")?;
}
The contract’s one line of QoS takes the image’s static RAM on Linux from 273,802 to 172,298 bytes, because the zenoh backend then sizes its payload pools for one sample instead of four. The listener still receives every message a 1 Hz talker publishes.
If it doesn’t work
-
The build ignores
system.contract.yaml. The bringup has alaunch/directory, so its own launch files are used and nothing is generated or carried. Move the contract tolaunch/<stem>.contract.yaml, beside the launch file it describes. -
The build warns that the bringup has no
launch/directory and no[[component]]row. The warning reads:nros: warning: <bringup>/system.toml: this bringup has no `launch/` directory and no `[[component]]` row, so nothing says what it runs and no system model is resolved for it. Add a `[[component]]` row (pkg, class, name) to system.toml, or add `launch/system.launch.xml`.With no row, there is no launch file to carry the contract to. Add the row.
-
A node’s endpoints are refused, or never matched. The
nodes:key is not the row’sname, or the code registers a relative name. Use the row’sname, and an absolute name at the call site. See Fix a contract refusal for the messages.
See also
- Size an image from its contract: what the counts size, and how to measure the result.
- Declare QoS in a contract.
- Contract format reference: every contract key, generated from the grammar this release pins.