工具使用-ROS中server、client消息传递

发布 : 2019-06-24 浏览 :

Service Node

教程中的例子,server接收两个整数,求和并返回。在这之前需要创建srv消息类型, 参考工具使用-ROS中创建和配置msg及srv

1
2
roscd beginner_tutorials/srv
vim AddTwoInts.srv

消息内容定义

1
2
3
4
int64 a
int64 b
---
int64 sum

然后定义services

1
2
roscd beginner_tutorials/scripts
vim add_two_ints_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
import rospy
from beginner_tutorials.srv import AddTwoInts

def handle_add_two_ints(req):
print("Returning [%s + %s = %s]"%(req.a, req.b, (req.a+req.b)))
return AddTwoIntsResponse(req.a + req.b) # 下面解释

def add_two_ints_server():
rospy.init_node("add_two_ints_server", anonymous=True)
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
# 发现service的定义和subscriber类似,要接受的请求名为 add_two_ints, 接收消息类型AddTwoInts,回调函数为handle_add_two_ints
print("Ready to add two ints")
rospy.spin() # 同样的保证进程alived, 和Publisher不同,这里不需要不断刷新,只需要等待请求即可

if __name__ == '__main__':
add_two_ints_server()

Client

由于请求-响应 server是一直等待请求的,但是client并不需要循环请求,所以client可以是node,也可以只是一次执行的任务。这里教程定义的是一次执行任务。

1
2
roscd beginner_tutorials/script
vim add_two_ints_client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python
import sys
import rospy
from beginner_tutorials.srv import AddTwoInts

def add_two_ints_client(x, y):
rospy.wait_for_service("add_two_ints") # block代码直到对应的服务可用开始继续执行
try:
# 在当前程序中创建服务的一个代理,或者说句柄
add_two_ints = rospy.ServiceProxy("add_two_ints", AddTwoInts)
#直接像本地一样调用句柄
resp1 = add_two_ints(x, y)
return resp1.sum
except rospy.ServiceException, e:
print("Service call failed: %s"%e)

if __name__=="__main__":
if len(sys.argv) == 3:
x = int(sys.argv[1])
y = int(sys.argv[2])
else:
print usage()
sys.exit(1)
print("Requesting %s + %s"%(x, y))
print("%s + %s = %s"%(x, y, add_two_ints_client(x, y)))

Request和Response

在本地调用服务的句柄时,相当于发送的XXXRequest,XXX表示srv类型,比如AddTwoIntsRequest。而server返回的则是XXXResponse, 如AddTwoIntsResponse。

Building nodes

已经配置好依赖项 message_generationmessage_runtime, 这里需要添加的只是srv文件, 在CMakeLists文件中修改

add_service_files(

​ FILES

​ AddTwoInts.srv

)

然后编译

1
2
cd ~/catkin_ws
catkin_make

运行

1
roscore

新开两个终端,分别执行两个代码

1
rosrun beginner_tutorials add_two_ints_server.py
1
rosrun beginner_tutorials add_two_ints_client.py

输出:

results

思考

教程中,包括很多网上的资料都没提到如果srv返回多个变量该怎么办?

然后对上面的例子

1
2
3
4
5
6
# File: srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum
int64 subtract
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#File: scripts/add_two_ints_server.py
#!/usr/bin/env python

from beginner_tutorials.srv import *
import rospy

def handle_add_two_ints(req):
print("Return [%s + %s = %s]"%(req.a, req.b, (req.a+req.b)))
s1 = req.a+req.b
print("return [%s - %s = %s]"%(req.a, req.b, req.a-req.b))
s2 = req.a - req.b
return AddTwoIntsResponse(s1, s2)

def add_two_ints_server():
rospy.init_node('add_two_ints_server')
s = rospy.Service("add_two_ints", AddTwoInts, handle_add_two_ints)
print("Ready to add two ints")
rospy.spin()


if __name__=="__main__":
add_two_ints_server()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File: scripts/add_two_ints_client.py
#!/usr/bin/env python

import sys
import rospy
from beginner_tutorials.srv import *

def add_two_ints_client(x, y):
rospy.wait_for_service('add_two_ints')
try:
add_two_ints = rospy.ServiceProxy("add_two_ints", AddTwoInts)
resp1 = add_two_ints(x, y)
return resp1.sum, resp1.subtract
except rospy.ServiceException, e:
print("Service call failed: %s"%e)

def usage():
return "%s [x, y]"%sys.argv[0]


if __name__=="__main__":
if len(sys.argv) == 3:
x = int(sys.argv[1])
y = int(sys.argv[2])
else:
print(usage())
sys.exit(1)

print("Requesting %s + %s"%(x, y))
s1, s2 = add_two_ints_client(x, y)
print("%s + %s = %s"%(x, y, s1))
print("%s - %s = %s"%(x, y, s2))

然后重新编译执行:

结果如下:

multi_results

本文作者 : zhouzongwei
原文链接 : http://yoursite.com/2019/06/24/ros-server-client/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

知识 & 情怀 | 赏或者不赏,我都在这,不声不响

微信扫一扫, 以资鼓励

微信扫一扫, 以资鼓励

支付宝扫一扫, 再接再厉

支付宝扫一扫, 再接再厉

留下足迹