The Beginner Tutorial is quite long so I made this article to quickly go through everything we need to know about ROS.

My Environment:

ROS kinetic on Ubuntu 16.04

ROS melodic on Ubuntu 18.04

VScode support for ROS

C++ and Python

C++

  • C++ codes go to <your package>/src folder
    • For c++, you need to mess with the CMakeLists.txt in package level.

Messing with CMakeLists.txt (C++)

Just add these into the bottom.

Lets say we have a file in src called webcam_pub_cpp.cpp.

1
2
add_executable(webcam_pub_cpp src/webcam_pub_cpp.cpp)
target_link_libraries(webcam_pub_cpp ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

More info about CMakeLists.txt in ROS

Python

  • Python codes go to <your package>/scripts folder (you may need to manually create the scripts folder)
    • You can also choose to set the interpreter in the first line of python script.
      • #!/usr/bin/env python - python 2.7
      • #!/usr/bin/env python3 - python 3
    • You need to mark the python file as executable

Node default ROS Melodic use python 2.7 interpreter. You need to mess with the ROS setup in order to use python3.

Mark as executable

For python scripts, you need to make the file an executable.

1
chmod +x <your program>.py

Messing with CMakeLists.txt (Python)

Just add these into the bottom.

Lets say we have 2 files in scripts called webcam_pub.py and webcam_sub.py.

1
2
3
4
5
catkin_install_python(PROGRAMS
scripts/webcam_pub.py
scripts/webcam_sub.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

More info about CMakeLists.txt in ROS

Publisher and Subscriber

The publisher (“talker”) node will continually broadcast a message.

The subscriber node will receive the messages of publisher node.

  • Any node can publish a message to a topic
  • Any node can subscribe to any topic
  • Multiple node can publish/subscribe to the same topics
  • A Node can publish/subscribe to multiple topics

ROS master can be started with roscore or roslaunch.

useful command as publisher/subscriber tools

  • rosnode list
    • Check nodes
  • rosnode info /<some_node>
    • Check publications, subsciptions and services of the rosnode
  • rostopic list
    • Check active topic
  • rostopic list -v
    • Check active topic (detailed)
  • rostopic info /<some_topic>
    • Check the Publishers and Subscribers of that topic
  • rostopic echo /<some_topic>
    • Print messages to screen
  • rostopic pub /<some_topic>
    • Publish data to topic

roslaunch

Since we often run the publisher and subscriber at the same time, it is better to run them together.

the file can be put in the launch folder. (You need to manually create the folder)

1
2
3
4
5
6
7
8
9
10
11
12
<launch>
<node
pkg="<your package name>"
type="<your cpp/py filename (for cpp no need filetype, only the name)>"
name="<your cpp/py filename (no need filetype, only the name)>"
output="screen"
/>
<node
...
/>
...
</launch>
  • launch: Root element of the launch file
  • node: Each <node> tag specifies a node to be launched
  • name: Name of the node (free to choose)
  • pkg: Package containing the node
  • type: Type of the node, there must be a corresponding executable with the same name
  • output: Specifies where to output log messages (screen: console, log: log file)

You can include other package’s launch file in ur launch file.

Roslaunch tips for large projects

Service and Client

ROS msg and srv

First we need to have the concept of ROS msg and srv.

  • msg files are simple text files that describe the fields of a ROS message. They are used to generate source code for messages in different languages.
    • msg files are stored in the msg directory.
  • srv file describes a service. It is composed of two parts: a request and a response.
    • srv files are stored in the srv directory.

msg

msgs are just simple text files with a field type and field name per line. The field types you can use are:

  • int8, int16, int32, int64 (plus uint*)
  • float32, float64
  • string
  • time, duration
  • other msg files
  • variable-length array[] and fixed-length array[C]

There is also a special type in ROS: Header, the header contains a timestamp and coordinate frame information that are commonly used in ROS. You will frequently see the first line in a msg file have Header header.

Here is an example of a msg file:

1
2
3
4
5
6
Header header
int64 num
string first_name
string last_name
uint8 age
uint32 score
  • msg files are located in <your package>/msg folder. (You need to manually create the folder).

Creating a msg

Creating a msg file

First go to your package

1
cd <your package>

create folder msg if you dont have it

1
mkdir msg

then create a msg file (lets say in this example we name it Num.msg)

1
touch msg/Num.msg

Then add those lines into Num.msg.

1
2
3
4
5
int64 num
string first_name
string last_name
uint8 age
uint32 score

Modify package.xml

We need to modify the <your package>/package.xml to make sure that the msg files are turned into source code for C++, Python, and other languages. Uncomment these 2 lines by removing <!-- and -->:

1
2
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Note that at build time, we need “message_generation”, while at runtime, we only need “message_runtime”

Modify CMakesLists.txt

After modifying the <your package>/package.xml, we must also modify the <your package>/CMakeLists.txt.

add the message_generation dependency to the find_package

1
2
3
4
find_package(catkin REQUIRED COMPONENTS
...
message_generation
)

You may notice that sometimes your project builds fine even if you did not call find_package with all dependencies. This is because catkin combines all your projects into one, so if an earlier project calls find_package, yours is configured with the same values. But forgetting the call means your project can easily break when built in isolation.

export the message runtime dependency

1
2
3
4
5
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...
)

replace the stand in Message*.msg files with your .msg file (We assume we have msg/Num.msg in this example)

1
2
3
4
## Generate messages in the 'msg' folder
add_message_files(FILES
Num.msg
)

By adding the .msg files manually, we make sure that CMake knows when it has to reconfigure the project after you add other .msg files.

1
2
3
4
5
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)

