[ROS2] --- service

1 service介绍

1.1 service概念

话题通信是基于订阅/发布机制的,无论有没有订阅者,发布者都会周期发布数据,这种模式适合持续数据的收发,比如传感器数据。机器人系统中还有另外一些配置性质的数据,并不需要周期处理,此时就要用到另外一种ROS通信方式——服务(Service)。服务是基于客户端/服务器模型的通信机制,服务器端只在接收到客户端请求时才会提供反馈数据。

1.2 service特点

  • 同一个服务(名称相同)有且只能有一个节点来提供
    在这里插入图片描述

  • 同一个服务可以被多个客户端调用(可以一对一也可一对多)
    在这里插入图片描述

  • 同步通信
    这个过程一般要求越快越好,假设服务器半天没有反应,你的浏览器一直转圈圈,那有可能是服务器宕机了,或者是网络不好,所以相比话题通信,在服务通信中,客户端可以通过接收到的应答信息,判断服务器端的状态,我们也称之为同步通信。

2 自定义通信接口

和话题通信类似,服务通信的核心还是要传递数据,数据变成了两个部分,一个请求的数据,比如请求苹果位置的命令,还有一个反馈的数据,比如反馈苹果坐标位置的数据,这些数据和话题消息一样,在ROS中也是要标准定义的,话题使用.msg文件定义,服务使用的是.srv文件定义。

2.1 新建工作空间

mkdir -p dev_ws/src
cd dev_ws/src
ros2 pkg create custom_interface --build-type ament_cmake

2.2 编写srv接口文件

# 创建srv目录
cd  dev_ws/src/custom_interface
mkdir srv
touch CapitalFullName.srv

CapitalFullName.srv

string name
string surname
---
string capitalfullname

2.3 编译

colcon build

3 service代码实现

上面第二步已经实现了自定义接口,并在install目录生成了对应的头文件,我们下面的代码中可以直接引用这个自定义接口了。

3.1 新建工作空间

前面已经讲解过,这里不再赘述
这里创建工作空间名为learning03_service

3.2 server_node_class.cpp

