[ROS Q&A] 171 – Python Class for simple ROS Subscriber

[ROS Q&A] 171 – Python Class for simple ROS Subscriber

About:
In the following video we are going to show how to create a simple ROS Subscriber using a Python class.

Original Question: https://answers.ros.org/question/310423/python-class-for-simple-subscriber/

// RELATED LINKS
Robot Ignite Academy
ROS Development Studio (ROSDS)
Original Question


Feedback

Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.

[ROS2 in 5 mins] 006 – What is a ROS2 message?

[ROS2 in 5 mins] 006 – What is a ROS2 message?

Hello ROS developers and enthusiasts!

In this short post, we’ll find out what a ROS2 message is and what ROS2 has provided to work with messages. Keeping up with our usual style, we’ll use a practical-centric approach to learning ROS, with some sort of twist here – a practical/theory sandwich!

Let’s go!

Setup for the practicals

To follow this post, you need access to a ROS2 installation. There are two options for this. I recommend option 1; I used it for this post.

  1. Avoid all headaches related to ROS(2) installation and embrace the future — spin a development environment within a few seconds and with a few clicks on ROSDS. If you select this option, to “open a terminal”, just select the Shell app on the ROSDS Tools menu.
  2. Keep all the headaches related with ROS(2) installation; you have good reasons like supporting the drug companies…kidding 🙂 — use a local ROS2 install or a PC with Docker installed.

Okay, you just made your choice; now, let’s shoot the first command. On a new terminal, spin up the ROS2 docker machine. You can skip this if you have ROS2 installed locally:

user:~$ docker run -it osrf/ros2:nightly
Unable to find image 'osrf/ros2:nightly' locally
nightly: Pulling from osrf/ros2
...
root@9cd3dc8de69a:/#

Good job; now we are ready for some action!

So, what is a ROS2 message? Here’s your sandwich!

Well, you had it coming; here you go!

What does ROS2 have to say about messages?

In your open shell, type this command at the shell:

root@9cd3dc8de69a:/# ros2 msg
usage: ros2 msg [-h] Call `ros2 msg <command> -h` for more detailed usage. ...

Various msg related sub-commands

optional arguments:
  -h, --help            show this help message and exit

Commands:
  list      Output a list of available message types
  package   Output a list of available message types within one package
  packages  Output a list of packages which contain messages
  show      Output the message definition

  Call `ros2 msg <command> -h` for more detailed usage.

That’s about all you get to work with ROS2 messages in the current version.

The makers of ROS2 decided to save you some typing by shortening “message” to “msg”, but you might find yourself typing “ros2 message…” sometimes. Not to worry, it happens, and the shell will faithfully do its job of shocking you back to reality :). But I digress…

Back to the issue on ground: all that output above and not a word about what a ROS2 message is? The shell output is rather assuming, don’t you think? Anyways, time to use some theory. We’ll come back to the shell later on.

A picture speaks a thousand words

So they say. Since the shell couldn’t help us, maybe a picture will. Here is it:

ROS2 messages

Key points about the picture above:

  • Nodes need to communicate with one another.
  • They do so by sending and receiving messages over channels called topics.

These are the basics of ROS(2) messages. We’ll see more in the “tell and show” subsections that follow.

There are different kind of messages

Yes, depending on the goal. For instance, a message to move a robot wheel is different from a message to take a picture with its camera.

Let’s see what the shell has to say about this, using the first command (list) shown in our first shell output:

root@9cd3dc8de69a:/# ros2 msg list
...
geometry_msgs/Twist
...
geometry_msgs/Vector3
...
std_msgs/String
...
root@9cd3dc8de69a:/#

Whew, we have a bucket list there (output truncated)! Those are the message types bundled with ROS2. You can create your own messages, but we won’t talk about that here.

You now know that there are many message type, but there’s one more important thing you should know…

You need to know the structure of messages before you can use them effectively

Yes, that right:

  • Sending nodes need this to compose a valid message.
  • Receiving nodes need this to properly process the message received.

