Callback Graph¶
The CB graph is a networkx multidigraph.
The graph vertices are refered to as “actions”, to distinguish them from ROS nodes.
In networkx, vertices have arbitrary hashable type and mutable attributes.
Here, the hashable type is an increasing, unique, integer ID which is generated by (TODO: function).
Every vertex has exactly one attribute with name “data”, which is of type Action
.
Edges in networkx have no value, but every edge in the CB graph have an attribute to distinguish its type:
Every edge has an attribute “edge_type” of type EdgeType
.
- class orchestrator.orchestrator_lib.action.EdgeType(value)¶
An enumeration.
- CAUSALITY = 0¶
Edge points to the action which produces a required input
- SAME_NODE = 1¶
Edge points to a previous action at the same node
- SAME_TOPIC = 2¶
Points to a previous action receiving a topic published by this action
- SERVICE_GROUP = 3¶
Points to a previous action calling a service provided by this node, or to the provider of a service called by this action
Action Types¶
The following action types are available:
- orchestrator.orchestrator_lib.action.Action¶
alias of
Union
[TimerCallbackAction
,RxAction
,OrchestratorBufferAction
,OrchestratorStatusAction
,DataProviderInputAction
]
The first two are “callback actions”, meaning they represent callbacks executed at nodes within the ROS stack.
- orchestrator.orchestrator_lib.action.CallbackAction¶
alias of
Union
[TimerCallbackAction
,RxAction
]
- class orchestrator.orchestrator_lib.action._BaseAction(state: ActionState, node: str, timestamp: Time)¶
Base class for callback actions.
- node: str¶
- state: ActionState¶
- timestamp: Time¶
- class orchestrator.orchestrator_lib.action.TimerCallbackAction(state: ActionState, node: str, timestamp: Time, cause: TimerInput)¶
Execution of a timer callback at a ROS node.
- cause: TimerInput¶
Description of the causing input
- property period: int¶
Alias for cause.period, provided for compatibility.
- class orchestrator.orchestrator_lib.action.RxAction(state: ActionState, node: str, timestamp: Time, cause: TopicInput, data: Any | None = None, is_approximate_time_synced: bool = False)¶
Execution of a subscription callback at a ROS node.
- cause: TopicInput¶
Description of causing topic input
- data: Any | None = None¶
Cached input ROS message triggering this callback (deserialized)
- is_approximate_time_synced: bool = False¶
Flag indicating that this topic input belongs to an approximate-time-synced message filter. This implies that the filter-callback might not be executed for this input.
- property topic: str¶
Alias for cause.input_topic, provided for compatibility.
The remaining types are actions executed by the orchestrator or data source:
- orchestrator.orchestrator_lib.action.OrchestratorAction¶
alias of
Union
[OrchestratorBufferAction
,OrchestratorStatusAction
,DataProviderInputAction
]
Action state¶
Graph Processing¶
“Processing” refers to iterating over the graph and executing actions if possible.
Actions are able to be executed if their state is Ready
(implying the required input is available/has been buffered) and if they have no outgoing edges (ordering dependencies).
Processing is done exhaustively, meaning that the graph is repeatedly iterated over until no action has been executed within one iteration.
Timer Handling¶
Timers are triggered by messages on /clock
, just as they would be during a simulation run.
This requires all nodes using timers to set the use_sim_time
parameter to True
.
When the data source announces a clock-publish, the corresponding timer callbacks are created in the CB graph.
The actions are set to READY
once the corresponding clock message actually arrives at the orchestrator.
Clock messages are not buffered, since they can be recreated trivially from the known timer execution time.
Clock messages are only forwarded to nodes when they trigger a timer callback.
This implies that using self.get_clock().now()
or similar during callback execution or elsewhere always returns the time of the most recent timer callback.
This is consistent with the model that nodes only execute during callbacks, and that all callbacks complete in zero time.
Unexpected behavior may occur although if non-timer callbacks exist which access the current node time. Usually, clock-messages could be received between the last timer callback and this callback, updating the node time. It would not be wise to rely on assumptions such as that the node time has already advanced to the current simulation time when an input from that simulation timestep is received, since the clock message may not always arrive before the input. If this is a problem, the time handling may need to be changed to forward every clock message (which presents a challenge since the clock-receive callback has no observable feedback from outside the node).