zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

ROS入门21讲笔记(七)自定义消息消息类型和使用

消息笔记入门 类型 自定义 21 ros 使用
2023-09-27 14:27:31 时间

这一节主要是学习如何自定义一个服务类型并使用它。

一、如何自定义服务消息?

服务数据是以.srv结尾的文件,是一个用于描述ROS服务信息简单文本文件,用于生成不同语言消息的源代码。srv文件存放在package文件夹下srv文件夹中。

二、自定义服务数据的一般步骤

经过下面四个步骤,返回到workspace目录进行catkin_make,ROS就能根据你的srv文件产生C++需要的源文件定义。

2.1 Step1 创建一个srv文件

srv文件每一行用段类型和段名组成,段类型有:

  • int8, int16, int32, int64 (plus uint*)
  • float32, float64
  • string
  • time, duration
  • other msg files
  • variable-length array[] and fixed-length array[C]

此外,因为服务信息内容由三横线分为上下两部分,分别是请求(request)和回应(response)。如:

int64 A
int64 B
---
int64 Sum

上面A B是请求数据,下面Sum是回应数据,数据类型都是int64。

2.2 Step2 修改package.xml

确保package内package.xml文件以下内容已经被解注释:

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

这是为了保证msg文件能够转换成C+,Python和其他语言的源文件代码,第一行是编译的时候的依赖,第二行是执行时依赖。

2.3 Step3 修改CMakeLists.txt

确保find_package命令存在message_generation模块。

find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
   message_generation
)

确保generate_messages语句已经加入依赖(要在catkin_package前):

generate_messages(
  DEPENDENCIES
  std_msgs
)

确保catkin_package语句已经有了运行时依赖message_runtime

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)

确保add_service_file语句已经增加了想要的srv文件:

add_service_files(
  FILES
  Service1.srv
  Service2.srv
)

CMakeLists.txt一共要进行四处确认find_package generate_messages catkin_packageadd_service_files

三、例子:创建一个服务器使用自定义服务通信数据

在这个例子中,客户端将两个int64数据发送到服务器,服务器对这两个数据求和后返回他们的总和。

3.1 创建srv文件

在package目录创建一个srv文件夹,并创建自己的自定义消息:

mkdir srv
cd srv
touch TwoIntsSum.srv

消息格式如下(TwoIntsSum.srv):

int64 a
int64 b
---
int64 sum

3.2 修改package.xml描述

package.xml添加固定的片段:

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

一个用于编译时信息产生依赖<build_depend>message_generation</build_depend>;
另一个用于执行时信息依赖<exec_depend>message_runtime</exec_depend>
在这里插入图片描述

3.3 修改package的CMakeLists.txt

find_package中增加message_generation
在这里插入图片描述

在generate_messages语句已经加入依赖:(不可以缺少!)

generate_messages(
  DEPENDENCIES
  std_msgs
)

catkin_package命令增加message_runtime
在这里插入图片描述

message_runtime对于msgsrv都有效果,虽然名字叫做message_*

add_service_files命令增加TwoIntsSum.srv
在这里插入图片描述

回到工作空间根目录,使用catkin_make进行编译,如果出现以下打印,说明一切正常:
在这里插入图片描述
此时,ros已经根据你的配置生成了C++编程所需要的头文件了和msg一样放在workspace/devel/include/package/里面:

service_test/
├── TwoIntsSum.h
├── TwoIntsSumRequest.h
└── TwoIntsSumResponse.h

0 directories, 3 files

四、编写客户端和服务端程序

客户端代码程序代码:

#include <ros/ros.h>
#include "service_test/TwoIntsSum.h"

int main(int argc,char**argv)
{
    ros::init(argc,argv,"twoNumberClient");
    ros::NodeHandle n;

    ros::service::waitForService("/sumupTwo");
    ros::ServiceClient client=n.serviceClient<service_test::TwoIntsSum>("/sumupTwo");

    service_test::TwoIntsSum srv;
    srv.request.a=1;
    srv.request.b=2;

    ROS_INFO("Call service to add numbers up request [a:%d,b:%d]",srv.request.a,srv.request.b);
    client.call(srv);

    ROS_INFO("Get result from server ,the sum is : %d",srv.response.sum);

    return 0;
}

服务器程序代码:

#include <ros/ros.h>
#include "service_test/TwoIntsSum.h"

bool Callback(service_test::TwoIntsSum::Request &req,service_test::TwoIntsSum::Response &res)
{
    ROS_INFO("Receieve two number from client a=[%d],b=[%d]",req.a,req.b);

    res.sum=req.a+req.b;

    return true;
    
}

int main(int argc,char ** argv)
{
    ros::init(argc,argv,"Sumserver");
    ros::NodeHandle n;

    ros::ServiceServer server=n.advertiseService("/sumupTwo",Callback);

    ROS_INFO("Server ready");
    ros::spin();

    return 0;
}

OK,最后一步,往这个包对应的CMakeLists.txt中添加:

add_executable(clientGiveTwonum src/clientTwonumber.cpp)
target_link_libraries(clientGiveTwonum ${catkin_LIBRARIES})
add_dependencies(clientGiveTwonum ${PROJECT_NAME}_gencpp)

add_executable(serverCal src/serverSumup.cpp)
target_link_libraries(serverCal ${catkin_LIBRARIES})
add_dependencies(serverCal ${PROJECT_NAME}_gencpp)

注意相比于msg这里多了一个add_dependencies。

回到workspace目录,catkin_make!看到如下情况说明一切顺利:
在这里插入图片描述

你使用sensor.msg,最后会产生一个sensor.h。代码中表现是package::sensor

五、运行起来!

开启第一个终端,用来启动roscore核心:

roscore

这个指令再复习一下:

Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS]
  rosrun will locate PACKAGE and try to find
  an executable named EXECUTABLE in the PACKAGE tree.
  If it finds it, it will run it with ARGS.

第二个终端,启动service_test中的应用serverCal

rosrun service_test serverCal

第三个终端,启动service_test中的应用clientGiveTwonum

rosrun service_test clientGiveTwonum

结果如下:
(客户端)

junwu@Room:~/Desktop/myWS$ rosrun service_test clientGiveTwonum 
[ INFO] [1648649460.485700436]: Call service to add numbers up request [a:1,b:2]
[ INFO] [1648649460.486496542]: Get result from server ,the sum is : 3

(服务端)

junwu@Room:~/Desktop/myWS$ rosrun service_test serverCal 
[ INFO] [1648649458.228923550]: Server ready
[ INFO] [1648649460.486441702]: Receieve two number from client a=[1],b=[2]

[1] https://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv#Common_step_for_msg_and_srv