[ROS in 5 mins] 018 – What is a ROS message? Part#1

[ROS in 5 mins] 018 – What is a ROS message? Part#1

In this post, we will see what a ROS message is all about! We’ll see how it relates to ROS nodes and topics.

Let’s go!

Step 1: Create a Project (ROSject) on ROSDS

Head to http://rosds.online and create a project named “ros_message” or whatever you like. Please ensure you select “Ubuntu 16.04 + ROS Kinetic + Gazebo 7” under “Configuration”.

Step 2: Create source files

Pick a Shell from the Tools menu and run the following commands:

user:~$ cd catkin_ws/src
user:~/catkin_ws/src$ touch obiwan.py obiwan_pub.py obiwan_sub.py #create the files
user:~/catkin_ws/src$ chmod +x obiwan.py obiwan_pub.py obiwan_sub.py # make them executable

Pick the IDE from the Tools menu. Locate the folder catkin_ws/src in the IDE’s file navigator, locate the corresponding files and paste the following code into them.

 obiwan.py

#! /usr/bin/env python

import rospy

rospy.init_node("sos_1")
rate = rospy.Rate(2)
while not rospy.is_shutdown():
    print "Help me Obi-Wan Kenobi, you're my only hope"
    rate.sleep()

obiwan_pub.py

#! /usr/bin/env python

import rospy
from std_msgs.msg import String

rospy.init_node("sos_2")
rate = rospy.Rate(2)
help_msg = String()
help_msg.data = "help me Obi-Wan Kenobi, you're my only hope"
pub = rospy.Publisher('/help_msg', String, queue_size = 1)
while not rospy.is_shutdown():
    pub.publish(help_msg)
    rate.sleep()

obiwan_sub.py

#! /usr/bin/env python

import rospy
from std_msgs.msg import String

def callback(msg):
    print "SOS received: '%s'!" %(msg.data)
    
rospy.init_node('help_desk')
sub = rospy.Subscriber('/help_msg', String, callback)
rospy.spin()

Step 3: Execute the files and observe…

First, start the ROS master in the background. Then check the ROS topics currently available:

user:~/catkin_ws/src$ nohup roscore &
user:~/catkin_ws/src$ rostopic list
/rosout
/rosout_agg

 obiwan.py

Run this command in the current terminal. You should see the following output:

ser:~/catkin_ws/src$ ./obiwan.py
Help me Obi-Wan Kenobi, you're my only hope
Help me Obi-Wan Kenobi, you're my only hope
...

Pick another Shell from the Tools menu and run the following command. You should see that no additional topic has been created:

user:~$ rostopic list
/rosout
/rosout_agg

obiwan_pub.py

Stop the obiwan.py program in the first terminal by pressing Ctrl + C. Then run the obiwan_pub.py program:

user:~/catkin_ws/src$ ./obiwan_pub.py

Program is doing nothing? Nah, we shall see shortly. In the second terminal, rerun the last command:

user:~$ rostopic list
/help_msg
/rosout
/rosout_agg

Ah, now we have a new topic: help_msg! But where’s the help message? We’ll see that in the third program.

obiwan_sub.py

In the second terminal, run the obiwan_sub program:

user:~$ cd catkin_ws/src
user:~/catkin_ws/src$ ./obiwan_sub.py
SOS received: 'Help me Obi-Wan Kenobi, you're my only hope'!
SOS received: 'Help me Obi-Wan Kenobi, you're my only hope'!

That’s the message being generated by the obiwan_pub.py program.

Now, let’s put everything together.

Step 4: Master the Concept: What is a ROS message?

The obiwan.py and obiwan_pub.py create similar messages. However, the message created by obiwan.py is NOT a ROS message because:

  1. It didn’t use a recognized ROS message type.
  2. It was not sent over a ROS channel (topic).

obiwan_pub.py publishes a message on the /help_msg topic while obiwan_sub subscribes to that topic and therefore gets the message.

In summary,

  1. ROS nodes communicate with one another through messages.
  2. They communicate over channels called topics.
  3. There are different types of messages for different tasks. For example, a node controlling a drone will tell the drone to take off using a ROS message type Empty over a topic that might be something like /drone/takeoff.
  4. Extra: when you send a message to a robot via the command line, you are a n*** …or at least behaving like one 🙂 .

