[ROS Q&A] 188 – How do you extract multiple variables from a ROS message

[ROS Q&A] 188 – How do you extract multiple variables from a ROS message

Learn how to extract multiple variables from a ROS message, through a very simple example. This video answers the following question found on the ROS Answers forum: https://answers.ros.org/question/322896/how-do-you-extract-multiple-variables-from-a-message/. Let’s go!


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 ROSDS, pick 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: Launch a simulation

We are going to use a topic from a simulation of a robot. You may use any robot that has Odometry (/odom topic). For this post, we are using Turtlebot 2.

On ROSDS, start a Turtlebot 2 simulation from the simulations menu:

  • Simulations -> Use a provided simulation -> (Empty world) + Select a robot -> Turtlebot 2 > Start simulation.

Step 3: Find out the kind and structure of the message the Odometry topic uses

Open a terminal and run the following:

user:~$ rostopic info /odom
Type: nav_msgs/Odometry

Publishers:
 * /gazebo (http://rosdscomputer:37377/)

Subscribers: None


user:~$ rosmsg show nav_msgs/Odometry
std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
string child_frame_id
geometry_msgs/PoseWithCovariance pose
  geometry_msgs/Pose pose
    geometry_msgs/Point position
      float64 x
      float64 y
      float64 z
    geometry_msgs/Quaternion orientation
      float64 x
      float64 y
      float64 z
      float64 w
  float64[36] covariance
geometry_msgs/TwistWithCovariance twist
  geometry_msgs/Twist twist
    geometry_msgs/Vector3 linear
      float64 x
      float64 y
      float64 z
    geometry_msgs/Vector3 angular
      float64 x
      float64 y
      float64 z
  float64[36] covariance
  • First command (rostopic info): we found out the kind of message  – nav_msgs/Odometry.
  • Second command (rosmsg show): we found out the structure of the message.

Next, let’s examine the structure of the ROS message nav_msgs/Odometry:

  • It’s a fairly complex message as it contains a lot of nested variables.
  • The variables are arranged in hierarchical or tree form, with parent variable appearing without indentation. “Parent variables” here include
    • header
    • child_frame_id
    • pose
    • twist.
  • Some of the parent variables have children, grandchildren, and so on, which are also variables. These are indicated by the visual indents. For example,
    • header has three children.
    • pose has two children.
      • pose, which also has children position and orientation, which both have children too.
      • covariance, which has no children.
  • Every variable has a type, indicated just before the variable name. Type for …
    • header is std_msgs/Header.
    • pose -> pose -> position -> x is float64.
    • child_frame_id is string.

Next, let create a Python package and see how to access these variables in code.

Step 4: Create a package and extract these multiple variables from the message std_msgs/Odometry

Create a package and create a Python file. Please note that we are making the Python file executable with chmod +x, otherwise it won’t run!

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

Open the extract_msg_node.py using the IDE and paste in the following code that extracts some of the multiple variables from the ROS message.

#! /usr/bin/env python

import rospy # the ROS api for python. We need it to create a node, 
             # a subscriber and access other ROS-specific program control
from nav_msgs.msg import Odometry # Python message class for Odometry


rospy.init_node("extra_message_node")
msg = rospy.wait_for_message("/odom", Odometry)
print "Full message: \n"
print msg # that's the whole Odometry message. It should be something like
            # what was printed out by `rosmsg show nav_msgs/Odometry`

# print out each of the parent variables
print "\n Parent variables: \n"
print msg.header
print msg.child_frame_id
print msg.pose
print msg.twist

# print some children
print "\nSome children: \n"
print msg.header.frame_id
print msg.pose.pose
print msg.twist.twist

# print out some grandchildren
print "\nSome grandchildren: \n"
print msg.pose.pose.position
print msg.twist.twist.linear

# print out some great grandchildren :)
print "\nSome great grandchildren: \n"
print msg.pose.pose.orientation.w
print msg.twist.twist.angular.z

# print other (great grand) children below this line
print "\nOther ones you have specified: \n"

Run the program:

user:~$ rosrun extract_msg extract_msg_node.py

The program should run once and print out the extracted variables. Try adding your own variables.

And so that was it! I hope you were able to learn a thing or two from this post.

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

[ROS Q&A] 187 – Unable to use data received in callback function

[ROS Q&A] 187 – Unable to use data received in callback function

Learn the proper use of ROS spin for a ROS subscriber so that the data received in the callback function can be accessed.  This is an answer to a question on the ROS Answers forum. Let’s go!


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 ROSDS, pick 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 ROS project containing the C++ code

Create a ROS project in your workspace

user:~$ cd ~/catkin_ws/src
user:~/catkin_ws/src$ catkin_create_pkg callback_fix roscpp
Created file callback_fix/package.xml
Created file callback_fix/CMakeLists.txt
Created folder callback_fix/include/callback_fix
Created folder callback_fix/src
Successfully created files in /home/user/catkin_ws/src/callback_fix. Please adjust the values in package.xml.

Create a C++ file in the project’s src folder and paste in the code specified below.

user:~/catkin_ws/src$ cd callback_fix/src
user:~/catkin_ws/src/callback_fix/src$ touch callback_fix_node.cpp
user:~/catkin_ws/src/callback_fix/src$

We are using a slightly modified version of the code here, using simpler message types since the driving_msg is not available.

#include "ros/ros.h"
#include "std_msgs/Int32.h"
#include <iostream>
using namespace std;

class server {
public:
  int totalobjects;
  void chatterCallback(const std_msgs::Int32 &msg);
};

void server::chatterCallback(const std_msgs::Int32 &msg) {
  totalobjects = msg.data;
}

int main(int argc, char **argv) {
  server objserver;
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub =
      n.subscribe("/ground_truth", 1000, &server::chatterCallback, &objserver);
  ros::spin();
  cout << objserver.totalobjects;
  cout << "\n";
  return 0;
}

On ROSDS, pick the IDE from the Tools menu, locate the callback_code.cpp file and paste in the code.

Step 3: Prepare your C++ code for compilation and compile it

To ensure that our C++ code is runnable, we need to make some modifications to the CMakeLists.txt file. Please edit the following Build section of the file as follows.

We have simply uncommented the add_executable, add_dependencies and target_link_libraries directives.

PS: If your C++ file is named differently, you need to adjust the values accordingly. I have used the default name for the C++ file and its, which is ${PROJECT_NAME}_node.cpp (callback_fix_node.cpp). It’s executable will be generated without the .cpp suffix.

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/callback_fix.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node src/callback_fix_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}_node
   ${catkin_LIBRARIES}
)

