Callbacks
MOV.AI Flow™ enables you to define callbacks that are automatically triggered upon a node receiving an input message or when a node outputs a message.
Defining which Callback is Triggered by a Node's Port
You may refer to the I/O Configuration section of Node Templates for a description of how to define which callbacks are triggered by the input and/or output ports of a node.
Creating a Callback
To create a new callback –
-
Launch MOV.AI Flow, as described in Launching MOV.AI Flow or click the Home button to return to the MOV.AI Flow home page.
-
Click the Create New Document button in the top left corner, as shown above. The following menu displays –
-
Select the Callback option.
-
A popup window displays in which you can add a name for this callback and then click the CREATE button. It is typical to assign the callback the name of the node, followed by an underscore and then the name of the port, as shown below –
- The following displays in which you can enter the code for this callback. Enter the callback code in Python.
- Click Ctrl + S to save this callback.
Callback Python Syntax
Callbacks can be added to MOV.AI Flow™ nodes. They are associated with Ports.
If the node subscribes to a given topic, a callback can be called every time a new message arrives at that port.
Periodic Callbacks are also possible by adding a new Port of the type ROS1/Timer
Persistent Variables
If you need to store values into variables (eg. mysolidvar
) in a more persistent manner, use the following syntax:
gd.shared.mysolidvar = ...
This can be useful when receiving messages for later processing at another Callback, or if a callback is called periodically and you need to access an old value.
Reading parameters
If a MOVAI Node has a parameter called param1
it can be accessed by the expression:
gd.params["param1"]
Creating new ROS messages
If you need a new message, the traditional ROS1- Python syntax can be used.
For instance, if a new Twist message (named mymsg
) is needed, you can simply type:
mymsg = Twist()
mymsg.linear.x = 2
mymsg.angular.z = 0.2
Some Python import should be necessary. Therefore, use the right pane, Imports tab to add from geometry_msgs.msg import Twist
Publishing a message
A MOV.AI Node with OPorts of the type ROS1/Publisher (eg. output1
and output2
) can be used to publish messages. The python callback can trigger new messages by calling:
gd.oport['output1'].send(mymsgA)
gd.oport['output2'].send(mymsgB)
Special Ports - IOPort
If a node has an IOPort of the type ROS1/ActionClient, you can access its sub-fields namely inputs feedback
,results
, and status
, as well as the outputs goal
and cancel
by the use of @
character.
For instance, if you have an Action called goal1
, you can trigger a new action
with the following syntax:
gd.oport['goal1@action'].send(mymsgC)
Subscribing a message
A MOV.AI Node with an IPort of the type ROS1/Subscriber and name input1
should have a callback associated where incoming messages can be processed, and saved accordingly.
A common approach is to save the message into a Persistent Variable.
gd.shared.mysolidvar = msg
The topic name of the input is not relevant for the syntax.
TF-Subscribing
If your node is subscribing to a TF message (eg. input tf_sub
), you can use the following syntax to set up a child_frame:
gd.iport['tf_sub'].child_frame = "a_nice _frame"
Transition Out
A MOV.AI Node can be a state in the state machine as long as it has at least two special Ports: one Entry Transition and one Exit Transition.
Assuming its exit port is called exit1
, a MOV.AI Node terminates when the callback reaches the following code:
gd.oport['exit1'].send()
Protected Variables
Some variables have a special meaning, namely:
count
- number of times this callback has been called while the node initiated. It goes back to zero if the node restarts.msg
- the incoming message that triggered the callback
Imports
it is recommended to use Imports menu, available on the right pane, to add new libraries of functions.
If you need to use math functions such as sqrt
, don't forget to add from math import sqrt
Logging / Debug
When the node runs, it can produce important messages that can be used to check the health of your code in runtime.
Use the following syntax to print messages that should be available in the spawner container docker-log:
logger.info('Your code has reached this line! hurray')
logger.debug('Starting the flux capacitor generator')
logger.info(f'Navigation result: {mymessage}')
Check Debugging page for more info
Updated about 2 years ago