If you are interested in how this works in detail or even you want to create your own messages, please check our ROS Basics In 5 Days (Python) course!

Extra 1: ROSject link

Get the ROSject containing all code used in the post in the following link: http://www.rosject.io/l/18f83296-0e7e-4c5c-95a7-2d3e3d6430d4/

Extra 2: Video

Prefer to watch a video demonstrating the steps above? We have one for you below!

Related Resources

If you are a ROS beginner and want to learn ROS basics fast, we recommend you take any of the following courses on Robot Ignite Academy:

Feedback

Did you like this post? Whatever the case, please leave a comment 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] 135 – How to rotate a robot to a desired heading using feedback from odometry?

 

In this video we are going to see how to rotate our robot based on data from odometry. We will subscribe to /odom topic to get the heading of our robot, process it, and then send a command over the /cmd_vel topic.

This is a video based on the following post on ROS Answers: https://answers.ros.org/question/290534/rotate-a-desired-degree-using-feedback-from-odometry

// RELATED LINKS

▸ Original question: https://goo.gl/GSHi42
▸ ROS Development Studio (ROSDS): https://goo.gl/bUFuAq
▸ Robot Ignite Academy: https://goo.gl/6nNwhs

[irp posts=”7999″ name=”ROS Q&A – How to convert quaternions to Euler angles”]

Step 1. Create a project in ROS Development Studio(ROSDS)

We can do any ROS development we want easily, without setting up environment locally in ROSDS and that’s the reason why we will use ROSDS for this tutorial. If you haven’t had an account yet. You can create one here for free now. After logging in, let’s begin our journey by clicking on the create new project and call it rotate_robot.

Step 2. Create package

At first, we launch the simulation from Simulations->Turtlebot 2

We’ll create a package for the rotating robot task with the following command

cd ~/catkin_ws/src
catkin_create_pkg rotate_robot rospy

Then we’ll create a script folder and a main.py script inside it with the following content

#!/usr/bin/env python
import rospy
from nav_msgs.msg import Odometry
from tf.transformations import euler_from_quaternion, quaternion_from_euler

roll = pitch = yaw = 0.0

def get_rotation (msg):
    global roll, pitch, yaw
    orientation_q = msg.pose.pose.orientation
    orientation_list = [orientation_q.x, orientation_q.y, orientation_q.z, orientation_q.w]
    (roll, pitch, yaw) = euler_from_quaternion (orientation_list)
    print yaw

rospy.init_node('my_quaternion_to_euler')

sub = rospy.Subscriber ('/odom', Odometry, get_rotation)

r = rospy.Rate(1)
while not rospy.is_shutdown():
    quat = quaternion_from_euler (roll, pitch,yaw)
    print quat
    r.sleep()

Then we can run the script with the following command to see the topic publishing in quaternion and Euler angle.

cd rotate_robot/script
chmod +x main.py
rosrun rotate_robot main.py

You can also run the teleop script to move the robot and see the value changing with this command

rosrun  teleop_twist_keyboard teleop_twist_keyboard.py

Step 3. Rotate the robot

We’ll use the easiest way to do it by applying the controller. Please save the script with a new name rotate.py and change it as the following content.

#!/usr/bin/env python
import rospy
from nav_msgs.msg import Odometry
from tf.transformations import euler_from_quaternion, quaternion_from_euler
from geometry_msgs.msg import Twist
import math

roll = pitch = yaw = 0.0
target = 90
kp=0.5

def get_rotation (msg):
    global roll, pitch, yaw
    orientation_q = msg.pose.pose.orientation
    orientation_list = [orientation_q.x, orientation_q.y, orientation_q.z, orientation_q.w]
    (roll, pitch, yaw) = euler_from_quaternion (orientation_list)
    print yaw

rospy.init_node('rotate_robot')

sub = rospy.Subscriber ('/odom', Odometry, get_rotation)
pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)
r = rospy.Rate(10)
command =Twist()

