.. _isaac_sim_app_tutorial_ros_custom_message: ============================== Custom Message ============================== The python environment in |isaac-sim| comes with a built-in ROS environment based on ROS Noetic that contains rospy. This makes most of the core ROS packages and messages available, as well as publishing/receiving custom messages. Learning Objectives ======================= - Publishing and receiving ROS messages in standalone python scripts. - Using custom ROS message that contains contact sensor information. - Publishing ROS messages in extension scripts. Getting Started ================================ **Prerequisite** This tutorial assumes that you have - Basic understanding of `ROS publisher and subscriber in Python `_. - Experience building `ROS custom messages `_. - Completed the :ref:`isaac_sim_app_install_ros` so that the ``noetic_ws`` has been built and sourced. - Completed :ref:`isaac_sim_app_tutorial_core_hello_world` to understand the two workflows (Standalone and Extension). .. note:: Always make sure ``roscore`` is running, and that ``noetic_ws`` is in your environment's ``$ROS_PACKAGE_PATH`` before running any of the following scripts. .. _isaac_sim_app_tutorial_ros_custom_message_standalone: Publishing A Custom Message in Standalone Python ================================================= We will use data from our contact sensor to demonstrate how to publish a customized ROS message. To start, make a ROS message with the fields corresponding to the contact sensor data fields. The message definition file can be found in ``noetic_ws/src/isaac_tutorials/msg/ContactSensor.msg`` .. code-block:: Header header float64 time float64 value bool in_contact There are modifications that are necessary in the ``CMakeLists.txt`` and ``package.xml`` to enable building custom messages. This is already done for you in the workspace provided. Go to `ROS custom messages `_ for more information on building custom messages in your own workspace. Build and source the workspace with the custom message definition. .. code-block:: bash $ cd noetic_ws $ catkin_make $ source devel/setup.bash $ cd ../ Now the custom message is ready to be used, and you can run the provided contact sensor publisher example .. code-block:: bash $ ./python.sh standalone_examples/api/omni.isaac.ros_bridge/contact.py To exit the sample you can terminate via the terminal with CTRL-C The code provided is putting a cube on the ground and reporting the force experienced on the cube. It is meant to run in headless mode, so no images will be rendered. The contact information will be first printed in the terminal where the ``contact.py`` is running, and the same message is also published to a rostopic named ``/contact_report``. To check the raw published messages, open a new ROS-sourced terminal: .. code-block:: bash $ cd noetic_ws $ source devel/setup.bash $ rostopic echo /contact_report Publishing in Extension Scripting ===================================== If you wish to publish messages in the Extension workflow, you must use ``asyncio`` (or similar modules). It allows the thread running rospy commands to not block the main |isaac-sim| thread. Its necessary when running rospy in an extension or in the script editor. The following script can be executed in the ``Window -> Script Editor`` Window. .. code-block:: python import asyncio import rospy try: rospy.init_node("hello", anonymous=True, disable_signals=True, log_level=rospy.ERROR) except rospy.exceptions.ROSException as e: print("Node has already been initialized, do nothing") async def my_task(): from std_msgs.msg import String pub = rospy.Publisher("/hello_topic", String, queue_size=10) for frame in range(10): pub.publish("hello world " + str(frame)) await asyncio.sleep(1.0) pub.unregister() pub = None asyncio.ensure_future(my_task()) You can monitor the received message in another ROS-sourced terminal. Note that the above code will publish 10 times and stops, so make sure to run the following command **before** running the publishing script. The first message might not print out as it takes time for the `rostopic echo` command to initialize the ROS subscription to the topic .. code-block:: bash $ rostopic echo /hello_topic Publishing Custom Messages in Extension Scripting ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To publish custom messages in extension scripting, you would need to provide the full path to your custom message Python module. The following code snippet is used to import the `ContactSensor` message (from :ref:`isaac_sim_app_tutorial_ros_custom_message_standalone` tutorial). Change ```` to ``python3`` if using ROS Noetic or ``python2.X`` if using ROS Melodic: .. code-block:: python import sys sys.path.append('/devel/lib//dist-packages/isaac_tutorials/msg') from _ContactSensor import ContactSensor contact_msg = ContactSensor() Receiving ROS Messages ============================ We also provide a simple subscriber example where upon receiving an empty ROS message, a cube in the scene teleport to a random location. This one is running with rendering enabled, so you should be able to see the scene and the cube moving. To run this example .. code-block:: bash $ ./python.sh standalone_examples/api/omni.isaac.ros_bridge/subscriber.py To exit the sample you can terminate via the terminal with CTRL-C Once the scene with cube is loaded, you can publish the empty message manually from another terminal. We'll do it at rate of 1Hz. .. code-block:: bash $ rostopic pub -r 1 /move_cube std_msgs/Empty .. raw:: html
Summary ======================= This tutorial covered - Publishing and receiving ROS messages in standalone and extension scripting - Using custom ROS message that contains contact sensor information. Next Steps ^^^^^^^^^^^^^^^^^^^^^^ Continue on to the next tutorial in our ROS Tutorials series, :ref:`isaac_sim_app_tutorial_ros_python` to learn how to run the ROS Bridge in the standalone workflow. Further Reading ^^^^^^^^^^^^^^^^^^^^^^ - See :ref:`isaac_sim_sensors_contact` for additional information about the contact sensor extension