ROS: A Minimum Tutorial
- This is a minimum tutorial of ROS. For a complete tutorial, read http://wiki.ros.org/ROS/Tutorials .
This tutorial assumes you have already installed the ROS.
Environment setup †
Details are written in: http://wiki.ros.org/ROS/Tutorials/InstallingandConfiguringROSEnvironment
Step-1 †
Make your ROS workspace directory in your home directory:
$ cd ~
$ mkdir ros_ws
Tilde ~ denotes your home directory. You can change the name ros_ws as you want. Also, make Catkin workspace (e.g. catkin_ws) if you want to use Catkin. Additional steps may be needed (see the tutorial).
Step-2 †
If you are using the bash terminal environment, execute the following one by one. Change ROS_DISTR if you are using a different ROS version (like groovy, hydro, ...).
$ ROS_DISTR=indigo
$ . /opt/ros/$ROS_DISTR/setup.bash
$ . ~/catkin_ws/devel/setup.bash
$ . /opt/ros/$ROS_DISTR/share/rosbash/rosbash
Note: The catkin_ws command works only when you setup Catkin in the ~/catkin_ws directory.
Optionally, configure the ROS Master URI (default: http://localhost:11311) and ROS_IP (IP address of your computer; default: N/A).
$ export ROS_MASTER_URI=http://localhost:11311
$ export ROS_IP=127.0.0.1
Then, we will register additional paths (your ROS workspace) to the ROS system.
$ export ROS_PACKAGE_PATH=${ROS_PACKAGE_PATH}:$HOME/ros_ws:$HOME/prg/testl/ros_sandbox
Here, $HOME/ros_ws and $HOME/prg/testl/ros_sandbox are added. Modify them as you want.
Those directories will be recognized by ROS. You can put your or other developers' packages in those directories, then you can use them through ROS.
Execute Step-1 just once for each computer/user. Execute Step-2 for each new terminal.
If you don't like to write Step-2 every time, write them in ~/.bashrc, or make an alias, or ...
Let's use ROS! †
Sending and receiving ROS topic from command †
In the first test, we use the rostopic command to send a ROS topic, and receive that topic with another rostopic command.
Anyway, let's run roscore.
$ roscore
Open a new terminal (don't forget Step-2), execute:
$ rostopic pub -r 10 /test std_msgs/String 'humanoids'
- pub: rostopic will publish a topic.
- -r 10: in 10 Hz.
- /test: the topic name is "/test".
- std_msgs/String: the message type is std_msgs/String (a string).
- 'humanoids': the sending data is 'humanoids'.
Open a new terminal (don't forget Step-2), execute:
$ rostopic echo /test
- echo: rostopic will subscribe a topic.
- /test: the topic name is "/test".
You will see
data: humanoids --- data: humanoids --- ...
Press "Ctrl+C" to stop the programs.
Sending ROS topic from a Python program †
We will make a Python program to send a ROS topic.
In this time, we do not make a ROS package, but make a stand alone executable (node). So you can put this Python program anywhere (not necessarily to put in ros_ws directory).
Save the following code as ros_min.py:
import roslib; roslib.load_manifest('std_msgs')
import rospy
import std_msgs.msg
import time
if __name__=='__main__':
rospy.init_node('ros_min')
pub_str= rospy.Publisher("/test", std_msgs.msg.String)
i= 0
while not rospy.is_shutdown():
a= (i*(i+1))/2
s= 'ros_min ... %i'%a
print 'saying %r'%s
pub_str.publish(s)
time.sleep(0.5)
i+= 1
Then change the file mode to executable:
$ chmod 755 ros_min.py
Execute:
Terminal-1:
$ roscore
Terminal-2:
$ ./ros_min.py
Terminal-3:
$ rostopic echo /test
In the terminal-2, the Python program is sending a string data, and in the terminal-3, the rostopic command is receiving the data.
Some explanations:
#Import some Python packages for ROS:
import roslib; roslib.load_manifest('std_msgs')
import rospy
#Import a ROS message type to use std_msgs/String.
import std_msgs.msg
#Initialize the node.
rospy.init_node('ros_min')
#Create a publisher that send data of std_msgs/String type to "/test" topic.
pub_str= rospy.Publisher("/test", std_msgs.msg.String)
#Send data s through the publisher pub_str.
pub_str.publish(s)
Receiving ROS topic in a Python program †
We make a Python program that receives a ROS topic by subscribing a topic.
The point is that we need to make a callback function that is executed when the program receives a message from the topic. Then we register the callback function as a subscriber.
Save the following code as ros_sub1.py, and change its mode to executable.
import roslib; roslib.load_manifest('std_msgs')
import rospy
import std_msgs.msg
import time
def Callback(msg):
print 'received:',msg
if __name__=='__main__':
rospy.init_node('ros_sub1')
sub= rospy.Subscriber("/test", std_msgs.msg.String, Callback)
rospy.spin()
We subscribe a topic "/test" which is made by the above program. Our callback function is simple. Just print the received message.
Execute:
Terminal-1:
$ roscore
Terminal-2:
$ ./ros_min.py
Terminal-3:
$ ./ros_sub1.py
Now you will see a communication between the terminal-2 and 3.
Making a ROS service server in a Python program †
We will test a ROS service.
Similarly, create a file named ros_srv1.py with the following contents, and change the mode to executable.
import roslib; roslib.load_manifest('std_srvs')
import rospy
import std_srvs.srv
C= 1
def TestService(req):
global C
print 'Service required',C
C+= 1
return std_srvs.srv.EmptyResponse()
if __name__=='__main__':
rospy.init_node('ros_srv1')
s= rospy.Service('test_srv', std_srvs.srv.Empty, TestService)
rospy.spin()
This program provides a service named "test_srv" with the type std_srvs/Empty (both input and output are empty; void in C/C++ term).
TestService is the function that actually executed.
Execute:
Terminal-1:
$ roscore
Terminal-2:
$ ./ros_srv1.py
Terminal-3:
$ rosservice call test_srv
$ rosservice call test_srv
$ rosservice call test_srv
$ ... (EXECUTE SEVERAL TIMES)
In the terminal-2, you will find "Service required ..." for each "rosservice call test_srv" execution.
Making a ROS service client in a Python program †
Making a service client is simple. Just making a service proxy as a client of the service, and using it like a function.
Save the following code as ros_cli1.py, and change its mode to executable.
import roslib; roslib.load_manifest('std_srvs')
import rospy
import std_srvs.srv
if __name__=='__main__':
rospy.init_node('ros_cli1')
rospy.wait_for_service('test_srv') #Wait until the service is available
srvp= rospy.ServiceProxy('test_srv', std_srvs.srv.Empty) #Making a service proxy
for i in range(5):
srvp() #Calling the service
This program makes a service client to use a service 'test_srv' defined in the previous section.
Execute:
Terminal-1:
$ roscore
Terminal-2:
$ ./ros_srv1.py
Terminal-3:
$ ./ros_cli1.py
In terminal-3, program quits soon after execution. See terminal-2 after that. You will find the result of service execution defined in ros_srv1.py.
For more information †
Read for more complete tutorial: http://wiki.ros.org/ROS/Tutorials
When you want to create your own message types or service types, create a package. My tools (e.g. lfd_trick, etc.) use rosbuild, NOT catkin.
http://wiki.ros.org/ROS/Tutorials/CreatingPackage
In the beginning of CreatingPackage tutorial, there is a switch to select rosbuild or catkin.
To create your own message types or service types:
http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv
There is a switch to select rosbuild or catkin.
More about publisher, subscriber, service server, and service client (there are tutorials of C++ and Python):
- Writing a Simple Publisher and Subscriber (C++)
- Writing a Simple Publisher and Subscriber (Python)
- Examining the Simple Publisher and Subscriber
- Writing a Simple Service and Client (C++)
- Writing a Simple Service and Client (Python)
- Examining the Simple Service and Client
Use roslaunch to execute many nodes at once.