Download

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 –

  1. 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.

  2. Click the Create New Document button in the top left corner, as shown above. The following menu displays –

  1. Select the Callback option.

  2. 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 –

  1. The following displays in which you can enter the code for this callback. Enter the callback code in Python.

  1. 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 param1it 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 goaland 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