当前位置: 首页 > news >正文

ROS学习之服务通信

根据b站赵老师的视频进行学习,下面给出代码

服务通信,可以用于两个无人车之间的通信。

(补充:动作通信可用于雷达之间的持续通信。

在客户端给出两个数 在服务端输出两个数之和

在前面的准备工作(如,创建工作空间,创建功能包等不再一一给出,详细请参考这一

ROS中话题通信之C++实现-CSDN博客

关于C++的服务端:

#include "rclcpp/rclcpp.hpp"
#include "base_interfaces/srv/addints.hpp"//using namespace std::chrono_literals;
using base_interfaces::srv::Addints;
using std::placeholders::_1;
using std::placeholders::_2;class AddintsServer: public rclcpp::Node{
public:AddintsServer():Node("add_ints_server_node_cpp"){RCLCPP_INFO(this->get_logger(),"server create!");server_ = this->create_service<Addints>("add_ints",std::bind(&AddintsServer::add,this,_1,_2));//创建服务端// use: ros2 topic echo /chatter 检测接收方 是否接受到//timer_ = this->create_wall_timer(1s,std::bind(&AddintsServer::on_timer,this));}
private:
//创建回调函数void add(const Addints::Request::SharedPtr req, const Addints::Response::SharedPtr res){res->sum = req->num1 + req->num2;RCLCPP_INFO(this->get_logger(),"%d + %d = %d",req->num1,req->num2,res->sum);}rclcpp::Service<Addints>::SharedPtr server_;//rclcpp::TimerBase::SharedPtr timer_;//size_t count;
};
int main(int argc, char ** argv)
{rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<AddintsServer>());rclcpp::shutdown();return 0;
}

关于C++的客户端:

// listen 订阅发布的消息 并且在终端输出
// 1、包含头文件 2、初始化客户端 3、自定义节点类 4、调用spin函数 并且传入节点指针 5、支援释放
// 3.1、创建订约方 3、2 解释并且输出数据
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces/srv/addints.hpp"using base_interfaces::srv::Addints;
using namespace std::chrono_literals;
class AddintsClient: public rclcpp::Node{
public:AddintsClient():Node("add_ints_client_node_cpp"){RCLCPP_INFO(this->get_logger(),"client create!");//subscription_ = this->create_subscription<std_msgs::msg::String>("chatter",10,std::bind(&AddintsClient::do_cb,this,std::placeholders::_1));client_ = this->create_client<Addints>("add_ints");}bool connect_server(){// 在1s内 连接服务器 链接上返回true 否着 False//client_->wait_for_service(1s);while (!client_->wait_for_service(1s)){if (!rclcpp::ok())// 针对crtl+c 的特殊处理{RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Connect false in force...");return false;/* code */}RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Connecting...");/* code */}return true;}rclcpp::Client<Addints>::FutureAndRequestId send_request(int num1,int num2){auto request = std::make_shared<Addints::Request>();request->num1 = num1;request->num2 = num2;return client_->async_send_request(request);}
private:rclcpp::Client<Addints>::SharedPtr client_;//rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char const *argv[])
{if(argc != 3){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"give:num1 and num2");return 1;}rclcpp::init(argc,argv);//rclcpp::spin(std::make_shared<AddintsClient>());auto client = std::make_shared<AddintsClient>();bool flag = client->connect_server();if (!flag){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"false connect!");return 0;/* code */}auto future = client->send_request(atoi(argv[1]),atoi(argv[2]));if (rclcpp::spin_until_future_complete(client,future) == rclcpp::FutureReturnCode::SUCCESS){/* code */RCLCPP_INFO(client->get_logger(),"success!sum = %d",future.get()->sum);}else{RCLCPP_INFO(client->get_logger(),"False");}rclcpp::shutdown();/* code */return 0;
}

相关的Cmakelist修改:

cmake_minimum_required(VERSION 3.8)
project(cpp02_service)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(base_interfaces REQUIRED)add_executable(demo01_server src/demo01_server.cpp)
add_executable(demo02_client src/demo02_client.cpp)
target_include_directories(demo01_server PUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)
target_compile_features(demo01_server PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
ament_target_dependencies(demo01_server"rclcpp""base_interfaces"
)ament_target_dependencies(demo02_client"rclcpp""base_interfaces"
)install(TARGETS demo01_serverDESTINATION lib/${PROJECT_NAME})install(TARGETS demo02_clientDESTINATION lib/${PROJECT_NAME})if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()

结果如下:

下面给出Python相关代码:

import rclpy
from rclpy.node import Node
from base_interfaces.srv import Addintsclass Addintsserver(Node):def __init__(self):super().__init__("add_ints_server_node_py")self.get_logger().info("server create!(py)")self.server = self.create_service(Addints,"add_ints",self.add)def add(self,request,response):response.sum = request.num1 + request.num2self.get_logger().info("%d + %d = %d" % (request.num1,request.num2,response.sum))return responsedef main():rclpy.init()rclpy.spin(Addintsserver())rclpy.shutdown()if __name__ == '__main__':main()

客户端:

import rclpy
import sys
from rclpy.logging import get_logger
from rclpy.node import Node
from base_interfaces.srv import Addintsclass Addintsclient(Node):def __init__(self):super().__init__("add_ints_client_node_py")self.get_logger().info("client create!(py)")self.client = self.create_client(Addints,"add_ints")while not self.client.wait_for_service(1.0):self.get_logger().info("COnnetcing...")def send_request(self):request = Addints.Request()request.num1 = int(sys.argv[1])request.num2 = int(sys.argv[2])self.future = self.client.call_async(request)def main():if len(sys.argv) != 3:get_logger("rclpy").info("Need two nums")returnrclpy.init()client = Addintsclient()client.send_request()rclpy.spin_until_future_complete(client,client.future)try:response = client.future.result()client.get_logger().info("result: sum = %d" % response.sum)except Exception:client.get_logger().error("client fail")rclpy.shutdown()if __name__ == '__main__':main()

需要对setup.py进行修改:

from setuptools import find_packages, setuppackage_name = 'py02_service'setup(name=package_name,version='0.0.0',packages=find_packages(exclude=['test']),data_files=[('share/ament_index/resource_index/packages',['resource/' + package_name]),('share/' + package_name, ['package.xml']),],install_requires=['setuptools'],zip_safe=True,maintainer='xwh',maintainer_email='xwh@todo.todo',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts': ['demo01_server_py = py02_service.demo01_server_py:main','demo02_client_py = py02_service.demo02_client_py:main'],},
)

运行后的结果,与C++的相同。

本篇与ROS学习之动作通信-CSDN博客这一篇是一起学习的,上传的程序代码包含了话题、服务、动作通信。

http://www.lryc.cn/news/572510.html

相关文章:

  • flink的多种部署模式
  • 【LLM学习笔记3】搭建基于chatgpt的问答系统(下)
  • 面试-操作系统
  • 【Dify 沙箱网络问题排查与解决】
  • 工程师生活:清除电热水壶(锅)水垢方法
  • 3DTiles三维模型
  • Python-循环结构解析
  • windows 11 安装和配置 WSL #1 Ubuntu
  • 30.all和any
  • 动态规划:01 背包(闫氏DP分析法)
  • python脚本间的相互调用
  • 磐基PaaS平台MongoDB组件SSPL许可证风险与合规性分析(上)
  • Git(三):分支管理
  • 达梦数据库锁超时问题
  • 使用Dagster资产工厂模式高效管理重复ETL任务
  • 识别网络延迟与带宽瓶颈
  • M1芯片macOS安装Xinference部署大模型
  • Datawhale 网络爬虫技术入门第2次笔记
  • QT6与VS下实现没有CMD窗口的C++控制台程序
  • 日本生活:日语语言学校-日语作文-沟通无国界(3)-题目:わたしの友達
  • 编程马拉松的定义、运作与发展
  • C语言标准I/O库详解:文件操作与缓冲区机制
  • Qt蓝图式技能编辑器状态机模块设计与实现
  • html实现登录与注册功能案例(不写死且只使用js)
  • 深入解析select模型:FD_SET机制与1024限制的终极指南
  • Linux系统远程操作和程序编译
  • 23.ssr和csr的对比?如何依赖node.js实现
  • [11-5]硬件SPI读写W25Q64 江协科技学习笔记(20个知识点)
  • 嵌入式编译工具链熟悉与游戏移植
  • 基于C#的Baumer相机二次开发教程