Let’s say we want to send a ‘string’ message “Hello World”. Looking at the list of bundled messages, std_msgs/String looks like a good candidate. How do we compose a message of that type? Here’s where the last command (show) proposed by our first shell output comes in:

root@9cd3dc8de69a:/# ros2 msg show std_msgs/String
string data

So we know from the output above that we need to compose a message object with a single variable data of string type. Now let’s send the message over the wire:

root@9cd3dc8de69a:/# ros2 topic pub /world std_msgs/String "data: Hello World!"
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello World!')

Remember we mentioned that we send messages over channels called topics? Here we’re sending out message over the /world channel. If you want to learn more about working with topics, please see this post.

Take home – make your own sandwich!

So far so good! Having taken the sandwich in the section above, I believe you have come of age and can make some yourself now 🙂  . The following were intentionally left out of this post, try them out:

  • Examine the structure of the geometry_msgs/Twist , geometry_msgs/Vector3 and any other message(s) you wish from the bucket list of message types.
  • Try out the message sub-commands shown in the first shell output: package and packages.

Video version of this post

One man’s meat is another man’s fish. If you prefer to learn about ROS2 messages by watching a short video, we have one for your below. Happy watching!

Feedback

Did you like this post or the video? Whatever the case, please leave us your thoughts in the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know in the comments area and we will do a post or video about it.

Thank you!

[ROS Q&A] 170 – How can I perform some actions after the program ends?

[ROS Q&A] 170 – How can I perform some actions after the program ends?

Learn how to trigger an event in order to execute some action when our ROS program ends. This is an answer to the following question on ROS Answers:  https://answers.ros.org/question/309529/how-can-i-perform-some-actions-after-the-program-ends/.

Related Resources

Step 1: Get your development environment ready

Either of the following will do:

  1. Use the ROS Development Studio (ROSDS), an online platform for developing for ROS within a PC browser. Easy-peasy. I’m using this option for this post
    1. Once you log in, click on the New ROSject button to create a project that will host your code. Then Click on Open ROSject to launch the development/simulation environment.
    2. To open a “terminal” on ROSDSpick the Shell app from the Tools menu.
    3. You can find the IDE app on the Tools menu.
  2. You have ROS installed on a local PC. Okay, skip to Step 2.

Next step!

Step 2: Create a package with the code given in the post

1. If you are working on ROSDS, please create a ROSject first, as indicated in Step 1.

2. Open a terminal and create a package that holds the Python code:

user:~$ cd catkin_ws/src
user:~/catkin_ws/src$ catkin_create_pkg test_shutdown rospy
Created file test_shutdown/CMakeLists.txt
Created file test_shutdown/package.xml
Created folder test_shutdown/src
Successfully created files in /home/user/catkin_ws/src/test_shutdown. Please adjust the values in package.xml.
user:~/catkin_ws/src$ cd test_shutdown/src
user:~/catkin_ws/src/test_shutdown/src$ touch test_shutdown.py
user:~/catkin_ws/src/test_shutdown/src$ chmod +x test_shutdown.py

3. Open test_shutdown.py in the IDE and paste in the following code:

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def talker():

    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

try:
    talker()
except rospy.ROSInterruptException:
    rospy.loginfo("TEST")

4. Compile and run the code: go back to the catkin_ws directory and run the following commands

user:~/catkin_ws$ catkin_make
user:~/catkin_ws$ source devel/setup.bash
user:~/catkin_ws$ rospack profile
user:~/catkin_ws$ rosrun test_shutdown test_shutdown.py

(PS: Please run nohup roscore & to start ROS master in the background if you get an error that says “cannot connect to master”)

5. Stop the program with Ctrl + C:

Nothing happened? Yes, nothing happened like the OP explained. The OP expected that the word “TEST” would be printed, but it wasn’t. Let’s fix that next.

Step 3: Modify the code so that it triggers some actions when our ROS program ends

The key tool here is the rospy.on_shutdown() hook, which takes a function that should be called when ROS gets the shutdown signal.