while not rospy.is_shutdown():
    #quat = quaternion_from_euler (roll, pitch,yaw)
    #print quat
    target_rad = target*math.pi/180
    command.angular.z = kp * (target_rad-yaw)
    pub.publish(command)
    print("taeget={} current:{}", target,yaw)
    r.sleep()

After executing it, you should see the robot turn to the desired orientation.

 

Want to learn more?

Applying the controller is not the only way to do it. There are more advanced and better ways to do it. If you are interested, please check our ROS Basic and TF ROS 101 courses  in  Robot Ignite Academy for more information.

 

 

Edit by: Tony Huang

 


 

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 Q&A] 132 – Callback messages being executed one at a time

In this video we are going to see how to make sure callback messages are being executed one at a time.

This is a video trying to answer the following question posted at the ROS answers forum: https://answers.ros.org/question/287612/how-to-be-100-sure-that-only-one-callback-is-being-executed-at-a-time

RELATED LINKS

▸ Original question: https://answers.ros.org/question/287612/how-to-be-100-sure-that-only-one-callback-is-being-executed-at-a-time
Robot Ignite Academy
ROS Basics in 5 days (Python)
ROS Development Studio (ROSDS)

Step 1. Create a project in ROS Development Studio(ROSDS)

We’ll answer this question by walking you through an example with ROSDS. With ROSDS, we can focus on solving the problem directly instead of finding Linux pc, install ROS and etc. You can create an account here for free. After registering, let’s create a new project and call it q_a_callback_processing.

Step 2. Create package

Then, we’ll create a package with dependencies

cd catkin_ws/src
catkin_create_pkg my_pkg rospy std_msgs

Then create a folder called script under the package directory and a file called publisher.py under the script directory with the content

#!/usr/bin/env python

import rospy
from std_msgs.msg import Int32

def publisher():
    pub = rospy.Publisher('topic_name', Int32, queue_size=10)
    rospy.init_node('publisher')
    r = rospy.Rate(30)
    
    count = 1
    msg = Int32()
    while not rospy.is_shutdown():
        msg.data = count
        count = count+1 if count < 30 else 1
        pub.publish(msg)
        rospy.loginfo(msg)
        r.sleep()

if __name__ == '__main__':
    publisher()

You can see that the topic is publishing at 30 Hz.

To run it, you have to give it permission first with chmod +x publisher.py , then you can run it with rosrun my_pkg publisher.py . You’ll see the script starts to publishing message.

Now the publisher is working, let’s create a subscriber to subscribe to the topic. Let’s call it subscriber.py and fill it with the following content

#!/usr/bin/env python

import rospy
from std_msgs.msg import Int32

processing = False
new_msg = False
msg = None

def callback(data):
    global processing, new_msg, msg
    if not processing:
        new_msg = True
        msg = data

def listener():
    global processing, new_msg, msg
    rospy.init_node('subscriber')
    rospy.Subscriber('topic_name', Int32, callback)
    r = rospy.Rate(5)
    while not rospy.is_shutdown():
        if new_msg:
            #set processing to True
            processing = True
            new_msg = False
            #simulate a process that take 0.2 seconds
            rospy.loginfo(msg)
            r.sleep()
            #set processing to False
            processing = False
    
if __name__ == '__main__':
    listener()

Here in the subscriber, we only run it for 5 Hz. Now you have to give it permission and run it. You’ll see that the subscriber only get 5 messages every second. This is the answer!

 

Take away today:

You can specify different rates and r.sleep() function for publisher and subscriber in order to make sure the node has enough time to run your algorithm.

 

Edit by: Tony Huang


Feedback

Did you like this video? 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.

CMakeLists.txt Tutorial & Example

CMakeLists.txt Tutorial & Example

Hello ROS developers! In this post, we will see what CMakeLists.txt is and it’s importance in ROS in just 5 minutes! We’ll see what happens when it’s absent and when it’s improperly modified.

Let’s go!

Step 1: Setup your development environment

I love coding, and I hope you do too. Because of this, we’re going to solve the problem in this section using a pseudo-Python code. Here you go:

