当前位置: 首页 > 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.xdnf.cn/news/1060885.html

相关文章:

  • 2025虚幻引擎文件与文件夹命名规律
  • Tensorflow C++ API从入门到放弃
  • STUN (Session Traversal Utilities for NAT) 服务器是一种网络协议
  • MySQL八股文
  • AIGC - Prompt Optimizer 提示词优化器
  • 编程马拉松的定义、运作与发展
  • 解锁微服务潜能:深入浅出 Nacos
  • S32DS上进行S32K328的时钟配置,LPUART时钟配置步骤详解
  • SSH服务与rsync服务配置实战
  • FPGA基础 -- Verilog 概率分布函数
  • Stable Diffusion 实战-手机壁纸制作 第二篇:优化那些“崩脸”和“马赛克”问题,让图像更加完美!
  • 【LLM学习笔记3】搭建基于chatgpt的问答系统(下)
  • AJAX拦截器失效排查指南:当你的beforeSend有效但error/complete沉默时
  • CppCon 2017 学习:Everything You Ever Wanted to Know about DLLs
  • API 接口:程序世界的通用语言与交互基因
  • Spring Boot 虚拟线程 vs WebFlux:谁更胜一筹?
  • 主流防火墙策略绕过漏洞的修复方案与加固实践
  • 啊啊啊啊啊啊啊啊code
  • C++实现手写strlen函数
  • 什么是池化
  • [11-5]硬件SPI读写W25Q64 江协科技学习笔记(20个知识点)
  • Java求职者面试指南:Spring, Spring Boot, Spring MVC, MyBatis技术点深度解析
  • RK3568笔记八十五:LVGL播放AVI视频
  • MySQL读写分离技术详解:架构设计与实践指南
  • 不同系统修改 Docker Desktop 存储路径(从C盘修改到D盘)
  • 【AI论文】SWE-Factory:您的自动化工厂,提供问题解决培训数据和评估基准
  • PHP 生成当月日期
  • JavaEE->多线程2
  • 介绍一款免费MES、开源MES系统、MES源码
  • uni.getStorage 与 uni.getStorageSync 的区别解析