ROS stands for Robot Operating System. It is a collection of libraries and utilities that make up a software framework that is a node based publisher-subscriber model. It allows developers to quickly write modular code for a robot that does a specifc task while providing a layer of useful libraries and introspection tools. The publisher-subscriber principal allows for minimal coupling by leaving it up to each node to subscribe and publish data as it wishes to a common bus that is accessible to all other nodes.
The following are a set of notes I have taken while learning how to use ROS, and applying ROS to build an autonomous street robot name Primo.
A package in ROS is the “software organization unit of ROS code”. Think of a package as software project that does one task. It might contain multiple nodes, aka executable ROS processes, and a bunch of configuration information.
For example, say we have a robot with a robotic arm that uses a motor that is connected to an output shaft via some gearing, and also cause we're fancy we have a torque transducers on the output shaft along with an encoder for position information. That is a good amount of stuff for just one arm joint, but this “arm joint stuff” perfect candidate for a package. We can boil it down to set of tasks relating to the joint and cease a package. On top of that we can create the package in such a way that it can be configurable, and applied to more of the similar joints. The package would be responsible for the following:
Sketch of package responsibilities
With that sketch of responsibilities we can create engineering requirements that fully define the tasks and then go on to either try to find a package that does this already, or make our own. If we decide to make our own we'll build out our package and have nodes that handle each of those tasks that can easily talk to each other etc. Hope that gives you a good idea of what a ROS package is!
Nodes: A node is an executable that uses ROS to communicate with other nodes. Messages: ROS data type used when subscribing or publishing to a topic. Topics: Nodes can publish messages to a topic as well as subscribe to a topic to receive messages. Master: Name service for ROS (i.e. helps nodes find each other) rosout: ROS equivalent of stdout/stderr roscore: Master + rosout + parameter server (parameter server will be introduced later)
Use the rosnode command to get information about currently running nodes.
The following is the simplest structure of a ROS package:
my_package/ CMakeLists.txt package.xml
The manifest is a file called package.xml
and is a description of the package.
A package in a catkin workspace looks like this:
workspace_folder/ -- WORKSPACE src/ -- SOURCE SPACE CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin package_1/ CMakeLists.txt -- CMakeLists.txt file for package_1 package.xml -- Package manifest for package_1 ... package_n/ CMakeLists.txt -- CMakeLists.txt file for package_n package.xml -- Package manifest for package_n
Services are another way nodes can communicate with each other. Services allow nodes to send a request and receive a response.
You can look up the type of a service. Then using rossrv
you can get more information
on the that service. For example:
rosservice type /spawn | rossrv show
There is also such a thing as the ROS parameter server. It stores data.
You can look at all this data by using the rosparam
command. You can
list the parameters, set them and even save and load them.
Service files (srv) 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:
int64 A
int64 B
---
int64 Sum
Here are the steps to add a ROS service to a package. These are similar to adding a message.
.srv
file to the srv/
directory of a packagemessage_generation
and message_runtime
build and runtime dependencies are enabled in the package.xml
file.
When this is done, running catkin_make install
will build all the necessary stuff and also generate the header files required.
A service/client is another form of communication in ROS. Instead of relying on publisher/subscriber messages, which are asynchronous, you have a synchronous service based communication. A client calls a service and waits for a response.
srv/
folderros::init
ros::NodeHandle
ros::ServiceServer
ros::spin();
src/
folderros::init()
ros::NodeHandle
ros::ServiceClient
client.call(srv)
which acts as calling the service and gets returned with a response. Pretty neat.CMakeLists.txt
files## Declare a cpp executable add_executable(executable_one src/source_one.cpp src/source_two.cpp src/source_n.cpp)
To create multiple executables, you just add multiple instances of that line:
## Declare a cpp executable add_executable(executable_one src/source_one.cpp src/source_two.cpp src/source_n.cpp) add_executable(executable_two src/source_one.cpp src/source_two.cpp src/source_n.cpp) add_executable(executable_three src/source_one.cpp src/source_two.cpp src/source_n.cpp)
tf keeps track of all these frames over time, and allows you to ask questions like:
Transform is a deprecated package with tf2 being the new one.
I did the tutorials where I created a broadcaster and a listener in c++. I also did some stuff where you can compute the transform between two frames and convert it to a velocity command to a robot.
There are two things that you need to do to use tf. You have to listen and broadcast them.
There is a REP that outlines lots of good best practice stuff when defining your robot link.
For learning about quaternions check out the OGRE Quaternions intro.
For conversions use this calculator link.
You can use rosrun tf2_tools view_frames.py
to show you information about the frames.
You can use rosrun tf tf_monitor frame1 frame2
to show you timing info.
tf::MessageFilter
is a function that allows us to process stamped datatypes.
turtle1 wants to know its position relative to itself
Convenient class that allows to do the following:
The robot state publisher helps you to broadcast the state of your robot to the tf transform library.
It needs two things to run:
sensor_msgs/JointState
It subscribes to joint_states topic for joint position information.
It uses the following parameters
The rostopic
command lets you monitor all aspects of a ROS topic.
You can also use rostopic
to publish data of any message into a ROS topic.
rostopic hz <topic>
: look at how often a message is being sentrostopic pub <topic> <data>
: publish data to the topic
When using rostopic pub
, make sure you do not have a /
before the message name or
else autocomplete won't work!!!
Recording and playing back data is really nice and easy with ROS.
To record everything you run:
rosbag record -a
To play back a bag file you run:
rosbag play <your bag file>
URDF is an XML file that stands for Unified Robot Description Format.
Unfortunately the tutorials do not give you a step by step guide on how to make a URDF. Instead they just explain a sample URDF tutorial project, which leaves me guessing as to how integrate a URDF in an existing package.
There is a Solidworks to URDF exporter but is old and does not work very well. Do not use it! You are much better off learning how to code your own URDF files.
In a URDF there is a tree structure with one root link. The way you organize these links is with joints. You declare the links and then specify joints between them. If you have two links with no joint specified, RViz will give you an error.
If there are any joints in a mesh, you need to run the joint_state_publisher and also the robot_state_publisher. That means in your launch file you will have the following:
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" /> <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
You specify meshes in a URDF with the following:
<mesh filename="package://NAME_OF_PACKAGE/path"/>
You can use the command check_urdf
to text the URDF file. URDF_basic
For URDF files to work in gazebo they need to have the following:
<robot name="rrbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<intertia>
element within each <link>
element.The link tab has an origin tag with rpy and xyz params. These only change the origin of the object. They do not change the position. To change the position you set up a joint.
:URDF_basic: http://wiki.ros.org/urdf/Tutorials/Create%20your%20own%20urdf%20file :Gazebo_tut: http://gazebosim.org/tutorials/?tut=ros_urdf#Simplifycollisionmodel
Xacro is a URDF macro scripting language that gives you functionality to create more powerful and dynamically generated URDF code. It is a bit tricky to learn but it is very helpful.
The way it works is that you make a xacro file and then have the URDF get automatically generated.
You need these two lines at the top of a xacro file.
<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="firefighter">