After creating the msg, make sure that ROS can see it.

1
rosmsg show <message filename (only name)>

srv

srv files are just like msg files, except they contain two parts: a request and a response. The two parts are separated by a ‘—’ line.

Here is an example of a srv file:

1
2
3
4
int64 A
int64 B
---
int64 Sum

Creating a srv

First go to your package

1
cd <your package>

create folder srv if you dont have it

1
mkdir srv

then create a srv file (lets say in this example we name it AddTwoInts.srv)

1
touch srv/AddTwoInts.srv

Then add those lines into AddTwoInts.srv.

1
2
3
4
int64 A
int64 B
---
int64 Sum

Modify package.xml

If you have done it in the previous section, skip it.

We need to modify the <your package>/package.xml to make sure that the msg files are turned into source code for C++, Python, and other languages. Uncomment these 2 lines by removing <!-- and -->:

1
2
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Note that at build time, we need “message_generation”, while at runtime, we only need “message_runtime”

Modify CMakesLists.txt

After modifying the <your package>/package.xml, we must also modify the <your package>/CMakeLists.txt.

add the message_generation dependency to the find_package

1
2
3
4
find_package(catkin REQUIRED COMPONENTS
...
message_generation
)

If you have done this^, just do the below.

replace the placeholder Service*.srv files with your .srv file (We assume we have srv/AddTwoInts.srv in this example)

1
2
3
4
## Generate messages in the 'srv' folder
add_service_files(FILES
AddTwoInts.srv
)

After creating the msg, make sure that ROS can see it.

1
rossrv show <service filename (only name)>

Recording and Playing back data

The main component of rosbags is the bag file. A bag file is a formatted file that contains timestamped ROS messages.

Usally located at <your package>/bagfiles (we need to manually create bagfiles folder)

In the bagfiles folder, you can:

If you want to create a bag file of specific topics:

1
rosbag record -O <filename>.bag <topic-names>

If you want to record the messages of all published topics that are currently active, you would use the following command:

1
rosbag record -a

You don’t want to use the command above in large, complex robotics applications because your files can get quite large, especially if your application has a vision system that publishes data from a camera.

If you want to inspect a bag file, the syntax for doing this is:

1
rosbag info <filename>.bag

If you want to replay a bag file ,the syntax for doing this is:

1
rosbag play <filename>.bag

The Limitation of rosbag record/play

the user should not expect perfectly mimicked behavior when replaying the rosbag file.

Reference