.. index:: pair: page; Connecting with ROS from NRP-Core Experiments .. _doxid-guide_ros_in_nrp_core: Connecting with ROS from NRP-Core Experiments ============================================= The implemented mechanism to interact with ROS from NRP-Core experiments is via :ref:`ROS nodes ` in the :ref:`Computational Graph ` (these nodes are a type of node in the graph, not to be confused with ROS nodes in the ROS architecture). This :ref:`page ` describes how to define Computational Graphs in Python. And this :ref:`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 :ref:`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. .. _doxid-guide_ros_in_nrp_core_1generating_ros_python_bindings: 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) * std_msgs * geometry_msgs * sensor_msgs 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 ``navigation_msgs`` and ``my_ros_package`` in an NRP-Core experiments, NRP-Core should be configured with the command below: .. ref-code-block:: cpp cmake [other options] -DNRP_ROS_MSGS_PACKAGES=navigation_msgs;my_ros_package .. The generated Python bindings can be found under the Pythonmodule ``nrp_core.data.nrp_ros``. E.g. .. ref-code-block:: cpp 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. .. _doxid-guide_ros_in_nrp_core_1ros_python_bindings_differences: 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 ``std_msgs`` package: .. ref-code-block:: cpp # 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 ``UInt64MultiArray_data`` : .. ref-code-block:: cpp import nrp_core.data.nrp_ros.std_msgs as nrp_std a = nrp_std.UInt64MultiArray() :ref:`type `(a.data) # output is This new class behaves similarly to a Python ``list``. It supports ``append`` and ``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 ``index`` or ``sort``. Also attempting to append or extend the object with elements of the wrong type (depending with the array field type) will raise a ``TypeError`` exception. 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.