Custom Message
The Python environment in Omniverse 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 ROS and ROS 2 Installation so that the
noetic_ws
has been built and sourced.Completed Hello World to understand the two workflows (Standalone and Extension).
ROS bridge is enabled.
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.
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
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.
$ 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
$ ./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:
$ 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 Omniverse 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.
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
$ 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 Publishing A Custom Message in Standalone Python tutorial).
import sys
sys.path.append('<PATH_TO_noetic_ws>/devel/lib/python3/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
$ ./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.
$ rostopic pub -r 1 /move_cube std_msgs/Empty
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, ROS Bridge in Standalone Workflow to learn how to run the ROS Bridge in the standalone workflow.
Further Reading
See Contact Sensor for additional information about the contact sensor extension