【ROS】ROS2编程示例:服务和客户端-C++版

news/2025/3/16 22:45:04/

1、准备

1)安装ROS2
【ROS】Ubuntu22.04安装ROS2(Humble Hawksbill)

2)ROS2命令
【ROS】ROS2命令行工具详解

3)配置工作空间
【ROS】ROS2中的概念和名词解释中第一节:工作空间 workspace

4)ROS2源码及官方示例:

https://github.com/ros2
https://github.com/ros2/examples

2、编辑

2.1 创建功能包

1)ros2 pkg create

cd ~/ros/src
mkdir laoerExample
cd laoerExample
ros2 pkg create --build-type ament_cmake cSrvCli --dependencies rclcpp example_interfaces

注意:创建功能包时一定要先创建好目录,进入相应的目录后创建,不要使用下面的方法,否则会在编译时报错

cd ~/ros/src
ros2 pkg create --build-type ament_cmake laoerExample/cSrvCli

2)–dependencies
–dependencies将会自动在package.xml和CMakeLists.txt中添加必要的依赖项
例如:–dependencies rclcpp example_interfaces,将会在package.xml中自动添加:

<depend>rclcpp</depend>
<depend>example_interfaces</depend>

CMakeLists.txt中自动添加:

find_package(rclcpp REQUIRED)
find_package(example_interfaces REQUIRED)

3)example_interfaces
example_interfaces功能包是ROS2中自带的功能包,不需要自己创建
功能包目录:/opt/ros/humble/share/example_interfaces
这个博文的示例中将会用到其中的一个服务接口,两个数相加后,将结果返回,接口文件路径及内容如下:

/opt/ros/humble/share/example_interfaces/srv$ cat AddTwoInts.srv 
int64 a
int64 b
---
int64 sum

2.2 编辑源码

2.2.1 服务端

~/ros/src/laoerExample/cSrvCli$ vi srv.cpp
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"#include <memory>/* 求和函数 */
void add(const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> request,std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> response)
{/* 从请求中获取两个整数,并将相加的结果赋值给响应 */response->sum = request->a + request->b;/* RCLCPP_INFO:ROS2自带的log输出,分等级,带颜色,输出格式与printf相同,需要标明数据的类型。*/RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %ld" " b: %ld", request->a, request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%ld]", (long int)response->sum);
}int main(int argc, char **argv)
{/* 初始化ROS2 */rclcpp::init(argc, argv);/* 定义服务端节点add_two_ints_server */std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_server");/* 创建服务名为add_two_ints,服务函数为add的service服务端 */rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtr service =node->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints", &add);/* 通知准备就绪 */RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Ready to add two ints.");/* 运行节点 */rclcpp::spin(node);/* 退出ROS2 */rclcpp::shutdown();
}

2.2.2 客户端

~/ros/src/laoerExample/cSrvCli$ vi cli.cpp
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"#include <chrono>
#include <cstdlib>
#include <memory>using namespace std::chrono_literals;int main(int argc, char **argv)
{/* 初始化ROS2 */rclcpp::init(argc, argv);/* 需要两个命令行参数:x和y */if (argc != 3) {RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "usage: add_two_ints_client X Y");return 1;}/* 定义客户端节点add_two_ints_client */std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_client");/* 创建服务名为add_two_ints的client客户端 */rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client =node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");/* 创建请求request */auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();request->a = atoll(argv[1]);request->b = atoll(argv[2]);/* 搜索服务节点,间隔1s */while (!client->wait_for_service(1s)) {if (!rclcpp::ok()) {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");return 0;}/* 如果找不到,将会继续等待 */RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");}/* 获得应答并显示其状态 */auto result = client->async_send_request(request);// Wait for the result.if (rclcpp::spin_until_future_complete(node, result) ==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sum: %ld", result.get()->sum);} else {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints");}/* 退出ROS2 */rclcpp::shutdown();return 0;
}

2.3 添加依赖配置 package.xml

1)自动添加依赖
在创建功能包时,已经通过参数–dependencies指定了依赖

ros2 pkg create --build-type ament_cmake cSrvCli --dependencies rclcpp example_interfaces

2)手动添加依赖
依赖已自动添加在package.xml中,如果没有则需要手动修改添加即可

<depend>rclcpp</depend>
<depend>example_interfaces</depend>

3)完整的依赖 package.xml 如下:

~/ros/src/laoerExample/cSrvCli$ cat 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>cSrvCli</name><version>0.0.0</version><description>TODO: Package description</description><maintainer email="lesen@todo.todo">lesen</maintainer><license>TODO: License declaration</license><buildtool_depend>ament_cmake</buildtool_depend><depend>rclcpp</depend><depend>example_interfaces</depend><test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend><export><build_type>ament_cmake</build_type></export>
</package>

2.4 修改编译配置

1)依赖相关的编译配置
在创建功能包时,已经通过参数–dependencies指定了依赖,CMakeLists.txt中也会自动添加依赖相关的编译配置,如果没有则手动添加

find_package(rclcpp REQUIRED)
find_package(example_interfaces REQUIRED)

2)添加需要编译的源码文件

add_executable(server src/srv.cpp)
ament_target_dependencies(server rclcpp example_interfaces)add_executable(client src/cli.cpp)
ament_target_dependencies(client rclcpp example_interfaces)

