ROS Fundamentals - UTRA-ART/Caffeine GitHub Wiki
Written by: Erick Mejia Uzeda
Use the SumoROS repo to show examples for how to use concepts covered in this wiki!
ROS stands for Robot Operating System and serves as a framework for coding up robots. ROS is open source and has a large community of contributors for a variety of packages. Lots of things you will learn and more can be found in ROS Answers, but to cover the fundamentals this wiki will go over:
A good resources to consult is the book: A Gentle Introduction to ROS
- ROS architecture
- master
- nodes
- topics + messages
- Coding in ROS
- workspaces
- packages
- launch files
- Transforms
- ROS commands
When running ROS, a network of nodes is created with topics and services serving as communication channels between them. When visualized using rqt_graph
, the full network looks like a graph with ROS nodes serving as graph nodes and edges being ROS topics as seen in the following image
Another representation consists of ROS nodes as circle nodes and topics being rectangular nodes
To run the ROS master, run roscore
in a terminal. Note that roscore
has no additional arguments and will consume the terminal until the process is killed (Ctrl+C
). The master needs to be running for the entire time ROS is running.
ROS master can be thought of as the brain which enables nodes to connect to it, run and as well as sets up and manages the whole communication network via topics and services between nodes. It even holds a parameter server to store data. Note that when using roslaunch
the master will start automatically!
An instance of a ROS program is called a ROS node. Nodes are generally written in C++ or Python and can be thought of units that perform some form of data processing.
From the pov of the ROS master, nodes can be a subscriber and/or publisher. Subscribers are nodes that "subscribe" to a topic and read the messages published on it. Publishers are nodes that "publish" messages to a topic, enabling data transfer between nodes. In essence, subscribing and publishing is how a node performs IO operations.
The following image shows the relationship between the master, nodes and topics:
Communication between nodes is done via topics, with messages being passed through them. Note that each topic can only use one message type but we can have multiple topics using the same message type.
One can compare a topic to a data bus (in electronics) which allows transferring data between different nodes, with the message being the format in which the data is being transferred in. A subscriber/publisher would be a node that connects to that data bus and reads/publishes the data from the bus using the specified message type.
In reality, the ROS master sets up peer-to-peer connections between nodes based on the topics. Note that one can define their own custom message types as well.
Workspaces and packages are created and managed using catkin
. The general structure of a ROS development environment looks as follows:
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- The 'toplevel' CMake file
package_1/
CMakeLists.txt
package.xml
...
package_n/
CATKIN_IGNORE -- Optional empty file to exclude package_n from being processed
CMakeLists.txt
package.xml
...
build/ -- BUILD SPACE
CATKIN_IGNORE -- Keeps catkin from walking this directory
devel/ -- DEVELOPMENT SPACE (set by CATKIN_DEVEL_PREFIX)
bin/
etc/
include/
lib/
share/
.catkin
env.bash
setup.bash
setup.sh
...
install/ -- INSTALL SPACE (set by CMAKE_INSTALL_PREFIX)
bin/
etc/
include/
lib/
share/
.catkin
env.bash
setup.bash
setup.sh
...
A workspace is a folder where one builds, modifies and installs packages. All ROS development is done within a workspace.
To create a workspace, run:
mkdir -p catkin-ws/src
cd catkin-ws
catkin_make
First we create a workspace folder called catkin-ws
and an inner folder called src
- which will hold all our packages. Then run catkin_make
in /catkin-ws
to initialize the workspace. catkin_make
also builds all packages found in /src
. Note that you will have 2 more folders in /catkin-ws
after running catkin_make
: /build
and /devel
- you can leave those folders alone, they contain your compiled ROS code.
To have access to the code we just built, we "source" the terminal. This makes the newly compiled packages visible to the terminal. To source, go into /catkin-ws
and run:
source devel/setup.bash`
Quoting the ROS wiki: "Software in ROS is organized in packages. A package might contain ROS nodes, a ROS-independent library, a dataset, configuration files, a third-party piece of software, or anything else that logically constitutes a useful module. The goal of these packages it to provide this useful functionality in an easy-to-consume manner so that software can be easily reused. In general, ROS packages follow a "Goldilocks" principle: enough functionality to be useful, but not too much that the package is heavyweight and difficult to use from other software."
Packages are created in /src
using catkin by executing:
cd catkin-ws/src
catkin_create_package <package_name> <dependencies>
Some common directories found in packages are:
-
/launch
which houses launch files -
/src
which houses C++ code for nodes -
/scripts
which houses Python code for nodes
Moreover, if one wants to use someone else's package, then clone the package repository into the /src
folder. Packages can also be installed globally using sudo apt-get install ros-<distro>-<package>
.
Launch files are written in XML, generally exist in the /launch
folder of a package and can run multiple nodes, call other launch files as well as set parameters in the ROS parameter server. It also automatically launches/re-uses ROS master.
Any launch file is enclosed in the <launch></launch>
tag. Other common tags are:
<arg>
Specify an input argument to the launch file
<include>
Call another launch file
<node>
Run a node
Launch files can be run using:
roslaunch <package> <file>.launch <arg>:=<value>
For a full list of tags and attributes, see the ROS wiki. Note that we can evaluate simple python expressions in launch files and access variables using the $(...)
operator.
Given that robots have many moving parts, one must manage the different frames (coordinate systems) that exist. This is done in ROS via the tf
package - Note. the tf2
package is replacing the tf
package in ROS.
Mathematically, the relationship between different coordinate systems is described using a transform. A transform is described using a 4x4 matrix and describes the translation, rotation and scale needed to go from one frame to another. If you have a well defined origin, then a transform can describe a frame itself.
Example of a TRS 4x4 transform matrix with unit scaling
From the pov of ROS (the tf
package), it creates a data structure called the transform tree (tf_tree
) to maintain the relationships between the various frame. The tf_tree
can be viewed by running rosrun rqt_tf_tree rqt_tf_tree
.
The nodes of the tree correspond to frames (ie. a coordinate system) and the edges show the relationship between the frames. A tree is used to avoid any contradictions when querying the transform between two frames.
There are a variety of cheat sheets giving a high level overview of command line ROS commands that can be found. This is one of them. The important commands are:
rostopic
list
to get all current topics.
echo <topic>
to print out the messages being published to the specified topic.
pub <topic> <msg_type> <msg>
to publish a message to a topic.
roslaunch <package> <file>.launch
runs launch files which serve as scripts that can run many ROS nodes and other launch files.
rosrun <package> <node>
runs executables from as ROS nodes.
rqt_graph rqt_graph
opens up the rqt GUI with the graph plugin. Allows to view nodes and topics.
rqt_tf_tree rqt_tf_tree
opens up rqt GUI with the tf_tree plugin. Allows to view frames and their relationships.