ROS开发(五)Service通信编程

实现一个标准服务器消息定义的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,然后分别运行服务端和客户端就可以看到结果了。

本博客采用 知识共享署名-禁止演绎 4.0 国际许可协议 进行许可

本文标题:ROS开发(五)Service通信编程

本文地址:https://jizhong.plus/post/2019/07/ros-service.html