Compile the package. Go back to the Terminal and…

user:~/catkin_ws/src/callback_fix/src$ cd ~/catkin_ws/
user:~/catkin_ws$ catkin_make

Step 4: Run your package and experience the elusive output!

user:~/catkin_ws$ rosrun callback_fix callback_fix_node

PS: If you get a message indicating a connection cannot be made to the master, please stop the program, run nohup roscore & to start the master node in the background and then start your program again.


Open another terminal and publish to the ground_truth topic. You should see the published data in the terminal where you started in the callback_fix_node.

user:~$ rostopic pub /ground_truth std_msgs/Int32 "data: 55"
publishing and latching message. Press ctrl-C to terminate

Did something happen? I’d bet it didn’t, whew!

Now stop the callback_fix_node:

user:~/catkin_ws$ rosrun callback_fix callback_fix_node
^C55
user:~/catkin_ws$

Huh, did you see that? The moment we stopped the node, the data we published appeared. That’s baloney, isn’t it? Let’s find out the fix in the next section.

Step 5: Fix the baloney (by implementing a proper use of ROS spin) and run the program again

In the callback_fix_node.cpp file, we can see that the print statements appear right after then ros::spin() statement! The problem is, anything after ros::spin() will not run until the program exits, because ros::spin() creates a loop that won’t exit until the program is interrupted!

In the v2 of the code below, use ros::spinOnce(), instead of ros::spin() to solve the problem:

1. Replace the int main() function with this snippet:

int main(int argc, char **argv) {
  server objserver;
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Rate loop_rate(1);
  ros::Subscriber sub =
      n.subscribe("/ground_truth", 1000, &server::chatterCallback, &objserver);
  while (ros::ok()) {
    ros::spinOnce();
    loop_rate.sleep();
    cout << objserver.totalobjects;
    cout << "\n";
  }
  return 0;
}

2. Compile the workspace again:

user:~/catkin_ws$ catkin_make

3.  Run the callback_fix_node again:

user:~/catkin_ws$ rosrun callback_fix callback_fix_node

4. In the other terminal, publish to the ground_truth topic again and watch the output of the first terminal:

