创建简单的服务和客户端

创建服务端和客户端

ROS message(msg与srv介绍)

msg

简介

  • ROS 使用简化的消息描述语言来描述 ROS 节点发布的数据值(又名消息)
  • ROS消息类型,即是ROS话题的格式,可视为ROS的数据类型,基本上是指同一个意思
  • 消息描述存储在ROS包的 msg/ 子目录中的 .msg 文件中
  • msg文件就是简单的文本文件,每行都有一个字段类型和字段名称,用于为不同编程语言编写的消息生成源代码

基本类型

  • int8,,int16, int32, int64 (以及 uint*)
  • float32, float64
  • string
  • time,duration
  • 其他 msg文件
msg类型 C++对应类型 Python对应类型
bool uint8_t bool
int8 int8_t int
int16 int16_t int
int32 int32_t int
int64 int64_t int,long
uint8 uint8_t int
uint16 uint16_t int
uint32 uint32_t int
uint64 uint64_t int,long
float32 float float
float64 float float
string std:string str,bytes
time ros:Time rospy.Time
duration ros::Duration rospy.Duration

srv

简介

  • ROS 使用简化的服务描述语言(“srv”)来描述 ROS 服务类型
  • 服务描述存储在ROS包的 srv/ 子目录中的 .srv 文件中
  • 一个srv文件描述一个服务。它由两部分组成:请求(request)和响应(response),以“---”分隔,上方表示 request数据类型,下面是 response类型

例如

int8 FOO=1
int8 BAR=2
int8 foobar
another_pkg/AnotherMessage msg
---
uint32 SECRET=123456
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer

创建

  • 从另一个包复制现有的srv定义,而不是手动创建新的srv
roscd finaltest
mkdir srv
roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
  • 使用rossrv查看能否识别
rossrv show finaltest/AddTwoInts

配置

package.xml

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

注意,在构建时,其实只需要message_generation,而在运行时,我们只需要message_runtime

CMakeLists.txt

  • 将message_generation加在括号闭合前即可
find_package(catkin REQUIRED COMPONENTS
        std_msgs
        message_generation
)
  • 表示要编译的服务类型文件,生成头文件
add_service_files(
        FILES
        AddTwoInts.srv
        Person.srv
)
  • 添加生成消息的依赖,默认的时候要添加 std_msgs
generate_messages(
        DEPENDENCIES
        std_msgs
)
  • 设置运行依赖
catkin_package(
	CATKIN_DEPENDS message_runtime	
)

编写服务端节点

  • 在finaltest包中创建src/add_two_ints_server.cpp文件
#include <ros/ros.h>
#include "finaltest/AddTwoInts.h"

/**
 * 服务端实现: 解析客户端发送的请求, 并反馈给客户端
 * 1.包含头文件
 * 2.初始化ROS节点
 * 3.创建节点句柄
 * 4.创建服务对象
 * 5.处理请求并反馈
 * 6.spin()
*/

 // service 回调函数,输入参数req,输出参数res
bool add(finaltest::AddTwoInts::Request & req, finaltest::AddTwoInts::Response & res)
{
    res.sum = req.a + req.b;
    ROS_INFO("request: x=%ld, y=%ld", long (req.a), long (req.b));   // 显示请求数据
    ROS_INFO("sending back response: [%ld]", long (res.sum));   // 设置反馈数据
    return true;
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "add_two_ints_server");  // ROS节点初始化
    ros::NodeHandle n;  // 创建节点句柄

    // 创建一个名为 add_two_ints 的 server,注册回调函数 add
    ros::ServiceServer service = n.advertiseService("add_two_ints", add);
    ROS_INFO("Ready to add two ints.");
    ros::spin();  // 循环等待回调函数

    return 0;
}

编写客户端节点

  • 在finaltest包中创建src/add_two_ints_client.cpp文件
#include <ros/ros.h>
#include "finaltest/AddTwoInts.h"
#include <cstdlib>

/**
 * 客户端实现: 提交两个整数, 并处理相应的结果
 * 1.包含头文件
 * 2.初始化ROS节点
 * 3.创建节点句柄
 * 4.创建客户端对象
 * 5.发送请求并接收反馈
*/

int main(int argc, char **argv)
/*
 * argc 是 argument count的缩写,表示传入main函数的参数个数;
 *
 * argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,
 * 并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,
 * 所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;
*/
{
    ros::init(argc, argv, "add_two_ints_client");  // 初始化ROS节点

    if (argc != 3)
    {
      ROS_INFO("usage: add_two_ints_client X Y");
      return 1;
    }

    ros::NodeHandle n;  // 创建节点句柄

    // 为 add_two_ints 服务创建一个客户端,连接名为 add_two_ints 的 service
    ros::ServiceClient client = n.serviceClient<finaltest::AddTwoInts>("add_two_ints");

    // 初始化 finaltest::AddTwoInts 的请求数据
    finaltest::AddTwoInts srv;
    srv.request.a = atoll(argv[1]);
    srv.request.b = atoll(argv[2]);

    // 等待服务启动
    client.waitForExistence();
    // ros::service::waitForService("add_two_ints");

    if (client.call(srv))  // 请求服务调用
    {
      ROS_INFO("Sum: %ld", long (srv.response.sum));
    }
    else
    {
      ROS_ERROR("Failed to call service add_two_ints");
      return 1;
    }
    return 0;
}

配置CMakeLists.txt

  • 添加到CMakeLists.txt文件底部
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server ${PROJECT_NAME}_gencpp)

add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client ${PROJECT_NAME}_gencpp)
posted @ 2021-11-20 13:40  TNTksals  阅读(91)  评论(0编辑  收藏  举报