ROS与Python入门教程-写简单服务端和客户端
ROS与Python入门教程-写简单服务端和客户端
说明
- 这一节介绍如何写服务端和客户端
定义srv服务
- 在beginner_tutorials,新建srv服务目录,新建AddTwoInts.srv文件
$ roscd beginner_tutorials
$ mkdir srv
$ cd srv
$ touch AddTwoInts.srv
$ rosed beginner_tutorials AddTwoInts.srv
- srv文件分为请求和响应两部分,由'---'分隔。手工输入代码:
int64 A
int64 B
---
int64 Sum
- 打开文件
rosed beginner_tutorials package.xml
,增加依赖,
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
- 打开文件
rosed beginner_tutorials CMakeLists.txt
,增加依赖,
# Do not just add this line to your CMakeLists.txt, modify the existing line
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
- 在CMakeLists.txt文件,增加服务文件,取消#,并修改为
add_service_files(
FILES
AddTwoInts.srv
)
- 在CMakeLists.txt文件,增加消息生成包,取消#,并修改为
generate_messages(
DEPENDENCIES
std_msgs
)
- 编译代码
$ cd ~/catkin_ws
$ catkin_make
- 检查服务
- 命令:
$ rossrv show beginner_tutorials/AddTwoInts
- 效果:
int64 a
int64 b
---
int64 sum
编写服务端节点
- 访问代码:
https://github.com/ros/ros_tutorials/blob/kinetic-devel/rospy_tutorials/005_add_two_ints/add_two_ints_server
- 在scripts目录新建add_two_ints_server.py文件
$ roscd beginner_tutorials/scripts
$ touch add_two_ints_server.py
$ chmod +x add_two_ints_server.py
$ rosed beginner_tutorials add_two_ints_server.py
- 手工输入如下代码:
#!/usr/bin/env python
NAME = 'add_two_ints_server'
# import the AddTwoInts service
from beginner_tutorials.srv import *
import rospy
def add_two_ints(req):
print("Returning [%s + %s = %s]" % (req.a, req.b, (req.a + req.b)))
sum = req.a + req.b
return AddTwoIntsResponse(sum)
def add_two_ints_server():
rospy.init_node(NAME)
s = rospy.Service('add_two_ints', AddTwoInts, add_two_ints)
print "Ready to add Two Ints"
# spin() keeps Python from exiting until node is shutdown
rospy.spin()
if __name__ == "__main__":
add_two_ints_server()
- 代码分析
代码:
from beginner_tutorials.srv import *
分析:导入定义的服务
代码:
s = rospy.Service('add_two_ints', AddTwoInts, add_two_ints)
分析:
- 定义服务节点名称,服务的类型,处理函数。
- 处理函数调用实例化的AddTwoIntsRequest接收请求和返回实例化的AddTwoIntsResponse
- 参考rospy.Service API
代码:return AddTwoIntsResponse(sum)
分析:AddTwoIntsResponse由服务生成的返回函数
- 编译代码
$ cd ~/catkin_ws/
$ catkin_make
- 测试代码
- 打开新终端,启动add_two_ints_server.py
$ rosrun beginner_tutorials add_two_ints_server.py
- 打开新终端,列出服务
$ rosservice list
/add_two_ints
/add_two_ints_server/get_loggers
/add_two_ints_server/set_logger_level
/rosout/get_loggers
/rosout/set_logger_level
- 查看服务参数类型
$ rosservice args /add_two_ints
A B
- 调用服务
$ rosservice call /add_two_ints 1 2
sum: 3
- 启动的服务端显示
$ rosrun beginner_tutorials add_two_ints_server.py
Ready to add Two Ints
Returning [1 + 2 = 3]
Returning [1 + 4 = 5]
Returning [1 + 3 = 4]
编写客户端节点
- 访问代码:
https://github.com/ros/ros_tutorials/blob/kinetic-devel/rospy_tutorials/005_add_two_ints/add_two_ints_client
- 在scripts目录新建add_two_ints_client.py文件
$ roscd beginner_tutorials/scripts
$ touch add_two_ints_client.py
$ chmod +x add_two_ints_client.py
$ rosed beginner_tutorials add_two_ints_client.py
- 手工输入如下代码:
#!/usr/bin/env python
import sys
import os
import rospy
# imports the AddTwoInts service
from rospy_tutorials.srv import *
## add two numbers using the add_two_ints service
## @param x int: first number to add
## @param y int: second number to add
def add_two_ints_client(x, y):
# NOTE: you don't have to call rospy.init_node() to make calls against
# a service. This is because service clients do not have to be
# nodes.
# block until the add_two_ints service is available
# you can optionally specify a timeout
rospy.wait_for_service('add_two_ints')
try:
# create a handle to the add_two_ints service
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
print "Requesting %s+%s"%(x, y)
# simplified style
resp1 = add_two_ints(x, y)
# formal style
resp2 = add_two_ints.call(AddTwoIntsRequest(x, y))
if not resp1.sum == (x + y):
raise Exception("test failure, returned sum was %s"%resp1.sum)
if not resp2.sum == (x + y):
raise Exception("test failure, returned sum was %s"%resp2.sum)
return resp1.sum
except rospy.ServiceException, e:
print "Service call failed: %s"%e
def usage():
return "%s [x y]"%sys.argv[0]
if __name__ == "__main__":
argv = rospy.myargv()
if len(argv) == 1:
import random
x = random.randint(-50000, 50000)
y = random.randint(-50000, 50000)
elif len(argv) == 3:
try:
x = int(argv[1])
y = int(argv[2])
except:
print usage()
sys.exit(1)
else:
print usage()
sys.exit(1)
print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))
- 代码分析
代码:
rospy.wait_for_service('add_two_ints')
分析:等待接入服务节点,参考rospy.wait_for_service api
代码:
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
分析:创建服务的处理句柄,参考rospy.ServiceProxy api
- 编译代码
$ cd ~/catkin_ws/
$ catkin_make
- 测试代码
- 命令:
$ rosrun beginner_tutorials add_two_ints_client.py 4 5
- 效果:
Requesting 4+5
4 + 5 = 9
- 服务器输出
Returning [4 + 5 = 9]
制作launch文件
- 进入bringup目录,新建server_client.launch,用来启动add_two_ints_server.py
$ roscd beginner_tutorials/bringup
$ touch server_client.launch
$ rosed beginner_tutorials server_client.launch
- 手工输入如下代码:
<launch>
<node name="server" pkg="beginner_tutorials" type="add_two_ints_server.py" />
</launch>
- 启动server_client.launch
- 命令:
$ roslaunch beginner_tutorials server_client.launch
- 效果:
started roslaunch server http://192.168.0.105:38839/
SUMMARY
========
PARAMETERS
* /rosdistro: indigo
* /rosversion: 1.11.16
NODES
/
service (beginner_tutorials/add_two_ints_server.py)
ROS_MASTER_URI=http://192.168.0.88:11311
core service [/rosout] found
process[service-1]: started with pid [32174]
- 运行客户端节点即可获得结果
$ rosrun beginner_tutorials add_two_ints_client.py 4 5
参考:
- http://wiki.ros.org/rospy/Overview/Services
- http://wiki.ros.org/srv
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号