Connecting with ROS from NRP-Core Experiments¶
The implemented mechanism to interact with ROS from NRP-Core experiments is via ROS nodes in the Computational Graph (these nodes are a type of node in the graph, not to be confused with ROS nodes in the ROS architecture). This page describes how to define Computational Graphs in Python. And this page contains information on how to configure experiments to use a Computational Graph instead of Transceiver Functions.
Please notice, that in order to connect an NRP-Core experiment with ROS and being able to subscribe and publish to topics from the Computational Graph, the parameter ROSNode must be included in the experiment configuration (more information here).
A complete example experiment using Computational Graph ROS nodes can be found in the folder
examples/event_loop_examples/husky_braitenberg_ros in the nrp-core repository.
Finally, NRP-Core instantiates and stores C++ ROS message objects internally, but the Computational Graph is coded in Python and only those ROS message types for which compatible Python bindings has been generated can be used in experiments.
Below this line there is information on how to generate Python bindings for ROS message definitions so they can be used in NRP-Core experiments and some noticeable differences with the native ROS messages Python API.
Generating Python bindings for ROS messages¶
By default Python bindings are generated for all message types in the next ROS packages:
nrp_ros_msgs (package containing NRP-core ROS message definitions)
In order to generate Python bindings for ROS message types defined in other ROS packages, the names of the latter must be pass to cmake by defining the variable
NRP_ROS_MSGS_PACKAGES. Therefore, in order to generate Python bindings for new ROS messages it is needed to re-configure and build NRP-Core.
As an example, if you would like to use ROS msgs from the ROS packages
my_ros_package in an NRP-Core experiments, NRP-Core should be configured with the command below:
cmake [other options] -DNRP_ROS_MSGS_PACKAGES=navigation_msgs;my_ros_package ..
The generated Python bindings can be found under the Pythonmodule
from nrp_core.data.nrp_ros.navigation_msgs import Path p = Path()
If any of the packages listed in
NRP_ROS_MSGS_PACKAGES does not exist in the ROS environment, there will be a cmake error.
API differences between native Python ROS messages and generated Python bindings¶
The generated binding classes match the original ROS Python API with only one exception. In ROS Python, fields of type
array are stored in objects of type
list while in the case of the Python binding generated by NRP-core a new class is created for each
array field. To illustrate the former, consider the case of
UInt64MultiArray message defined in the
# msg definition in std_msgs package MultiArrayLayout layout # specification of data layout uint64 data # array of data
In ROS Python the field
data is stored in a
list, while in the NRP-core Python wrapper class it is stored in a new Python class of type
import nrp_core.data.nrp_ros.std_msgs as nrp_std a = nrp_std.UInt64MultiArray() type(a.data) # output is <class 'nrp_core.data.nrp_ros.std_msgs.UInt64MultiArray_data'>
This new class behaves similarly to a Python
list. It supports
extend methods for adding new data. Its elements can accessed by index or iterated and
len will return the number of elements. But other methods of
list type are not supported as
sort. Also attempting to append or extend the object with elements of the wrong type (depending with the array field type) will raise a
Another important difference between native Python ROS messages and the NRP-Core Python bindings counterpart is that Python ROS messages allows to initialize the message fields in the object constructor while the NRP-Core Python bindings only have an empty constructor.