ROS是机器人操作系统的简称,本文介绍ROS应用开发入门,服务数据的定义和使用。客户端和服务端 之间通讯都使用服务数据(service data)。本文先定义一个服务数据,编译成功后,用一个服务端和一个客户端进行验证,客户端也可以直接用rosservice call,这样客户端不用程序。测试验证先是c++代码,然后是python 代码,你也可选择只看一种你熟悉的。

功能包建立

本文是 ROS 应用开发入门 客户端Client的编程 的继续,如果你在那文建立了功能包,这里就不用了,直接跳过本节。

在 ROS 开发应用准备:创建工作空间 一文中建立了ROS工作空间,现在就建立一个功能包:

cd ~/catkin_ws/src

catkin_create_pkg  learning_service std_msgs roscpp rospy geometry_msgs turtlesim

自定义服务数据

在工程包目录下新建一个目录srv

cd ~/catkin_ws/src/learning_service

mkdir srv

cd srv

然后新建一个Person.srv 文件

nano Person.srv

文件内容为:

string name
uint8  age
uint8  sexuint8 unknown = 0
uint8 male    = 1
uint8 female  = 2---
string result

我们来看看这个文件的特点:

请求数据和响应数据间用  ---  3个横线 - 隔开,上面是请求数据,下面是响应数据。

上面是发送数据,没有赋值的是数据类型,赋值了的可能是枚举类,所以需要输入3个变量 string name, uint8 age, uint8 sex

下面是响应数据,这里只是一个string

回到工程包目录下,打开并编辑package.xml:

cd ~/catkin_ws/src/learning_service

nano package.xml

添加下面2行:

<build_depend>message_generation</build_depend><exec_depend>message_runtime</exec_depend>

添加的位置是参考下面位置,就是<export> 前面注释上面:

 <exec_depend>roscpp</exec_depend><exec_depend>rospy</exec_depend><exec_depend>std_msgs</exec_depend><exec_depend>turtlesim</exec_depend><build_depend>message_generation</build_depend><exec_depend>message_runtime</exec_depend><!-- The export tag contains other, unspecified, tags --><export>

然后打开并编辑CMakeLists.txt,总共3处

nano CMakeLists.txt

先在find_package 里添加 message_generation
添加后如下所示:

find_package(catkin REQUIRED COMPONENTSgeometry_msgsroscpprospystd_msgsturtlesimmessage_generation
)

添加如下代码,也可以作为2行,

add_service_files(FILESPerson.srv
)generate_messages(DEPENDENCIESstd_msgs
)

添加位置参看如下:

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   geometry_msgs#   std_msgs
# )add_service_files(FILESPerson.srv
)generate_messages(DEPENDENCIESstd_msgs
)################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

在catkin_package里,取消   CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim行的注释,并添加 message_runtime
效果如下:

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_topicCATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime
#  DEPENDS system_lib
)

修改完这2个文件后,就在工作空间编译。

编译必须回到 ~/catkin_ws 目录下

cd ~/catkin_ws

catkin_make

如果编译成功,这样服务数据就定义准备好了。

看看编译最后阶段信息

Scanning dependencies of target learning_service_generate_messages_py
[ 40%] Generating Python code from SRV learning_service/Person
[ 45%] Generating Python srv __init__.py for learning_service
[ 45%] Built target turtle_command_server
Scanning dependencies of target learning_service_generate_messages_eus
[ 50%] Generating EusLisp code from learning_service/Person.srv
[ 54%] Generating EusLisp manifest code for learning_service
[ 54%] Built target learning_service_generate_messages_py
Scanning dependencies of target learning_service_generate_messages_nodejs
[ 59%] Generating Javascript code from learning_service/Person.srv
[ 59%] Built target learning_service_generate_messages_nodejs
Scanning dependencies of target learning_service_generate_messages_cpp
[ 63%] Generating C++ code from learning_service/Person.srv
[ 63%] Built target learning_service_generate_messages_cpp
Scanning dependencies of target learning_service_generate_messages_lisp
[ 68%] Generating Lisp code from learning_service/Person.srv
[ 68%] Built target learning_service_generate_messages_lisp
[ 72%] Built target learning_topic_generate_messages_nodejs
[ 77%] Built target learning_topic_generate_messages_cpp
[ 86%] Built target learning_topic_generate_messages_eus
[ 95%] Built target learning_topic_generate_messages_py
[100%] Built target learning_topic_generate_messages_lisp
[100%] Built target learning_topic_generate_messages
[100%] Built target learning_service_generate_messages_eus
Scanning dependencies of target learning_service_generate_messages
[100%] Built target learning_service_generate_messages

看来是为多种语言都准备好了。

c++ 验证源代码

要使用服务数据来验证,需要服务端和客户都2个程序,我们都放在 工程目录的src目录下

转到src 目录下,分别建立文件person_client.cpp和  person_server.cpp.cpp

cd ~/catkin_ws/src/learning_service/src

nano person_client.cpp

文件内容是:

/*** 该例程将请求/show_person服务,服务数据类型learning_service::Person*/#include <ros/ros.h>
#include "learning_service/Person.h"int main(int argc, char** argv)
{// 初始化ROS节点ros::init(argc, argv, "person_client");// 创建节点句柄ros::NodeHandle node;// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的serviceros::service::waitForService("/show_person");ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");// 初始化learning_service::Person的请求数据learning_service::Person srv;srv.request.name = "Tom";srv.request.age  = 20;srv.request.sex  = learning_service::Person::Request::male;// 请求服务调用ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", srv.request.name.c_str(), srv.request.age, srv.request.sex);person_client.call(srv);// 显示服务调用结果ROS_INFO("Show person result : %s", srv.response.result.c_str());return 0;
};

nano person_server.cpp

文件内容是:

/*** 该例程将执行/show_person服务,服务数据类型learning_service::Person*/#include <ros/ros.h>
#include "learning_service/Person.h"// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request  &req,learning_service::Person::Response &res)
{// 显示请求数据ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);// 设置反馈数据res.result = "OK";return true;
}int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "person_server");// 创建节点句柄ros::NodeHandle n;// 创建一个名为/show_person的server,注册回调函数personCallbackros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);// 循环等待回调函数ROS_INFO("Ready to show person informtion.");ros::spin();return 0;
}

2个文件准备好了。

配置cmake文件

在 ~/catkin_ws/src/learning_service/ 目录下,有个CMakeLists.txt 文件,我们需要修改这个文件

cd  ~/catkin_ws/src/learning_service/

nano CMakeLists.txt

在这个文件中添加下面几行,

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

添加的位置是Build段的末尾 参考下面位置,就是 ## install ## 前面,然后上一个客户端,服务端添加各2行的后面:

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )
add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})add_executable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES})add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)#############
## Install ##
#############

保存,退出

这样编译配置就完成了。

编译和运行测试

编译必须回到 ~/catkin_ws 目录下

cd ~/catkin_ws

catkin_make

编译后应该source 一次:

source devel/setup.bash

如果编译有错,就要排除错误,编译好了就运行测试。

打开一个终端,启动ros,执行

roscore

再打开一个终端,启动服务端,执行

rosrun learning_service person_server

再打开一个终端,启动客户端:

rosrun learning_service person_client

其实也可以用rosservice 直接作为客户端进行测试

rosservice call /show_person leon 12 2

或者

leon@ubuntu:~$ rosservice call /show_person "name: 'Leon'
age: 50
sex: 20" 
程序运行结果如下:客户端先执行2次客户端,然后2次rosservice call,再一次客户端

c++ 验证成功。

python 验证源代码

要验证服务数据,需要服务端和客户端2个程序,我们都放在 工程目录的scripts 目录下

转到scripts 目录下,分别建立文件person_client.py 和 person_server.py,没有的话就建立一个(mkdir scripts)。

~/catkin_ws/src/learning_service/scripts

nano person_server.py

文件内容是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-# 该例程将执行/show_person服务,服务数据类型learning_service::Personimport rospy
from learning_service.srv import Person, PersonResponsedef personCallback(req):# 显示请求数据rospy.loginfo("Person: name:%s  age:%d  sex:%d", req.name, req.age, req.sex)# 反馈数据return PersonResponse("OK")def person_server():# ROS节点初始化rospy.init_node('person_server')# 创建一个名为/show_person的server,注册回调函数personCallbacks = rospy.Service('/show_person', Person, personCallback)# 循环等待回调函数print "Ready to show person informtion."rospy.spin()if __name__ == "__main__":person_server()

nano person_client.py

文件内容是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-# 该例程将请求/show_person服务,服务数据类型learning_service::Personimport sys
import rospy
from learning_service.srv import Person, PersonRequestdef person_client():# ROS节点初始化rospy.init_node('person_client')# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/show_person')try:person_client = rospy.ServiceProxy('/show_person', Person)# 请求服务调用,输入请求数据response = person_client("Tom", 20, PersonRequest.male)return response.resultexcept rospy.ServiceException, e:print "Service call failed: %s"%eif __name__ == "__main__":#服务调用并显示调用结果print "Show person result : %s" %(person_client())

运行测试

因为python 不需要编译,但需要设置为可执行文件

chmod +x *.py

打开一个终端,启动ros,执行

roscore

先source 一下:

source ~/catkin_ws/devel/setup.bash

再打开一个终端,启动服务端,执行

rosrun learning_service person_server.py

再打开一个终端,启动客户端:

rosrun learning_service person_client.py

客户端验证也可直接用rosservice call

rosservice call /show_person leon 12 2

或者

leon@ubuntu:~$ rosservice call /show_person "name: 'Leon'
age: 50
sex: 20"

rosservice list 可以列出所有服务名。

程序运行结果如下:

python 验证成功。

rossrv 的使用

rossrv
rossrv is a command-line tool for displaying information about ROS Service types.

Commands:
    rossrv show    Show service description
    rossrv info    Alias for rossrv show
    rossrv list    List all services
    rossrv md5    Display service md5sum
    rossrv package    List services in a package
    rossrv packages    List packages that contain services