Replace the code in test_shutdown.py with the following code that creates the shutdown hook function and registers it.

#!/usr/bin/env python

import rospy
from std_msgs.msg import String

def talker():

    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

def my_shutdown_hook():
    rospy.loginfo("It's shutdown time!")

try:
    rospy.on_shutdown(my_shutdown_hook)
    talker()
except rospy.ROSInterruptException:
    rospy.loginfo("TEST")

Now run the program again and then stop it with Ctrl + C:

user:~/catkin_ws$ rosrun test_shutdown test_shutdown.py
[INFO] [1586198566.464600]: hello world 1586198566.46
[INFO] [1586198566.564763]: hello world 1586198566.56
^C[INFO] [1586198568.326002]: It's shutdown time!

And that was it! Of course, the shutdown hook could perform more useful tasks, like stopping the robot for example.

Extra: Video of the post

Here below you have a “sights and sounds” version of this post, just in case you prefer it that way. Enjoy!

Feedback

Did you like this post? Do you have any questions about the explanations? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS or ROS2 topics, please let us know in the comments area and we will do a video or post about it.


Edited by Bayode Aderinola

[ROS2 in 5 mins] 005 – How to work with ros2 topics from the command line

[ROS2 in 5 mins] 005 – How to work with ros2 topics from the command line

Hello ROS2 developers!

In this post, we’ll see how to work (or play) with ROS2 topics from the command line. This is very useful for tinkering with ROS2 topics as wells as writing and debugging mission-critical ROS2 programs.

Let’s go, shall we?

Getting Ready for the Action

This post is 99.99% practical, so you need a functional ROS2 installation to follow along. We will use one of the awesome Docker images of ROS2 provided by the Open Source Robotics Foundation (OSRF), to keep it easy for everyone and make sure we can tinker with ROS2 without committing too much time to installing it (yet). Choose any of the following options:

  1. Spin a free ROS development environment at ROSDS. With this, you skip all installations; just a few clicks and you will have access a ROS-ready computer within your browser. This is the recommended option and the one used for this post. In this option, a “open a terminal” means you should pick the Shell app from the ROSDS Tools menu.
  2. You have docker installed on your local development machine. Please note that a ROS2 installation is not necessary since we’re using a docker image.

Open a terminal on your machine and spin up the ROS2 docker image:

user:~$ docker run -it osrf/ros2:nightly
Unable to find image 'osrf/ros2:nightly' locally
nightly: Pulling from osrf/ros2
...
root@759719bcb5a5:/#

Important: if the image tag specified is not available, please check out the available tags at https://hub.docker.com/r/osrf/ros2/tags.

Now open three other terminals and run the same command above. We’ll need to work with them in parallel. So we should have four terminals now, Terminals 1 – 4.

ROS2 topics – how you can work (or play) with them

Now we are getting down to it; let’s see how we can work or play with ROS2 topics.

See a list of commands available to work with ROS2

First, we want to see the operations we can do on ROS2 topics. Depending on the version of ROS2 in the image you are able to spin, you might see a slightly different output. The version used in this post is ROS2 Crystal, but the one in the video is ROS2 Bouncy. That said, we’ll be looking at basically the same operations regardless of the RO2 version.

To see what commands you can run against ROS2 topics, type in the command shown below.

In Terminal 1:

root@759719bcb5a5:/# ros2 topic
usage: ros2 topic [-h] [--include-hidden-topics]
                  Call `ros2 topic <command> -h` for more detailed usage. ...

Various topic related sub-commands

optional arguments:
  -h, --help            show this help message and exit
  --include-hidden-topics
                        Consider hidden topics as well

Commands:
  delay  Display delay of topic from timestamp in header
  echo   Output messages from a topic
  hz     Print the average publishing rate to screen
  info   Print information about a topic
  list   Output a list of available topics
  pub    Publish a message to a topic

  Call `ros2 topic <command> -h` for more detailed usage.

There you go! Now let’s try some of these commands.

See a list of available topics

