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

基于B站ROS公开课:【古月居】古月·ROS入门21讲
基于Ubuntu 20.04.1、Noetic版本
修正错误,并详述Python版本部署


前面讲了两个Service模式的例子,分别用到了两种服务数据:turtlesim/Spawn和std_srvs/Trigger。
我们可以使用 rossrv show ...来查看数据结构:
在这里插入图片描述我们可以看到Spawn中的Request部分含坐标信息、朝向角和名称,Response部分含名称。
Trigger中Request部分为空,Response部分含成功Flag、消息内容。

与之前topic种的msg类似,我们也可以用相似的语法自定义服务数据srv
这节我们来自己定义服务数据来满足个性化的需求。
(部分图摘自:b站【古月居】古月·ROS入门21讲)

1 模型图

在第8节我们讲解了话题消息msg的定义与使用,在第8节的例子中我们曾自定义了一个消息类型“Person”以发布个人信息,Publisher发布个人信息,Subscriber接收个人信息。这个例子中,Publisher会不断地发信息,Subscriber不停地接数据,一开动就停不下来了,也是topic模式的缺陷。
本节我们使用Service模式用自定义的服务数据srv来实现,我们希望Request一次才发一次信息来显示。

如图,Client发布显示某个人的信息的Request,通过自定义的服务数据“Person”(learning::Person)来发出去。
Server端收到Request,显示这个人的具体信息,同时发Response向Client反馈显示结果。
ROS Master负责管理节点。

在这里插入图片描述

2 创建功能包

本节还是使用上节创建的 learning_service 包来进行代码存放和编译。

3 自定义服务数据

定义srv文件

我们通过自定义srv文件来自定义服务数据。与之前自定义话题数据msg类似。
我们定义srv文件名为:Person.srv

  1. 在learning_topic的功能包根目录下,新建文件夹 srv
    并创建新文件 Person.srv,创建方法为使用touch命令在当前目录输入:
touch Person.srv

在这里插入图片描述

注意Person的"P"要大写。

  1. 我们把下面代码复制进Person.srv
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2
---
string result

与之前Person.msg不同的是,多了破折号下面这个Response结果,上面的是Request内容。
定义好srv数据接口后,就可以根据这个定义用C++或Python编译。

在package.xml中添加功能包依赖

添加动态生成程序的功能包依赖。
打开package.xml文件,将下面代码拷到文件指定位置:

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

build_depend为编译依赖,这里依赖的是一个会动态产生message的功能包
exer_depend为执行依赖,这里依赖的是一个动态runtime运行的功能包
在这里插入图片描述

在CMakeLists.txt中添加编译选项

为什么要添加编译选项:

  1. 因为在package.xml添加了功能包编译依赖,在CMakeList.txt里的find_package中也要加上对应的部分;
  2. 需要将定义的Person.srv作为消息接口,针对它做编译;
  3. 需要指明编译这个消息接口需要哪些ROS已有的包;
    有了这两个配置才可将定义的srv编译成不同的程序文件
  4. 因为在package.xml添加了功能包执行依赖,在CMakeList.txt里的catkin_package中也要加上对应的部分;

代码,复制到图示位置:

find_package( ...... message_generation)

add_service_files(FILES Person.srv)
generate_messages(DEPENDENCIES std_msgs)

catkin_package( ...... message_runtime)

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

编译生成语言相关文件

以上完成后,到工作空间根目录,编译:

catkin_make

编译完成后,我们可以在 devel/include/learning_topic/ 下找到这个C++的头文件;
也可以在 devel/lib/python3/dist-packages/learning_topic/mrv 下找到Python的包。

4 创建代码并编译运行(C++)

创建代码

我们创建一个Client代码和一个Server代码,通过程序调用生成的头文件。
(源码:https://github.com/guyuehome/ros_21_tutorials/tree/master/learning_service/src)
用红字标示了自己的注解笔记。
在这里插入图片描述在这里插入图片描述
在代码中我们调用了自己编译好的头文件,使用了自定义的Person类和属性。
将代码拷贝到src文件夹下。

编译

先配置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)

第三项是添加依赖项,因为代码涉及到动态生成,我们需要将可执行文件与动态生成的程序产生依赖关系。
注:这里添加的依赖项用到的是gencpp包,是一个C++用的ROS message 和 service 生成器,以依赖动态生成的cpp文件。

在这里插入图片描述

然后编译:

cd ~/catkin_ws
catkin_make

运行

默认已经source,接着运行。

roscore
rosrun learning_service person_server
rosrun learning_service person_client

可以看到运行Server后,启动Client会发一次人物信息,在Server端看到,看到后反馈给Client确认后终止这次发送行为。
先运行Client的话则会一直等待Server端接收,直到Server端启动接收到信息。
在这里插入图片描述

5 创建代码并编译运行(Python)

创建代码

我们创建一个Client代码和一个Server代码,通过程序调用自己编译的py库。
(源码:https://github.com/guyuehome/ros_21_tutorials/tree/master/learning_service/scripts)
用红字标示了自己的注解笔记。绿字是Python3的修正。

在这里插入图片描述在这里插入图片描述
将代码拷贝到scripts文件夹下。
右击py文件→属性,打开执行权限。

编译

配置CMakeLists.txt编译规则
加上一个关于person_server.py和person_client.py的catkin_install_python方法:
下面代码写到指定位置

在这里插入图片描述
然后编译

cd ~/catkin_ws
catkin_make

运行

默认已经source,接着运行。

roscore
rosrun learning_topic person_server.py
rosrun learning_topic person_client.py

可以看到运行Server后,启动Client会发一次人物信息,在Server端看到,看到后反馈给Client确认后终止这次发送行为。
先运行Client的话则会一直等待Server端接收,直到Server端启动接收到信息。
在这里插入图片描述

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
ROS中,使用.msg文件来定义消息类型。具体步骤如下: 1. 在ROS包中创建一个名为msg的文件夹。 2. 在msg文件夹中创建一个名为*.msg的文件,其中*为你所定义的消息类型名称。 3. 在*.msg文件中定义消息类型的字段和类型。例如,定义一个包含字符串和整数字段的消息类型可以写作: ``` string name int32 age ``` 4. 在CMakeLists.txt文件中添加以下代码: ``` add_message_files( FILES *.msg ) generate_messages( DEPENDENCIES std_msgs ) ``` 其中,add_message_files()函数将*.msg文件添加到ROS包中,generate_messages()函数根据*.msg文件生成对应的消息类型代码。 5. 在package.xml文件中添加以下代码: ``` <build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend> ``` 这些代码声明了消息生成器(message_generation)和消息运行时(message_runtime)的依赖项。 6. 编译ROS包。在ROS包的根目录下运行以下命令: ``` catkin_make ``` 编译成功后,将生成一个msg_gen_cpp文件夹,其中包含自动生成的消息类型代码。 7. 在ROS节点中使用定义的消息类型。 在ROS节点中使用定义的消息类型时,需要包含消息类型的头文件,并使用该消息类型的变量进行消息传递。例如,使用上面定义的消息类型可以写作: ``` #include <ros/ros.h> #include <your_package_name/your_message_type_name.h> int main(int argc, char **argv) { ros::init(argc, argv, "your_node_name"); ros::NodeHandle nh; your_package_name::your_message_type_name msg; msg.name = "John"; msg.age = 30; ros::Publisher pub = nh.advertise<your_package_name::your_message_type_name>("your_topic_name", 10); pub.publish(msg); ros::spin(); return 0; } ``` 这个例子中,我们使用了自定义的消息类型your_message_type_name,将消息发布到your_topic_name话题上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值