一个程序包要想称为catkin程序包必须符合以下要求:
每个目录下只能有一个程序包。
最简单的程序包也许看起来就像这样:
· my_package/
· CMakeLists.txt
· package.xml
工作空间示例:
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided bycatkin
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
rosrun turtlesimturtlesim_node __name:=my_turtle
rosnodecleanup
$ rosnode pingmy_turtle
urtlesim_node节点和turtle_teleop_key节点之间是通过一个ROS话题来互相通信的。turtle_teleop_key在一个话题上发布按键输入消息,而turtlesim则订阅该话题以接收该消息。
上图中,红色箭头就表示一个话题,蓝色和绿色表示ros节点,他们通过/turtle1/cmd_vel的话题来通信,这样在键盘上按方向键,消息就发布到话题上了,然后turtle则订阅了这个话题,消息传递给乌龟,乌龟就会移动。
话题之间的通信是通过在节点之间发送ROS消息实现的。对于发布器(turtle_teleop_key)和订阅器(turtulesim_node)之间的通信,发布器和订阅器之间必须发送和接收相同类型的消息。这意味着话题的类型是由发布在它上面的消息类型决定的。使用rostopic type命令可以查看发布在某个话题上的消息类型。
· 消息(msg): msg文件就是一个描述ROS中所使用消息类型的简单文本。它们会被用来生成不同语言的源代码。
· 服务(srv): 一个srv文件描述一项服务。它包含两个部分:请求和响应。
msg文件存放在package的msg目录下,srv文件则存放在srv目录下。
msg文件实际上就是每行声明一个数据类型和变量名。可以使用的数据类型如下:
在ROS中有一个特殊的数据类型:Header,它含有时间戳和坐标系信息。在msg文件的第一行经常可以看到Header header的声明.
下面是一个msg文件的样例,它使用了Header,string,和其他另外两个消息类型。
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
srv文件分为请求和响应两部分,由'---'分隔。下面是srv的一个样例:
int64 A
int64 B
---
int64 Sum
其中 A 和 B 是请求, 而Sum 是响应。
我们认识了很多ros工具,但是很难一下子记住他们,幸运的是,大多数工具都自带帮助。
试试:
$ rosmsg -h
你将看到:
Commands:
rosmsg show Show message description
rosmsg list List all messages
rosmsg md5 Display message md5sum
rosmsg package List messages in a package
rosmsg packages List packages that containmessages
你还可以在子指令中获得帮助:
$ rosmsg show -h
显示:
Usage: rosmsg show[options]
Options:
-h, --help show this help message and exit
-r, --raw show raw message text, including comments
发布器节点和订阅器节点一般在/ROSPACKAGE/scripts中添加,官方例程中在scripts中添加了talk.py和listen.py并将他们都加上可执行文件权限,然后再来编译节点,在工作空间中使用catkin_make。
rosrunbeginner_tutorials talker.py (Python)
使用类似命令执行文件。
服务端和客户端的Python程序也是在scripts文件夹中存放的,并拥有可执行权限,最后需要编译节点。官方教程还可以提供更多程序参考。
新建一个文件夹/bagfiles来记录数据文件。
使用如下命令记录数据:
rosbag record -a
使用该命令查看数据信息:
rosbag info
或者回放该数据信息:
rosbag play
改变回放数据的速率:
rosbag play -r 2
只记录一个单个话题:
rosbag record -Osubset /turtle1/cmd_vel /turtle1/pose
-O选项是让记录的文件名字为subset。
日志等级按以下优先顺序排列:
Fatal
Error
Warn
Info
Debug
Fatal是最高优先级,Debug是最低优先级。通过设置日志等级你可以获取该等级及其以上优先等级的所有日志消息。比如,将日志等级设为Warn时,你会得到Warn、Error和Fatal这三个等级的所有日志消息。
Packages: 软件包,是ROS应用程序代码的组织单元,每个软件包都可以包含程序库、可执行文件、脚本或者其它手动创建的东西。
Manifest (package.xml): 清单,是对于'软件包'相关信息的描述,用于定义软件包相关元信息之间的依赖关系,这些信息包括版本、维护者和许可协议等。
将描述信息修改为任何你喜欢的内容,但是按照约定第一句话应该简短一些,因为它覆盖了程序包的范围。如果用一句话难以描述完全那就需要换行了
这是package.xml中要求填写的一个重要标签,因为它能够让其他人联系到程序包的相关人员。至少需要填写一个维护者名称,但如果有需要的话你可以添加多个。除了在标签里面填写维护者的名称外,还应该在标签的email属性中填写邮箱地址:
你应该选择一种许可协议并将它填写到这里。一些常见的开源许可协议有BSD、MIT、Boost Software License、GPLv2、GPLv3、LGPLv2.1和LGPLv3。你可以在Open SourceInitiative中阅读其中的若干个许可协议的相关信息。对于本教程我们将使用BSD协议,因为ROS核心组件的剩余部分已经使用了该协议:
接下来的标签用来描述程序包的各种依赖项,这些依赖项分为build_depend、buildtool_depend、run_depend、test_depend。关于这些标签的更详细介绍请参考CatkinDependencies相关的文档。在之前的操作中,因为我们将std_msgs、 roscpp、 和 rospy作为catkin_create_pkg命令的参数,所以生成的依赖项看起来如下:
节点,一个节点即为一个可执行文件,它可以通过ROS与其它节点进行通信。
ROS程序包中的一个可执行文件。ROS节点可以使用ROS客户库与其他节点通信。节点可以发布或接收一个话题。节点也可以提供或使用某种服务。
消息,消息是一种ROS数据类型,用于订阅或发布到一个话题。
话题,节点可以发布消息到话题,也可以订阅话题以接收消息。
节点管理器,ROS名称服务 (比如帮助节点找到彼此)。
ROS中相当于stdout/stderr。
主机+ rosout + 参数服务器 (参数服务器会在后面介绍)。
服务(services)是节点之间通讯的另一种方式。服务允许节点发送请求(request) 并获得一个响应(response)
rosservice可以很轻松的使用 ROS 客户端/服务器框架提供的服务。rosservice提供了很多可以在topic上使用的命令,如下所示:
使用方法:
rosservicelist 输出可用服务的信息
rosservicecall 调用带参数的服务
rosservicetype 输出服务类型
rosservicefind 依据类型寻找服务find services by service type
rosservice uri 输出服务的ROSRPC uri
roswtf根据你当前目录来确定需要做的检查,这里表示你是在rosstack中启动roswtf。 * "Static checks summary": 这是有关文件系统问题的检查报告,现在的检查结果表示文件系统没问题。 * "Cannot communicate with master, ignoring graph checks(无法与master连接,忽略图(graph)检查)": roscore没有运行,所以roswtf没有做运行时检查。
当运行了roscore时,在运行roswtf提示:
WARNING Thefollowing node subscriptions are unconnected:
* /rosout:
* /rosout
roswtf发出警告说rosout节点订阅了一个没有节点向其发布的话题。在本例中,这正是所期望看到的,因为除了roscore没有任何其它节点在运行,所以我们可以忽略这些警告。
roswtf会对一些系统中看起来异常但可能是正常的运行情况发出警告。也会对确实有问题的情况报告错误。
rospack允许你获取软件包的有关信息。在本教程中,我们只涉及到rospack中find参数选项,该选项可以返回软件包的路径信息。
rospack find [包名称] 例如:rospack find roscpp
roscd是rosbash命令集中的一部分,它允许你直接切换(cd)工作目录到某个软件包或者软件包集当中
roscd [本地包名称[/子目录]]
注意:roscd只能显示ROS_PACKAGE_PATH环境变量包涵的路径
使用roscd也可以切换到一个软件包或软件包集的子目录中,例如:
roscd roscpp/cmake
或者打开ros保存日记的目录:
roscd log
rospack命令工具还可以用来查看一级依赖包,如下:
rospack depends1beginner_tutorials
输出:
std_msgs
rospy
roscpp
这些依赖包随后保存在package.xml
在很多情况中,一个依赖包还会有它自己的依赖包,比如,rospy还有其它依赖包,如:
rospack depends1rospy
可以看到rospy的依赖包。
一个程序包还可以有好几个间接的依赖包,幸运的是使用rospack可以递归检测出所有的依赖包。
$ rospack dependsbeginner_tutorials
cpp_common
rostime
roscpp_traits
roscpp_serialization
genmsg
genpy
message_runtime
rosconsole
std_msgs
rosgraph_msgs
xmlrpcpp
roscpp
rosgraph
catkin
rospack
roslib
rospy
rosls是rosbash命令集中的一部分,它允许你直接按软件包的名称而不是绝对路径执行ls命令(罗列目录)
rosls [本地包名称[/子目录]]
例如:rosls roscpp_tutorials
这是一个为了创建ros工作空间的方便的工具,他将创建一个 CMakeLists.txt在src文件夹。
catkin_make 实际和下面的指令是等效的
$ cd ~/catkin_ws
$ cd src
$catkin_init_workspace
$ cd ..
$ mkdir build
$ cd build
$ cmake ../src -DCMAKE_INSTALL_PREFIX=../install -DCATKIN_DEVEL_PREFIX=../devel
$ make
所以最先被编译的是那个在src下的公用的CMakeList.txt文件
这个文件的大部分内容都是在找catkin这个包的位置。最后执行一个cmake函数catkin_workspace。这个函数在/opt/ros/kinetic/share/catkin/cmake/catkin_workspace.cmake文件中定义。这个函数对catkin_make执行时的参数进行解析,比如CATKIN_WHITELIST_PACKAGES。然后开始遍历工作空间中的文件夹,如果文件夹中有package.xml文件就将其当作一个软件包。同时对每个软件包调用add_subdirectory。add_subdirectory是一个cmake的内置函数,会调用这个文件夹内的CMakeList.txt文件。这样就开始了每个软件包的编译了。
参考链接: make cmake和catkin_make的区别
catkin_make的时候发生了什么
catkin_create_pkg:创建一个新的catkin程序包
用法:
# This is anexample, do not try to run this
# catkin_create_pkg
显示当前运行的ROS节点信息。rosnode list 指令列出活跃的节点。
你会看到:
/rosout
这表示当前只有一个节点在运行: rosout。因为这个节点用于收集和记录节点调
试输出信息,所以它总是在运行的。
rosnode info 命令返回的是关于一个特定节点的信息。
$ rosnode info/rosout
这给了我们更多的一些有关于rosout的信息。
rosrun 允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。
用法:
rosrun[package_name] [node_name]
例如:运行turtlesim包中的 turtlesim_node
rosrun turtlesim turtlesim_node
rostopic命令工具能让你获取有关ROS话题的信息。
你可以使用帮助选项查看rostopic的子命令:
rostopic -h
显示:
rostopic bw display bandwidth used by topic
rostopic echo print messages to screen
rostopic hz display publishing rate of topic
rostopic list print information about active topics
rostopic pub publish data to topic
rostopic type print topic type
rostopic echo可以显示在某个话题上发布的数据。
用法:
rostopic echo[topic]
让我们在一个新终端中看一下turtle_teleop_key节点在/turtle1/command_velocity话题(非hydro版)上发布的数据。
$ rostopic echo/turtle1/command_velocity
这条命令可以看到节点在话题上发布的命令。当方向键有输入时,就会显示消息。
rostopic list能够列出所有当前订阅和发布的话题。
让我们查看一下list子命令需要的参数,在一个新终端中运行:
$ rostopic list -h
Usage: rostopiclist [/topic]
Options:
-h, --help show this help message and exit
-b BAGFILE, --bag=BAGFILE
list topics in .bagfile
-v, --verbose list full details about each topic
-p list only publishers
-s list only subscribers
在rostopic list中使用verbose选项:
$ rostopic list -v
这会显示出有关所发布和订阅的话题及其类型的详细信息。
Published topics:
* /turtle1/color_sensor [turtlesim/Color] 1publisher
* /turtle1/command_velocity[turtlesim/Velocity] 1 publisher
* /rosout [roslib/Log] 2 publishers
* /rosout_agg [roslib/Log] 1 publisher
* /turtle1/pose [turtlesim/Pose] 1 publisher
Subscribed topics:
* /turtle1/command_velocity[turtlesim/Velocity] 1 subscriber
* /rosout [roslib/Log] 1 subscriber
rostopic type 命令用来查看所发布话题的消息类型。
用法:
rostopic type[topic]
输出:
geometry_msgs/Twist
rostopic pub可以把数据发布到当前某个正在广播的话题上。
用法:
rostopic pub[topic] [msg_type] [args]
示例:
$ rostopic pub -1/turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
以上命令会发送一条消息给turtlesim,告诉它以2.0大小的线速度和1.8大小的角速度开始移动。
这是一个非常复杂的例子,因此让我们来详细分析一下其中的每一个参数
rostopic pub
这条命令将会发布消息到某个给定的话题。
-1
(单个破折号)这个参数选项使rostopic发布一条消息后马上退出。
/turtle1/command_velocity
这是消息所发布到的话题名称。
turtlesim/Velocity
这是所发布消息的类型。
--
(双破折号)这会告诉命令选项解析器接下来的参数部分都不是命令选项。这在参数里面包含有破折号-(比如负号)时是必须要添加的。
2.0 1.8
正如之前提到的,在一个turtlesim/Velocity消息里面包含有两个浮点型元素:linear和angular。在本例中,2.0是linear的值,1.8是angular的值。这些参数其实是按照YAML语法格式编写的,这在YAML文档中有更多的描述。
你可能已经注意到turtle已经停止移动了。这是因为turtle需要一个稳定的频率为1Hz的命令流来保持移动状态。我们可以使用rostopic pub -r命令来发布一个稳定的命令流(非hydro版):
rostopic pub/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0,1.8]'
这条命令以1Hz的频率发布速度命令到速度话题上。
在rqt_graph上也可以看到,rostopic发布器节点(红色)正在与rostopic echo节点(绿色)进行通信。
rostopic hz命令可以用来查看数据发布的频率。
rostopic hz [topic]
我们看一下turtlesim_node发布/turtle/pose时有多快:
rostopic hz/turtle1/pose
rosmsg showgeometry_msgs/Twist
rosmsg命令来查看上述打印出来的消息的详细情况
可以看到:
geometry_msgs/Vector3linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3angular
float64 x
float64 y
float64 z
下面通过rosmsg show命令,检查ROS是否能够识消息。
使用方法:
$ rosmsg show[message type]
样例:
$ rosmsg showbeginner_tutorials/Num
你将会看到:
int64 num
在上边的样例中,消息类型包含两部分:
· beginner_tutorials -- 消息所在的package
· Num -- 消息名Num.
如果你忘记了消息所在的package,你也可以省略掉package名。输入:
$ rosmsg show Num
你将会看到:
· [beginner_tutorials/Num]:
· int64 num
rqt_plot命令可以实时显示一个发布到某个话题上的数据变化图形。这里我们将使用rqt_plot命令来绘制正在发布到/turtle1/pose话题上的数据变化图形。首先,在一个新终端中运行rqt_plot命令:
$ rosrun rqt_plotrqt_plot
这会弹出一个新窗口,在窗口左上角的一个文本框里面你可以添加需要绘制的话题。在里面输入/turtle1/pose/x后之前处于禁用状态的加号按钮将会被使能变亮。按一下该按钮,并对/turtle1/pose/y重复相同的过程。现在你会在图形中看到turtle的x-y位置坐标图。
list 命令显示turtlesim节点提供了9个服务:重置(reset), 清除(clear), 再生(spawn), 终止(kill), turtle1/set_pen, /turtle1/teleport_absolute, /turtle1/teleport_relative, turtlesim/get_loggers,and turtlesim/set_logger_level. 同时还有另外两个rosout节点提供的服务: /rosout/get_loggers and /rosout/set_logger_level.
使用方法:
rosservice type[service]
例如:
rosservice typeclear
提示:(注意,clear要加/)
std_srvs/Empty
服务的类型为空(empty),这表明在调用这个服务是不需要参数(比如,请求不需要发送数据,响应也没有数据)。下面我们使用rosservice call命令调用服务:参看rosservice call
rosservice typespawn| rossrv show
通过查看再生(spawn)服务的信息,我们来了解带参数的服务:
使用方法:
rosservice call[service] [args]
因为服务类型是空,所以进行无参数调用:
rosservice callclear
正如我们所期待的,服务清除了turtlesim_node的背景上的轨迹。
rosservice callspawn 2 2 0.2 ""
这个服务使得我们可以在给定的位置和角度生成一只新的乌龟。名字参数是可选的,这里我们不设具体的名字,让turtlesim自动创建一个。
服务返回了新产生的乌龟的名字:
name: turtle2
rosparam使得我们能够存储并操作ROS 参数服务器(Parameter Server)上的数据。参数服务器能够存储整型、浮点、布尔、字符串、字典和列表等数据类型。rosparam使用YAML标记语言的语法。一般而言,YAML的表述很自然:1 是整型, 1.0是浮点型, one是字符串, true是布尔, [1, 2, 3]是整型列表, {a: b, c: d}是字典. rosparam有很多指令可以用来操作参数,如下所示
rosparam set 设置参数
rosparam get 获取参数
rosparam load 从文件读取参数
rosparam dump 向文件中写入参数
rosparamdelete 删除参数
rosparam list 列出参数名
我们可以看到turtlesim节点在参数服务器上有3个参数用于设定背景颜色:
/background_b
/background_g
/background_r
/roslaunch/uris/aqy:51932
/run_id
Usage:
rosparam set[param_name]
rosparam get[param_name]
现在我们修改背景颜色的红色通道:(后面的需要加/)
$ rosparam setbackground_r 150
上述指令修改了参数的值,现在我们调用清除服务使得修改后的参数生效:
$ rosservice callclear
此时,界面颜色变了:
现在我们来查看参数服务器上的参数值——获取背景的绿色通道的值:
$ rosparam getbackground_g
返回:
86
我们可以使用rosparam get /来显示参数服务器上的所有内容:
$ rosparam get /
background_b: 255
background_g: 86
background_r: 150
roslaunch:
uris: {'aqy:51932': 'http://aqy:51932/'}
run_id:e07ea71e-98df-11de-8875-001b21201aa8
你可能希望存储这些信息以备今后重新读取。这通过rosparam很容易就可以实现:
使用方法:
rosparam dump[file_name]
rosparam load[file_name] [namespace]
现在我们将所有的参数写入params.yaml文件:
$ rosparam dumpparams.yaml
你甚至可以将yaml文件重载入新的命名空间,比如说copy空间:
$ rosparam loadparams.yaml copy
$ rosparam getcopy/background_b
提示:
255
rqt_console属于ROS日志框架(loggingframework)的一部分,用来显示节点的输出信息。rqt_logger_level允许我们修改节点运行时输出信息的日志等级(logger levels)(包括 DEBUG、WARN、INFO和ERROR)。
现在让我们来看一下turtlesim在rqt_console中的输出信息,同时在rqt_logger_level中修改日志等级。在启动turtlesim之前先在另外两个新终端中运行rqt_console和rqt_logger_level:
rosrun rqt_console rqt_console
$ rosrunrqt_logger_level rqt_logger_level
你会看到弹出两个窗口:
现在让我们在一个新终端中启动turtlesim:
rosrun turtlesimturtlesim_node
因为默认日志等级是INFO,所以你会看到turtlesim启动后输出的所有信息,如下图所示:现在让我们刷新一下rqt_logger_level窗口并选择Warn将日志等级修改为WARN,如下图所示:
现在我们让turtle动起来并观察rqt_console中的输出
rostopic pub/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0,0.0]'
接下来我们将使用roslaunch来启动多个turtlesim节点和一个模仿节点以让一个turtlesim节点来模仿另一个turtlesim节点
roslaunch可以用来启动定义在launch文件中的多个节点。
roslaunch [package][filename.launch]
先切换到beginner_tutorials程序包目录下:
roscdbeginner_tutorials
如果roscd执行失败了,记得设置你当前终端下的ROS_PACKAGE_PATH环境变量,设置方法如下:
$ exportROS_PACKAGE_PATH=~/
$ roscdbeginner_tutorials
然后创建一个launch文件夹:
现在我们来创建一个名为turtlemimic.launch的launch文件并复制粘贴以下内容到该文件里面:
<launch>
<groupns="turtlesim1">
<nodepkg="turtlesim"name="sim"type="turtlesim_node"/>
group>
<groupns="turtlesim2">
<nodepkg="turtlesim"name="sim"type="turtlesim_node"/>
group>
<nodepkg="turtlesim"name="mimic"type="mimic">
<remapfrom="input"to="turtlesim1/turtle1"/>
<remapfrom="output"to="turtlesim2/turtle1"/>
node>
launch>
现在我们开始逐句解析launch xml文件。
1<launch>
在这里我们以launch标签开头以表明这是一个launch文件。
3 <groupns="turtlesim1">
4 <nodepkg="turtlesim"name="sim"type="turtlesim_node"/>
5 group>
6
7 <groupns="turtlesim2">
8 <nodepkg="turtlesim"name="sim"type="turtlesim_node"/>
9 group>
在这里我们创建了两个节点分组并以'命名空间(namespace)'标签来区分,其中一个名为turtulesim1,另一个名为turtlesim2,两个组里面都使用相同的turtlesim节点并命名为'sim'。这样可以让我们同时启动两个turtlesim模拟器而不会产生命名冲突。
切换行号显示
11 <nodepkg="turtlesim"name="mimic"type="mimic">
12 <remapfrom="input"to="turtlesim1/turtle1"/>
13 <remapfrom="output"to="turtlesim2/turtle1"/>
14 node>
在这里我们启动模仿节点,并将所有话题的输入和输出分别重命名为turtlesim1和turtlesim2,这样就会使turtlesim2模仿turtlesim1。
切换行号显示
16launch>
这个是launch文件的结束标签。
现在让我们通过roslaunch命令来启动launch文件:
$ roslaunchbeginner_tutorials turtlemimic.launch
现在将会有两个turtlesims被启动,然后我们在一个新终端中使用rostopic命令发送速度设定消息:
$ rostopic pub/turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]''[0.0, 0.0, -1.8]'
你会看到两个turtlesims会同时开始移动,虽然发布命令只是给turtlesim1发送了速度设定消息。
rosed 是 rosbash 的一部分。利用它可以直接通过package名来获取到待编辑的文件而无需指定该文件的存储路径了
rosed[package_name] [filename]
例子:
$ rosed roscppLogger.msg
这个实例展示了如何编辑roscpp package里的Logger.msg文件。
roscp是一个很实用的命令行工具,它实现了将文件从一个package复制到另外一个package的功能。
使用方法:
$ roscp[package_name] [file_to_copy_path] [copy_path]
现在我们可以从rospy_tutorials package中复制一个服务文件了:
roscprospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
还有很关键的一步:我们要确保srv文件被转换成C++,Python和其他语言的源代码。
现在认为,你已经如前边所介绍的,在CMakeLists.txt文件中增加了对message_generation的依赖。:
# Do not just addthis line to your CMakeLists.txt, modify the existing line
find_package(catkinREQUIRED COMPONENTS roscpp rospy std_msgs message_generation)
(对的, message_generation 对msg和srv都起作用)
同样,跟msg文件类似,你也需要在package.xml文件中做一些修改。查看上边的说明,增加额外的依赖项。
删掉#,去除对下边语句的注释:
#add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
用你自己的srv文件名替换掉那些Service*.srv文件:(注意,这里是serverfile)
add_service_files(
FILES
AddTwoInts.srv
)
现在,你可以生成自己的服务源代码了。
Usage:
$ rossrv show
Example:
$ rossrv showbeginner_tutorials/AddTwoInts
You willsee:
int64 a
int64 b
---
int64 sum
Similarto rosmsg, you can find service files like this withoutspecifying package name:
$ rossrv showAddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum
[rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum