Documenting your node’s interface¶
A node’s NoDL document already states its parameters, topics, services, and actions.
The nodl_docgen extension renders that document into your package’s documentation while the docs are being built,
so the interface page is generated from the same file the rest of the toolchain reads.
Nothing is pasted, so nothing goes stale. If the document changes, the page changes with it. If the document stops loading, the build reports an error at the directive, rather than publishing a page that no longer matches the node.
This page is the authoring walkthrough. For the directive’s full option surface, see the nodl_docgen package page.
1. Depend on the extension¶
nodl_docgen is only needed when documentation is built, which is what doc_depend means:
<doc_depend>nodl_docgen</doc_depend>
2. Enable the extension¶
Add it to extensions in your package’s doc/conf.py:
extensions = [
'myst_parser',
'nodl_docgen',
]
3. Render the document¶
Point the nodl-node directive at the NoDL file:
```{nodl-node} /../nodl/my_node.nodl.yaml
:title: my_node
```
The same directive in a reStructuredText page:
.. nodl-node:: /../nodl/my_node.nodl.yaml
:title: my_node
The argument is a path, resolved like literalinclude resolves one:
relative to the page, or relative to the Sphinx source root when it starts with /.
NoDL files usually live outside doc/, hence the /../nodl/... above,
which climbs out of a doc/ directory at the package root.
Use a path, not a nodl:// reference, for your own package’s documents.
rosdoc2 builds a package’s docs from source with its dependencies installed but not the package itself,
so a package’s own NoDL is not yet in the ament index while its docs are being built.
A nodl://<package>/<name> reference is for documenting a node that comes from a dependency.
:title: is the heading, and is worth setting:
a NoDL document carries no name of its own, because a node’s identity comes from the package that registers it.
A rendered example¶
This site dogfoods the directive. The document below is checked in at nodl/doc/examples/battery_monitor.nodl.yaml:
---
nodl_version: 2
description: |
Watches a battery pack and reports its state of charge.
Publishes a diagnostic warning while the charge is below a configurable threshold,
and offers an action that runs a full calibration cycle.
parameters:
publish_rate_hz:
type: double
default_value: 1.0
description: How often the pack state is published.
validation:
gt: [0.0]
lt_eq: [100.0]
low_charge_fraction:
type: double
default_value: 0.2
description: Charge fraction below which the monitor warns.
validation:
bounds: [0.0, 1.0]
cell_count:
type: int
read_only: true
description: Number of cells in the pack. Fixed by the hardware, and has no sensible default.
validation:
one_of: [[4, 6, 8]]
publishers:
- name: ~/state
type: sensor_msgs/msg/BatteryState
qos: {history: KEEP_LAST, depth: 5, reliability: RELIABLE}
description: Current pack state, published at the configured rate.
- name: /diagnostics
type: diagnostic_msgs/msg/DiagnosticArray
qos: {history: KEEP_LAST, depth: 1, reliability: BEST_EFFORT}
description: A warning entry while the charge is low.
subscriptions:
- name: /power/raw_cells
type: sensor_msgs/msg/BatteryState
qos: {history: KEEP_LAST, depth: 10, reliability: BEST_EFFORT}
description: Per-cell readings from the power board driver.
service_servers:
- name: ~/reset_fuel_gauge
type: std_srvs/srv/Trigger
description: Clears the accumulated charge estimate.
action_servers:
- name: ~/calibrate
type: example_robot_msgs/action/CalibrateBattery
description: Runs a full discharge and charge cycle to recalibrate the gauge.
Rendered by pointing the directive at that file, with :title: battery_monitor:
battery_monitor¶
Watches a battery pack and reports its state of charge.
Publishes a diagnostic warning while the charge is below a configurable threshold, and offers an action that runs a full calibration cycle.
Parameters¶
Name |
Type |
Default |
Read-only |
Description |
|---|---|---|---|---|
publish_rate_hz |
double |
1.0 |
How often the pack state is published.
|
|
low_charge_fraction |
double |
0.2 |
Charge fraction below which the monitor warns.
|
|
cell_count |
int |
yes |
Number of cells in the pack. Fixed by the hardware, and has no sensible default.
|
Publishers¶
Name |
Type |
QoS |
Description |
|---|---|---|---|
~/state |
sensor_msgs/msg/BatteryState |
KEEP_LAST(5), RELIABLE |
Current pack state, published at the configured rate. |
/diagnostics |
diagnostic_msgs/msg/DiagnosticArray |
KEEP_LAST(1), BEST_EFFORT |
A warning entry while the charge is low. |
Subscriptions¶
Name |
Type |
QoS |
Description |
|---|---|---|---|
/power/raw_cells |
sensor_msgs/msg/BatteryState |
KEEP_LAST(10), BEST_EFFORT |
Per-cell readings from the power board driver. |
Service Servers¶
Name |
Type |
Description |
|---|---|---|
~/reset_fuel_gauge |
std_srvs/srv/Trigger |
Clears the accumulated charge estimate. |
Action Servers¶
Name |
Type |
Description |
|---|---|---|
~/calibrate |
example_robot_msgs/action/CalibrateBattery |
Runs a full discharge and charge cycle to recalibrate the gauge. |
Reading the output¶
A few things in that rendering are worth pointing out, because they are decisions rather than a straight field dump:
Each interface category that has entries becomes a subsection with a table, and one that has none is left out entirely.
A column no row fills in is dropped. The service server above declares no QoS profile, so its table has no QoS column, while the topic tables do.
A QoS profile is summarized in one line, naming only what differs from the system default.
A parameter’s validators are read out as constraint sentences, and its default is shown as the YAML literal you would write in a parameter file. An empty default means the parameter has none and has to be set at startup, like
cell_countabove.
Descriptions are rendered as plain text. Write them as prose rather than as markup: they are read by every NoDL consumer, not only by Sphinx.
Next steps¶
NoDL Concepts covers what a NoDL document declares.
NoDL Schema reference is the field-by-field reference for writing one.
The nodl_docgen page documents the directive’s argument forms, options,
includemerging, failure behavior, and the summary core underneath it.