Adapting Nodes¶
Node Requirements¶
Ensure the node meets the required execution behavior:
All execution must happen in ROS callbacks. Those can be subscription-, timer- and service-callbacks. Execution not inside ROS callbacks might include things such as a separate main-loop possibly in a separate thread, this is not allowed as it can not be controlled by the executor. It is permissible to perform processing in a separate thread, if that processing is only ever triggered by a ROS callback, and as such could be modeled or implemented as a single ROS callback.
Observable node behavior must be deterministic. Specifically, the sequence of (ROS-)outputs (outgoing service calls and published messages) must remain exactly the same if the same sequence of inputs is applied again. This implicitly forbids reading data from sensors or devices which may change at any point. Stochastic processes depending on randomness might be used if the pseudo-RNG is deterministically seeded.
Inputs and outputs must be causally related, in a way that is describeable by the config file, see below. Callbacks may omit one or multiple outputs in some invocations, see the status message.
Status Outputs¶
If a callback does not produce an output, it must inform the orchestrator of callback completion by publishing a Status message.
1string node_name
2string[] omitted_outputs
3int32 debug_id
Omitted Outputs¶
Status messages may list omitted_outputs
.
This is a list of topic outputs which would usually occur during the current callback, but will not occur in this specific callback invocation.
It must contain remapped topic names, not internal names.
The actual topic name is available from ROS publishers in rclcpp
(rclcpp::PublisherBase::get_topic_name
) and rclpy
(rclpy.publisher.Publisher.topic_name
):
status_msg.omitted_outputs
.push_back(this->publisher->get_topic_name());
status_msg.omitted_outputs = [self.publisher.topic_name]
JSON Node Behavior Description¶
Node behavior needs to be described statically in a JSON configuration file. The file must adhere to the following schema (which is available at node_config_schema.json for IDE integration): Examples of node configs are given below.
Node Configuration¶
Behavior specification of a ROS node
node_config_schema |
|||
type |
object |
||
properties |
|||
|
type |
string |
|
|
type |
number |
|
|
List of callback specifications |
||
type |
array |
||
items |
|||
|
type |
array |
|
items |
type |
string |
|
uniqueItems |
True |
||
additionalProperties |
False |
Callback specification¶
type |
object |
||
properties |
|||
|
type |
string |
|
|
oneOf |
Internal input topic name |
|
type |
string |
||
|
type |
array |
|
items |
type |
string |
|
|
type |
array |
|
items |
Service name |
||
type |
string |
||
|
type |
boolean |
|
|
type |
boolean |
|
additionalProperties |
False |
Internal input topic name¶
type |
object |
|
properties |
||
|
type |
string |
const |
topic |
|
|
type |
string |
additionalProperties |
False |
Timer¶
type |
object |
|
properties |
||
|
type |
string |
const |
timer |
|
|
Timer period in nanoseconds |
|
type |
integer |
|
exclusiveMinimum |
0 |
|
additionalProperties |
False |
ApproximateTimeSynchronizer¶
type |
object |
||
properties |
|||
|
type |
string |
|
const |
approximate_time_sync |
||
|
type |
array |
|
items |
type |
string |
|
minItems |
2 |
||
uniqueItems |
True |
||
|
type |
number |
|
|
type |
integer |
|
additionalProperties |
False |
Node Config Example¶
A node config might then look like this:
1{
2 "name": "detector",
3 "callbacks": [
4 {
5 "name": "Input processing callback",
6 "trigger": "input",
7 "outputs": [
8 "output"
9 ]
10 }
11 ]
12}
1{
2 "name": "planning",
3 "callbacks": [
4 {
5 "name": "Planning timer callback",
6 "trigger": {
7 "type": "timer",
8 "period": 300000000
9 },
10 "outputs": [
11 "output"
12 ],
13 "service_calls": [
14 "egomotion"
15 ]
16 }
17 ]
18}