Type rossrv <command> -h for more detailed usage

源代码也可以在 https://github.com/huchunxu/ros_21_tutorials 下载

全文介绍到此。

ROS应用开发入门 服务数据的定义和使用相关推荐

  1. ROS入门-13.服务数据的定义与使用

    前面我们已经学习到了spawn和Trigger两种在ROS中已经定义好的服务数据类型的使用方式,当已经定义好的服务数据不能满足我们需求时,就需要根据自己需求来定义一个服务数据的类型并使用 之前在自定义 ...

  2. 【RK3399Pro学习笔记】十一、ROS服务数据的定义与使用

    目录 自定义服务数据 定义srv文件 在package.xml中添加功能包依赖 在CMakeLists.txt添加编译选项 编译生成语言相关文件 使用 C++ 编写程序 person_server.c ...

  3. ROS系统 服务数据的定义与使用

    如何自定义服务数据 定义srv文件 在package.xml中添加功能包依赖 在CMakeLists.txt添加编译选项 编译生成语言相关文件 cd ~/catkin_ws/src/learning_ ...

  4. 【ROS学习笔记】(八)服务数据的定义与使用

    一.目的 Client每Request一次数据请求,Server发送一次数据.数据格式为个人信息,如姓名.性别等. 二.自定义服务数据 此步骤与话题消息的定义与使用过程类似 1. 定义srv文件 再l ...

  5. 微服务应用开发入门④服务网关

    简述 相信通过微服务应用开发入门①web端架构演进的阅读,大家已经知道服务网关是干嘛的: 一般来说服务网关会做以下几件事情: 路由:路由是API网关很核心的模块功能,此模块实现根据请求,锁定目标微服务 ...

  6. 第十三弹 服务数据的定义与使用

    1.服务模型(服务端/客户端) 2.自定义服务数据 2.1定义srv文件 服务是有response的,所以需要上下分割.三个横线以上,是request数据,横线以下,是response数据. 创建一个 ...

  7. 学习笔记(一)-古月ROS机器视觉开发入门 -ROS摄像头驱动及数据接口

    ROS摄像头驱动及数据接口 二维摄像头 我们平常用的最多的就是二维摄像头,大部分笔记本上都会自带一个2d的摄像头,这种摄像头的接口一般是USB接口,市面上看到的罗技摄像头.RGB摄像头等,它们的底层协 ...

  8. 【ROS学习笔记】11.服务数据(srv)的定义与使用

    基于B站ROS公开课:[古月居]古月·ROS入门21讲 基于Ubuntu 20.04.1.Noetic版本 修正错误,并详述Python版本部署 文章目录 1 模型图 2 创建功能包 3 自定义服务数 ...

  9. ROS:服务数据(srv)的定义与使用

    目录 一.服务模型 二.创建功能包 三.自定义服务数据 3.1定义srv文件 3.2在package.xml中添加功能包依赖 3.3在CMakeLists.txt中添加编译选项 3.4编译生成语言相关 ...

最新文章

  1. mySQL Slow Query Log Rotation(慢查询日志轮循设置)
  2. 数据结构-浙大 MOOC 笔记一 基本概念
  3. java求最小步数,使数组值相等的最小步数 Minimum Moves to Equal Array Elements
  4. linux通过SSH连接的SSH加密原理(笔记自用)
  5. 趣谈设计模式 | 适配器模式(Adapter):如何让现存对象适用于新的环境?
  6. python建模分析实操_城市公交站点设置优化模型-基于Python
  7. python alter table_python(pymysql)之mysql简单操作
  8. 开发高级 Web 部件
  9. wps合并所有sheet页_表格高级筛选、表格合并,让表格处理事半功倍
  10. php基础开发(集成环境搭建)
  11. 网站域名备案时需要什么资料
  12. XSS 跨站脚本攻击 的防御解决方案
  13. 青鸟影院售票系统(一)
  14. 微软产品无法通过代理连接互联网解决办法
  15. java生成竖排文字图片_怎么给图片加上竖排文字?
  16. 手机软件测试wifi需要注意哪些问题,WiFi工作原理、测试及生产注意事项
  17. c java多态_浅谈Java多态
  18. Gitlab备份和恢复操作记录
  19. flask爱家租房项目开发(一)
  20. VLAN配置与链路聚合

热门文章

  1. 如何俘获一个 IT 男的心,让他成为男友然后变成老公
  2. CSS复合选择器---后代选择器、子选择器、并集选择器、伪类选择器
  3. 送几个非常nice的软件
  4. 惠普暗影精灵8和惠普暗影精灵7区别
  5. 折叠屏市场起风,华为、OPPO“你追我赶”
  6. 安装 win7虚拟机
  7. 15.9 文本查询程序再探(继承)
  8. 推荐一款在线免费共享云桌面
  9. 中国男人配不上中国女人?
  10. 深入好文:数字经济技能:基于角色的数字技能培养方法、行业趋势、未来及未来的关键角色、这些角色的学习路径