3)生成安装规则

install(TARGETSserverclientDESTINATION lib/${PROJECT_NAME})

4)完整 CMakeLists.txt 内容如下:

~/ros/src/laoerExample/cSrvCli$ cat CMakeLists.txt 
cmake_minimum_required(VERSION 3.8)
project(cSrvCli)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(example_interfaces REQUIRED)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()add_executable(server src/srv.cpp)
ament_target_dependencies(server rclcpp example_interfaces)add_executable(client src/cli.cpp)
ament_target_dependencies(client rclcpp example_interfaces)install(TARGETSserverclientDESTINATION lib/${PROJECT_NAME})ament_package()

3、编译

在工作空间根目录中编译:

cd ~/ros
~/ros$ colcon build

4、运行

在终端1中运行服务端:

~/ros$ source install/setup.sh 
~/ros$ ros2 run  cSrvCli server 

在终端2中运行客户端:

~/ros$ source install/setup.sh 
~/ros$ ros2 run cSrvCli client 123 456
[INFO] [1685671664.664459306] [rclcpp]: Sum: 579

注意:运行客户端时,需要传输两个参数值,否则会报错

[INFO] [1685671646.305281649] [rclcpp]: usage: add_two_ints_client X Y
[ros2run]: Process exited with failure 1

终端2输出打印信息:

[INFO] [1685671664.664459306] [rclcpp]: Sum: 579

终端1输出打印信息:

[INFO] [1685671604.946255679] [rclcpp]: Ready to add two ints.
[INFO] [1685671664.664030229] [rclcpp]: Incoming request
a: 123 b: 456
[INFO] [1685671664.664096508] [rclcpp]: sending back response: [579]

5、测试

1)查看节点信息
在终端3中查看节点信息,运行命令:ros2 node list

~$ ros2 node list 
/add_two_ints_server

对应服务端源码中定义服务节点时:

std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_server");

2)查看服务信息
在终端3中查看话题信息,运行命令:ros2 service list

~$ ros2 service list
/add_two_ints
/add_two_ints_server/describe_parameters
……
/add_two_ints_server/set_parameters_atomically

对应接口定义:

/opt/ros/humble/share/example_interfaces/srv/AddTwoInts.srv

以及服务端和客户端中定义节点时,使用的接口:

node->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints", &add);
node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");
文章来源:https://blog.csdn.net/u010168781/article/details/130999651
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ppmy.cn/news/180945.html

相关文章

图文并茂教你快速入门React系列03-事件

事件 使用 React 可以在 JSX 中添加 事件处理函数。其中事件处理函数为自定义函数&#xff0c;它将在响应交互&#xff08;如点击、悬停、表单输入框获得焦点等&#xff09;时触发。 事件处理 // 这样写&#xff1a;export default function Button() {function handleClic…

科莱特靠不靠谱?学过SAP的人来分享下

我是一七年三月份从科莱特出来的学员&#xff0c;目前就职于北京一家乙方公司快五年了&#xff0c;刚获得了晋升&#xff0c;年薪30w左右&#xff08;还在努力往上升&#xff09;。 当初大学选专业时没有多想&#xff0c;就随便选了个管理专业&#xff0c;进入职场后发现这行不…

科莱特集团三大业务板块

科莱特集团&#xff08;科莱特股份有限公司&#xff09;成立于2014年&#xff0c;以SAP项目实施、项目外包起家&#xff0c;因SAP顾问人才稀缺&#xff0c;服务的500强客户常问我们是否有SAP顾问人才可以推荐&#xff0c;故集团陆续成立科莱特教育事业部和科莱特人力资源公司进…

Arduino测量误差数据的处理——莱特、格拉布斯准则剔除异常数据

我们在用各种测量模块或设备进行测量时&#xff0c;或多或少会受到各种干扰的影响&#xff0c;使得到的数据与真实情况有所偏差&#xff0c;甚至与正确的数值差之千里。通常我们采用统计学的方法来获得相对正确的值&#xff0c;最基本的就是用平均值方法&#xff0c;即将大量数…

什么是特斯拉?他和爱迪生相爱相杀。

01 前言 你听说关于特斯拉的故事是什么&#xff1f;他发明了交流电并为整个世界供电、他与爱迪生关于交直电展开了电流战争、爱迪生在其余生中迫害特斯拉、他想使用特斯拉电塔让全世界可以免费用电、他是一位物理学天才等等。 关于他的故事遍布网络、电视以及电子游戏中。但是…

希尔伯特曲线

希尔伯特曲线 新方案已更新&#xff1a;https://blog.csdn.net/qq_39464369/article/details/90210366 希尔伯特曲线的构造方法&#xff1a; 构造初始形状 把已有图形缩小4倍&#xff08;对应坐标缩小2倍&#xff09;&#xff0c;放在左下角 将缩小图逆时针旋转90度放在右下…

卡莱特led显示屏调试教程_如何使用卡莱特软件点亮LED电子显示屏

如何使用卡莱特软件点亮LED电子显示屏 2020-03-04 3318 如何使用卡莱特软件点亮LED电子显示屏 卡莱特是国内主流的LED显示屏控制软件之一,有接触过LED行业的都知道,LED电子显示屏需要配套的控制系统才能显示和使用。这里主要介绍如何使用卡莱特软件将显示屏点亮。 首先卡莱特…