/*** @file service_node_class.cpp** @brief A basic ROS2 service server node with class implementation that gets two *        strings as request and answer with a capitalized full string as response.*        It's necessary to use the custom message defined in the external*        package "Custom msg and srv"*        To call the service from a terminal use on a single line:*        ros2 service call /create_cap_full_name *        custom_interface/srv/CapitalFullName "{name: x, surname: y}"** @author Antonio Mauro Galiano* Contact: https://www.linkedin.com/in/antoniomaurogaliano/**/#include "rclcpp/rclcpp.hpp"
#include "custom_interface/srv/capital_full_name.hpp"
#include <boost/algorithm/string.hpp>class MyServiceNode : public rclcpp::Node
{
private:rclcpp::Service<custom_interface::srv::CapitalFullName>::SharedPtr service_;void ComposeFullName(const std::shared_ptr<custom_interface::srv::CapitalFullName::Request> request,std::shared_ptr<custom_interface::srv::CapitalFullName::Response> response);public:MyServiceNode(std::string passedNodeName="VOID"): Node(passedNodeName){RCLCPP_INFO(this->get_logger(), "I am ready to capitalize your full name");// like the subscriber class node it's needed the boost::bind to acces the member method // with 2 placeholders to pass request and response to the callbackservice_ = this->create_service<custom_interface::srv::CapitalFullName>("create_cap_full_name", std::bind(&MyServiceNode::ComposeFullName, this, std::placeholders::_1, std::placeholders::_2 ));}};// method to handle the client request and give back a response
// the service gets the name and surname and responses with a capitalized full name
void MyServiceNode::ComposeFullName(const std::shared_ptr<custom_interface::srv::CapitalFullName::Request> request,std::shared_ptr<custom_interface::srv::CapitalFullName::Response> response)
{std::string fullName = request->name + " " + request->surname;std::string capitalFullName = boost::to_upper_copy<std::string>(fullName);response->capitalfullname = capitalFullName;    RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming name: %s" "\tIncoming surname: %s",request->name.c_str(), request->surname.c_str());RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sending back the capitalize full name: [%s]", response->capitalfullname.c_str());
}int main(int argc, char **argv)
{rclcpp::init(argc, argv);auto node = std::make_shared<MyServiceNode>("service_node");rclcpp::spin(node);   // the service starts to wait and manage requestsrclcpp::shutdown();
}

3.3 client_node_class.cpp

/*** @file client_node_class.cpp** @brief A basic ROS2 service client node with class implementation that asks the user *        to input twostrings and gets back a capitalized full string from the server service.*        It's necessary to use the custom message defined in the external *        package "custom_interface"** @author Antonio Mauro Galiano* Contact: https://www.linkedin.com/in/antoniomaurogaliano/**/#include "custom_interface/srv/capital_full_name.hpp"
#include "rclcpp/rclcpp.hpp"using namespace std::chrono_literals;class MyClientNode : public rclcpp::Node
{
private:const std::string name_;const std::string surname_;rclcpp::Client<custom_interface::srv::CapitalFullName>::SharedPtr client_;void ServerResponse();public:MyClientNode(std::string passedNodeName="VOID", std::string passedName="VOID", std::string passedSurname="VOID"): Node(passedNodeName), name_(passedName), surname_(passedSurname){client_ = this->create_client<custom_interface::srv::CapitalFullName>("create_cap_full_name");this->ServerResponse();}};void MyClientNode::ServerResponse()
{auto request =std::make_shared<custom_interface::srv::CapitalFullName::Request>();request->name = name_;request->surname = surname_;std::chrono::seconds myPause = 1s;while (!client_->wait_for_service(1s)) {if (!rclcpp::ok()) {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting.");}RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"SERVICE NOT AVAILABLE, waiting again...");}auto result = client_->async_send_request(request);// note that for the MyClientNode object it's used the get_node_base_interface// to allow the client spinning for a server response// it returns the needed rclcpp::node_interfaces::NodeBaseInterface::SharedPtr if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result) ==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Capitalized full name: %s",result.get()->capitalfullname.c_str());} else{RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Failed to call service create_cap_full_name");}
}int main(int argc, char **argv)
{rclcpp::init(argc, argv);std::string name = "";std::string surname = "";std::cout << "Insert the name -> ";std::cin >> name;std::cout << "Insert the surname -> ";std::cin >> surname;auto node = std::make_shared<MyClientNode>("client_node", name, surname);rclcpp::shutdown();
}

3.4 CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(learning03_service)# Default to C99
if(NOT CMAKE_C_STANDARD)set(CMAKE_C_STANDARD 99)
endif()# Default to C++14
if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)
endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(custom_interface REQUIRED)if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# uncomment the line when a copyright and license is not present in all source files#set(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# uncomment the line when this package is not in a git repo#set(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()# add_executable(service_node src/service_node.cpp)
# ament_target_dependencies(service_node rclcpp custom_interface)# add_executable(client_node src/client_node.cpp)
# ament_target_dependencies(client_node rclcpp custom_interface)add_executable(client_node_class src/client_node_class.cpp)
ament_target_dependencies(client_node_class rclcpp custom_interface)add_executable(service_node_class src/service_node_class.cpp)
ament_target_dependencies(service_node_class rclcpp custom_interface)install(TARGETS#  service_node#  client_nodeclient_node_classservice_node_classDESTINATION lib/${PROJECT_NAME})ament_export_dependencies(rosidl_default_runtime)
ament_package()

3.5 package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3"><name>learning03_service</name><version>0.0.0</version><description>Example nodes to create service server and service client</description><maintainer email="foo@foo.foo">Antonio Mauro Galiano</maintainer><license>TODO: License declaration</license><buildtool_depend>ament_cmake</buildtool_depend><build_depend>rclcpp</build_depend><exec_depend>rclcpp</exec_depend><test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend><depend>custom_interface</depend><export><build_type>ament_cmake</build_type></export>
</package>

4 编译运行

# 编译
colcon build# source环境变量
source install/setup.sh# 运行publisher
ros2 run learning03_service client_node_class# 运行subsriber
ros2 run learning03_service server_node_class

5 service常用指令

# 查看service列表
ros2 service list# 查看所有service类型
ros2 service list -t# 查看service类型
ros2 service type <service_name># 查看同一类型所有在运行的service
ros2 service find <service_type># 查看service内容
ros2 interface show <service_interface>
ros2 interface show <service_name># 调用service
ros2 service call <service_name> <service_type>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/211289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,图算法——以邻接节点表示的图最短路径的迪杰斯特拉(Dijkstra)算法C#程序

1 文本格式 using System; using System.Text; using System.Linq; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { public class Node // : IComparable<Node> { private int vertex, weigh…

【分布式微服务专题】从单体到分布式(一、SpringCloud项目初步升级)

目录 前言阅读对象阅读导航前置知识笔记正文一、单体服务介绍二、服务拆分三、分布式微服务升级前的思考3.1 关于SpringBoot/SpringCloud的思考【有点门槛】 四、SpringCloud升级整合4.1 新建父子项目 学习总结感谢 前言 从本节课开始&#xff0c;我将自己手写一个基于SpringC…

如何轻松恢复 Windows 中删除的文件夹

我们都曾经历过这样的事&#xff0c;而且我们中的大多数人可能很快就会再次这样做。我们讨论的是在 Windows 中按“Delete”或“ShiftDelete”键意外删除重要文件夹的情况。 如果您刚刚按下删除键且未超过 30 天&#xff0c;或者尚未清空回收站&#xff0c;则可以恢复文件夹。…

操作系统学习笔记---内存管理

目录 概念 功能 内存空间的分配和回收 地址转换 逻辑地址&#xff08;相对地址&#xff09; 物理地址&#xff08;绝对地址&#xff09; 内存空间的扩充 内存共享 存储保护 方式 源程序变为可执行程序步骤 链接方式 装入方式 覆盖 交换 连续分配管理方式 单一连…

python安装与工具PyCharm

摘要&#xff1a; 周末闲来无事学习一下python&#xff01;不是你菜鸡&#xff0c;只不过是对手太强了&#xff01;所以你要不断努力&#xff0c;去追求更高的未来&#xff01;下面先了解python与环境的安装与工具的配置&#xff01; python安装&#xff1a; 官网 进入官网下载…

git 关于分支、merge、commit提交

最近开始用git终端提交代码&#xff0c;梳理了一些知识点 一 关于分支 关于分支&#xff0c;git的分支分为本地分支远程分支两种分支&#xff0c;在上传代码时&#xff0c;我们要确保当前本地分支连接了一个远程分支。 我们可以通过下面代码查看当前的本地分支&#xff1a; g…

迅为3588开发板 sudo: 无法解析主机:/DNS配置

环境申明 RK3588 ubuntu 22.04 jammy 迅为开发板 hostname 看是否有Host .&#xff0c;如果没有&#xff0c; sudo vim /etc/hostname在里面加一行&#xff0c;我这就这一个 iTOP-RK3588hosts 修改本地hosts sudo vim /etc/hosts127.0.0.1 localhost localhost iTOP-RK3…

2.postman环境变量及接口关联

一、环境变量以及全局变量 操作流程 1.点击environment 2.点击environment右侧号&#xff0c;新增环境变量 3.在变量中输入变量名以及变量值 4.回到collection页面&#xff0c;修改变量环境 5.在collection中通过{{变量名}}调用变量 变量定义 环境变量&#xff1a;环境变量…

vue 限制在指定容器内可拖拽的div

<template><div class"container" id"container"><div class"drag-box center" v-drag v-if"isShowDrag"><div>无法拖拽出容器的div浮窗</div></div></div> </template><script&g…

P11 Linux进程编程exec族函数

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f6f8;推荐专栏3: ​​​​​​《链表_C…

Java 简易版 UDP 多人聊天室

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

算法通关村第五关—LRU的设计与实现(黄金)

LRU的设计与实现 一、理解LRU的原理 LeetCode146:运用你所掌握的数据结构&#xff0c;设计和实现一个LRU(最近最少使用)缓存机制 实现LRUCache类&#xff1a; LRUCache(int capacity) 以正整数作为容量capacity初始化 LRU 缓存 int get(int key) 如果关键字key存在于缓存中&a…

数据可视化|jupyter notebook运行pyecharts,无法正常显示“可视化图形”,怎么解决?

前言 本文是该专栏的第39篇,后面会持续分享python数据分析的干货知识,记得关注。 相信有些同学在本地使用jupyter notebook运行pyecharts的时候,在代码没有任何异常的情况下,无论是html还是notebook区域,都无法显示“可视化图形”,界面区域只有空白一片。遇到这种情况,…

Nginx服务优化以及防盗链

1. 隐藏版本号 以在 CentOS 中使用命令 curl -I http://192.168.66.10 显示响应报文首部信息。 查看版本号 curl -I http://192.168.66.10 1. 修改配置文件 vim /usr/local/nginx/conf/nginx.conf http {include mime.types;default_type application/octet-stream;…

京东数据运营(京东API接口):10月投影仪店铺数据分析

鲸参谋监测的京东平台10月份投影仪市场销售数据已出炉&#xff01; 10月份&#xff0c;环同比来看&#xff0c;投影仪市场销售均上涨。鲸参谋数据显示&#xff0c;今年10月&#xff0c;京东平台投影仪的销量为16万&#xff0c;环比增长约22%&#xff0c;同比增长约8%&#xff1…

鸿蒙应用开发ArkTS基础组件的使用

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 本文示例代码地址&#xff1a;Gitee 仓库地址 嗨&#xff0c;各位好呀&#xff0c;我是小白 上一篇文章我为大家介绍了如何使用 ArkTS 开发鸿蒙应用&#xff0c;对 HarmonyOS 项…

探索开源游戏的乐趣与无限可能 | 开源专题 No.47

CleverRaven/Cataclysm-DDA Stars: 9.0k License: NOASSERTION Cataclysm&#xff1a;Dark Days Ahead 是一个回合制的生存游戏&#xff0c;设定在一个后启示录世界中。尽管有些人将其描述为 “僵尸游戏”&#xff0c;但 Cataclysm 远不止于此。在这个残酷、持久、程序生成的世…

【原创】【一类问题的通法】【真题+李6卷6+李4卷4(+李6卷5)分析】合同矩阵A B有PTAP=B,求可逆阵P的策略

【铺垫】二次型做的变换与相应二次型矩阵的对应&#xff1a;二次型f&#xff08;x1&#xff0c;x2&#xff0c;x3&#xff09;xTAx&#xff0c;g&#xff08;y1&#xff0c;y2&#xff0c;y3&#xff09;yTBy ①若f在可逆变换xPy下化为g&#xff0c;即P为可逆阵&#xff0c;有P…

数字系统设计(EDA)实验报告【出租车计价器】

一、问题描述 题目九&#xff1a;出租车计价器设计&#xff08;平台实现&#xff09;★★ 完成简易出租车计价器设计&#xff0c;选做停车等待计价功能。 1、基本功能&#xff1a; &#xff08;1&#xff09;起步8元/3km&#xff0c;此后2元/km&#xff1b; &#xff08;2…

红队攻防实战之ThinkPHP-RCE集锦

你若不勇敢&#xff0c;谁又可以替你坚强&#xff1f; ThinkPHP 2.x RCE漏洞 1、查询phpinfo() 2、任意代码执行 3、Getshell 蚁剑连接&#xff1a; ThinkPHP5 5.0.23 RCE漏洞 发送数据包&#xff1a; 成功执行id命令&#xff1a; 工具验证 ThinkPHP5 SQL注入漏洞 &&am…