def setup_ros_environ(you, ros, docker):
  if you.prefer_not_to_embrace_the_cloud_revolution() or not you.want_something_that_works_for_sure():
    if ros.is_installed() and ros.version <= 'kinetic' and ros.version < 'crystal':
      return "You are good to go; just be ready to spin up a terminal at short notice."
    elif docker.is_installed():
      return "run docker run -it osrf/ros:kinetic-desktop in your terminal to pull a ROS docker image. " 
             "Please note: " 
             "- Docker will “pull” this image if you don’t have it locally already." 
             "- You need to run this command on every terminal you use in this post, before typing any other command!" 
  else: 
    return "Launch a ready-to-go development environment on ROS Development Studio (http://rosds.online) within your browser!" 
           "Click this link to get your copy of a ready-made ROS project: http://www.rosject.io/l/92ac9a3/" 
           "To 'open a terminal', pick the Shell app from the Tools menu. "

“Run” the program above, act on the output and proceed to the next section!

Step 2: See what CMakeLists.txt is by getting your hands dirty – on the Shell and/or IDE

Create a package in your catkin workspace (we won’t add any code here since it’s not needed for the demo). If you are using the ROS Development Studio and copied the ROS project, the package is already there!

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

After creating a package, we ought to compile it. But before that, we’ll tamper with the CMakeLists.txt file and see what happens.

  1. Rename CMakeLists.txt to CMakeList.txt. Similar enough and should work, right? Let’s see.
user:~/catkin_ws/src$ cd cmakelists_test/
user:~/catkin_ws/src/cmakelists_test$ mv CMakeLists.txt CMakeList.txt
user:~/catkin_ws/src/cmakelists_test$ cd ../..
user:~/catkin_ws$ catkin_make
...(output truncated)
-- ~~  traversing 1 packages in topological order:
-- ~~  - cmakelists_test
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'cmakelists_test'
-- ==> add_subdirectory(cmakelists_test)
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_workspace.cmake:116 (add_subdirectory):
  The source directory

    /home/user/catkin_ws/src/cmakelists_test

  does not contain a CMakeLists.txt file.
Call Stack (most recent call first):
  CMakeLists.txt:63 (catkin_workspace)


-- Configuring incomplete, errors occurred!
See also "/home/user/catkin_ws/build/CMakeFiles/CMakeOutput.log".
See also "/home/user/catkin_ws/build/CMakeFiles/CMakeError.log".
Invoking "cmake" failed

Didn’t work for sure. Let’s perform another dastardly act:

2. Restore the original name but comment out the ‘project’ directive of the CMakeLists.txt file shown below:

cmake_minimum_required(VERSION 2.8.3)
# project(cmakelists_test)                    --> comment out this line

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
user:~/catkin_ws$ cd src/
user:~/catkin_ws/src$ cd cmakelists_test/
user:~/catkin_ws/src/cmakelists_test$ mv CMakeList.txt CMakeLists.txt
user:~/catkin_ws/src/cmakelists_test$ cd ../..
user:~/catkin_ws$ catkin_make
... (output truncated)
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - cmakelists_test
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'cmakelists_test'
-- ==> add_subdirectory(cmakelists_test)
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:91 (message):
  catkin_package() PROJECT_NAME is set to 'Project', which is not a valid
  project name.  You must call project() before calling catkin_package().
Call Stack (most recent call first):
  cmakelists_test/CMakeLists.txt:103 (catkin_package)


-- Configuring incomplete, errors occurred!
See also "/home/user/catkin_ws/build/CMakeFiles/CMakeOutput.log".
See also "/home/user/catkin_ws/build/CMakeFiles/CMakeError.log".
Makefile:318: recipe for target 'cmake_check_build_system' failed
make: *** [cmake_check_build_system] Error 1
Invoking "make cmake_check_build_system" failed

We aren’t getting away with tampering with CMakeLists.txt, are we? Now, let’s repent and restore the file: remove the comment from the ‘project’ directive, save and run catkin_make again.

cmake_minimum_required(VERSION 2.8.3)
project(cmakelists_test)                    --> uncomment this line

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
user:~/catkin_ws$ catkin_make
... (output truncated)
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - cmakelists_test
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'cmakelists_test'
-- ==> add_subdirectory(cmakelists_test)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/catkin_ws/build
####
#### Running command: "make -j2 -l2" in "/home/user/catkin_ws/build"
####

