实现一个标准服务器消息定义的print_string服务,服务通信模型如下:
在命令行中输入rossrv show std_srvs/SetBool
命令可以查看标准服务器定义SetBool的结构,结果如下:
bool data
---
bool success
string message
以---
隔开,上面是请求,下面是响应。
接下来笔者用Python代码实现服务端和客户端,代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import rospy
from std_srvs.srv import SetBool, SetBoolResponse
def string_callback(req):
if req.data:
rospy.loginfo("Hello ROS!")
# 反馈数据
return SetBoolResponse(True, "Print Successully")
else:
return SetBoolResponse(False, "Print Failed")
def string_server():
rospy.init_node('string_server')
s = rospy.Service('print_string', SetBool, string_callback)
print 'Ready to print hello string.'
rospy.spin()
if __name__ == '__main__':
string_server()
string_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import rospy
from std_srvs.srv import SetBool, SetBoolRequest
def string_client():
rospy.init_node('string_client')
rospy.wait_for_service('print_string')
try:
string_client = rospy.ServiceProxy('print_string', SetBool)
# 请求服务调用,输入请求数据
response = string_client(True)
return response.success, response.message
except rospy.ServiceException, e:
print "Service call failed: %s" % e
if __name__ == '__main__':
print "Response: [%s] %s" % (string_client())
string_client.py
启动ROS Master后,分别用rosrun
命令运行服务端和客户端就可以看到效果了。
很多时候为满足业务需求,需要自定义srv。如下图:
服务通信模型(服务端/客户端)
在功能包文件夹下面创建srv目录,编写PersonSrv.srv
文件,写入以下内容:
string name
uint8 age
uint8 sex
uint8 unknown = 0
uint8 male = 1
uint8 femal = 2
---
string result
然后在package.xml
中添加依赖:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
最后在CMakeLists.txt
文件中添加编译选项:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
std_srvs
message_generation
)
add_service_files(FILES PersonSrv.srv)
catkin_package(
CATKIN_DEPENDS roscpp rospy std_msgs std_srvs message_runtime
)
回到工作空间根目录,执行catkin_make
编译命令就可以了。生成的Python文件在devel/lib/python2.7/dist-packages/learning_communication/srv/_PersonSrv.py
。
用rossrv show learning_communication/PersonSrv
可以看到如下结构:
uint8 unknown=0
uint8 male=1
uint8 femal=2
string name
uint8 age
uint8 sex
---
string result
接下来编写对应的服务端与客户端代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import rospy
from learning_communication.srv import PersonSrv, PersonSrvResponse
def person_callback(req):
rospy.loginfo("Person: name: %s age:%d sex:%d", req.name, req.age, req.sex)
return PersonSrvResponse("Ok")
def person_server():
rospy.init_node('person_server')
s = rospy.Service('show_person', PersonSrv, person_callback)
print 'Ready to show person info.'
rospy.spin()
if __name__ == '__main__':
person_server()
person_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import rospy
from learning_communication.srv import PersonSrv, PersonSrvRequest
def person_client():
rospy.init_node('person_client')
rospy.wait_for_service('show_person')
try:
person_client = rospy.ServiceProxy('show_person', PersonSrv)
response = person_client('tangjz', 28, PersonSrvRequest.male)
return response.result
except rospy.ServiceException, e:
print "Service call failed: %s" % e
if __name__ == '__main__':
print "Response: [%s]" % (person_client())
person_client.py
最后还是按照老规矩,运行ROS Master,然后分别运行服务端和客户端就可以看到结果了。