user:~$ rostopic pub /ground_truth std_msgs/Int32 "data: 67"
publishing and latching message. Press ctrl-C to terminate

Now you should see the published data printed in the first terminal, in real-time. Try publishing other integers:

# ...
67
67
999
999
999
#...

And that was it! I hope you have learned something about the proper use of ROS spin. See you in another post!

Extra: Video of this post

We made a video showing how we solved this challenge. If you prefer “sights and sounds” to “black and white”, here you go:

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.

? Subscribe for more free ROS learning


Edited by Bayode Aderinola

[ROS Q&A] 186 – How to store value from a subscribed topic in ROS in Python

[ROS Q&A] 186 – How to store value from a subscribed topic in ROS in Python

About:
In the video of today, we are going to see how you can easily store a value from a subscribed topic into a variable in order to use it later for further purposes. In this case, we will use a global variable to do so.

? Subscribe for more free ROS learning: https://www.youtube.com/channel/UCt6Lag-vv25fTX3e11mVY1Q?sub_confirmation=1

RELATED ROS RESOURCES&LINKS:

ROS Development Studio (ROSDS) —▸ http://rosds.online
Robot Ignite Academy –▸ https://www.robotigniteacademy.com


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 🙂

#ROS #Robot #rostutorials

[ROS Q&A] 185 – 2D Drone Navigation (Part 4 Get Odometry from Laser readings)

About:
In the video of today, we are going to see how you can generate Odometry data from the Drone’s laser readings (using the rf2o_laser_odometry package). Then, we will use this Odometry data in order to perform Navigation.

Get the full code of this video with this ROSject Link –▸ http://www.rosject.io/l/913ce36/

? Subscribe for more free ROS learning: https://www.youtube.com/channel/UCt6Lag-vv25fTX3e11mVY1Q?sub_confirmation=1

RELATED ROS RESOURCES&LINKS:

ROS Development Studio (ROSDS) —▸ http://rosds.online
Robot Ignite Academy –▸ https://www.robotigniteacademy.com
Quadrotor simulation –▸ https://bitbucket.org/theconstructcor…
rf2o_laser_odometry –▸ https://github.com/MAPIRlab/rf2o_laser_odometry


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 🙂

#ROS #Robot #rostutorials

[ROS Q&A] 183 – 2D Drone Navigation with ROS (Part 3 Path Planning)

[ROS Q&A] 183 – 2D Drone Navigation with ROS (Part 3 Path Planning)

About:
In the video of today, we are going to see how to easily navigate your robot autonomously, with Path Planning, in an indoor environment using a drone and the ROS move_base node from the Navigation Stack.

Get the full code of this video with this ROSject Link –▸ http://www.rosject.io/l/8797919/

? Subscribe for more free ROS learning: https://www.youtube.com/channel/UCt6Lag-vv25fTX3e11mVY1Q?sub_confirmation=1

RELATED ROS RESOURCES&LINKS:

ROS Development Studio (ROSDS) —▸ http://rosds.online
Robot Ignite Academy –▸ https://www.robotigniteacademy.com
Quadrotor simulation –▸ https://bitbucket.org/theconstructcor…
depthimage_to_laserscan –▸ http://wiki.ros.org/depthimage_to_las…
Turtlebot Navigation –▸ http://wiki.ros.org/turtlebot_navigation


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 🙂

#ROS #Robot #rostutorials

[ROS Q&A] 182 – 2D Drone Navigation (Part 2 Localization)

[ROS Q&A] 182 – 2D Drone Navigation (Part 2 Localization)

About:
In the video of today, we are going to see how to easily localize your drone in a map of an indoor environment using a drone and the amcl package from the Navigation Stack.

? Subscribe for more free ROS learning: https://www.youtube.com/channel/UCt6Lag-vv25fTX3e11mVY1Q?sub_confirmation=1

RELATED ROS RESOURCES&LINKS:

ROS Development Studio (ROSDS) —▸ http://rosds.online
Robot Ignite Academy –▸ https://www.robotigniteacademy.com
ROSject Link –▸ http://www.rosject.io/l/8797919/
Quadrotor simulation –▸ https://bitbucket.org/theconstructcor…
depthimage_to_laserscan –▸ http://wiki.ros.org/depthimage_to_las…
Turtlebot Navigation –▸ http://wiki.ros.org/turtlebot_navigation


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 🙂

#ROS #Robot #rostutorials

Pin It on Pinterest