Following the output of the command we ran above, let’s get this list of available topics.

In Terminal 1:

root@759719bcb5a5:/# ros2 topic list
/parameter_events
/rosout

ROS2 created the above topics by default; we didn’t create them. But that’ll change in a bit.

⇒ Take home: run the command ros2 topic list -h to see more options for this command, and try out some.

Create a topic and publish to it at the same time

Now we’ll create and publish to a new topic, /barbarians: run the command below.

In Terminal 1:

root@759719bcb5a5:/# ros2 topic pub /barbarians std_msgs/String "data: Hello World!"
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello World!')

publishing #2: std_msgs.msg.String(data='Hello World!')

publishing #3: std_msgs.msg.String(data='Hello World!')

publishing #4: std_msgs.msg.String(data='Hello World!')

Basically, to publish to a topic, you do ros2 topic pub [topic_name] [message_type] [message_in_right_structure]. For our case above:

  • Our desired topic name was /barbarians
  • The message type I wanted to publish is a String, so I just used the inbuilt message type std_msgs/String.You can get a list of inbuilt messages with ros2 msg list.
  • I “composed” the message according to the structure dictated by std_msgs/String.  I got the structure of this message type with:
root@dd56efdf3a28:/# ros2 msg show std_msgs/String
string data

And that’s it!

Also, by publishing to a topic that did not exist before, we got ROS2 to automatically create it. Let’s confirm that.

In Terminal 2:

root@ed2f3e495885:/# ros2 topic list
/barbarians
/parameter_events
/rosout
root@ed2f3e495885:/#

We could also publish to an existing topic, and we’ll see that shortly.

⇒ Take home: run the command ros2 topic pub -h to see more options for this command, and try out some.

View some pertinent info about a topic

Time to see some info about /barbarians

In Terminal 2:

root@dd56efdf3a28:/# ros2 topic info /barbarians
Topic: /barbarians
Publisher count: 1
Subscriber count: 0
root@dd56efdf3a28:/#

So we see that we have 1 node publishing to the topic, and zero nodes subscribed to it. Since it’s a “barbaric” topic, let’s have another node publishing to it:

In Terminal 3:

root@b1cf8a1224ce:/# ros2 topic pub /barbarians std_ms/String "data: Hello Barbs!"
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello Barbs!')

publishing #2: std_msgs.msg.String(data='Hello Barbs!')

publishing #3: std_msgs.msg.String(data='Hello Barbs!')

Now get back to Terminal 2 and re-run ros2 topic info /barbarians:

root@dd56efdf3a28:/# ros2 topic info /barbarians
Topic: /barbarians
Publisher count: 2
Subscriber count: 0
root@dd56efdf3a28:/#

We now have 2 publishers but, still, there are no subscribers. Grossly unfair, let’s change that narrative!

Subscribe to a topic

To ‘subscribe’ means to get the message(s) being published to a topic. Time to do that for /barbarians, so get set for some babbling.

In Terminal 4:

root@dd56efdf3a28:/# ros2 topic echo /barbarians
data: Hello Barbs!

data: Hello World!

data: Hello Barbs!

data: Hello World!

data: Hello Barbs!

data: Hello World!

So we see the two different messages being published to the topic.

Now, back to Terminal 2, let’s spy on the /barbarian topic once more:

root@ba621804eaa6:/# ros2 topic info /barbarians
Topic: /barbarians
Publisher count: 2
Subscriber count: 1

As expected, we now have 1 subscriber.

More commands to play with?

And that was all! Or maybe not.

We have seen how to use four different commands related to ROS2 topics: list, pub, info, echo. You may have seen that we didn’t cover every command listed. What to do with the ones we didn’t cover? Try them out on your own, of course ;).

The video version of this post

I hope you learned something useful from this post. If you prefer to watch the video version of this post, we have you covered. Please find the video below.

Feedback

Did you like this video? Whatever the case, please leave us some feedback in the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know in the comments area and we will do a video or post about it.

Thank you!

Pin It on Pinterest