Moral lesson: CMakeLists.txt can make or mar a project, if not properly modified. Let’s talk more about that in the next section.

Step 3: Master the concept – what is CMakeLists.txt?

According to ROS Wiki (http://wiki.ros.org/catkin/CMakeLists.txt),

The file CMakeLists.txt is the input to the CMake build system for building software packages. Any CMake-compliant package contains one or more CMakeLists.txt file that describe how to build the code and where to install it to.

Well, now you can see why renaming the file isn’t a good idea.  But what about commenting out parts of the file? Also according to ROS Wiki:

Your CMakeLists.txt file MUST follow this format otherwise your packages will not build correctly. The order in the configuration DOES count.

The configuration directives in CMakeLists.txt must follow a particular order; this is why commenting out the ‘project’ directive didn’t work, as the error message also hinted.

Visit http://wiki.ros.org/catkin/CMakeLists.txt to learn more.

We’re done here.

Extra: Video

Prefer “sights and sounds” to “black and white”? We have a video covering this same post, just for you!

Followup and Feedback

If you are a ROS beginner and want to learn ROS basics fast, we recommend you take any of the following courses on Robot Ignite Academy:

ROS Basics In 5 Days (Python)
ROS Basics In 5 Days (C++)

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

Thank you!

[ROS Q&A] 134 – Simple ROS Publisher in C++

In this video we are going to see how to create a simple ROS Publisher in C++.

* This is a video based on the question at the ROS Answers Forum

Step 1. Create a project in ROS Development Studio(ROSDS)

ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here. Let’s create a new project and call it abc_qa.

Step 2. Create a package

Let’s create a new package called abc_qa with dependency for the code.

cd catkin_ws/src
catkin_create_pkg abc_qa roscpp

Then we create a source file called abc_code.cpp under the abc_qa/src directory with the following content

int main()
{
     //Initialize and start the node
     ros::Publisher pub;
     //Define and create some messages
     abc;
     while(ros : ok)
     {
           ros_time = ros::time::now();
           pub.publish(abc);
           ros::spinOnce();               
     }

 }

In order to compile the code, we have to change the following BUILD part in the CMakeLists.txt.

...
## 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(abc_node src/abc_code.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(abc_node ${abc_node_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

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

...

Then we can try to compile it with the following command

cd ~/catkin_ws
catkin_make

You should get several compilation errors. Let’s fix the code. It should look like this after changing.

#include <ros/ros.h>
#include <std_msgs/Int32.h>

int main(int argc, char ** argv)
{
     //Initialize and start the node
     ros::init(argc, argv, "abc");
     ros::NodeHandle nh;
     
     ros::Publisher pub = nh.advertise<std_msgs::Int32>("abc_topic", 1000);
     //Define and create some messages
     std_msgs::Int32 abc;
     abc.data = 0;
     
     ros::Rate(200);
     
     while(ros::ok)
     {
           pub.publish(abc);
           ros::spinOnce();               
     }

 }

It should work now. Try to compile and run it again with the following command

cd ~/catkin_ws
catkin_make
source devel/setup.bash
rosrun abc_qa abc_node

Now we got error said that it’s missing master now. You can either run whatever simulation from Simulations or run roscore  in a new shell to solve this problem. After launching the master, execute the code again. Although it shows nothing, it is actually starting to publish to topic /abc_topic you can see it with the command rostopic echo /abc_topic. You can also try to increment the counter in the while loop.

Related Course

ROS Basics C++ Course Cover - ROS Online Courses - Robot Ignite Academy

ROS Basics for Beginners (C++)

 


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 in the comments area and we will do a video about it.

[Infographic] ROS Python vs C++

[Infographic] ROS Python vs C++

Getting Started with ROS Python or C++?

If you are new to ROS and unfamiliar with C++ or Python, you must be wondering whether you should start with ROS Python or ROS C++ in order to maximize your ROS learning speed.

In this infographic we recommend you start with ROS Python and show you 3 reasons for not using C++ in ROS:
ROS Python or ROS C++

Related resources:

Pin It on Pinterest