您现在的位置是:首页 >技术交流 >ros2服务器&客户端实例网站首页技术交流
ros2服务器&客户端实例
简介ros2服务器&客户端实例
简介
1.话题的缺点。
在ros通讯时,话题会按时持续的发送数据,这导致在我们不需要这些数据时发送一些无用数据,而且还消耗电脑资源。
2.服务器的优点
在客户端访问主机前,主机一直在静默,知道客户端请求才发送消息。
实例
1.1创建功能包
//创建example_cpp功能包。(存放实例)
ros2 pkg create example_cpp --build-type ament_cmake --dependencies rclcpp --license Apache-2.0
1.2在src中创建客户端
创建service_client_01.cpp,代码如下还有注释
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"
class ServiceClient01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
ServiceClient01(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "节点已启动:%s.", name.c_str());
// 创建客户端
client_ = this->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints_srv");
}
void send_request(int a, int b)
{
// 打印日志,输出计算a+b
RCLCPP_INFO(this->get_logger(), "计算%d+%d", a, b);
while (!client_->wait_for_service(std::chrono::seconds(1))) // 使用while循环等待服务端上线,每秒检测一次
{
if (!rclcpp::ok()) // 如果rclcpp的状态被打断,则打印错误日志并返回
{
RCLCPP_ERROR(this->get_logger(), "等待服务的过程中被打断...");
return;
}
// 打印日志,输出等待服务端上线中
RCLCPP_INFO(this->get_logger(), "等待服务端上线中");
}
/*
std::make_shared<example_interfaces::srv::AddTwoInts_Request>的变量类型
int64 a
int64 b
---
int64 sum 结果
*/
// 2.构造请求的
//auto关键字用于自动推导变量的类型。编译器会根据右侧表达式的类型自动推断出变量的类型。
auto request = std::make_shared<example_interfaces::srv::AddTwoInts_Request>();//std::make_shared在创建对象时会一次性分配内存,从而避免潜在的内存泄漏问题。
request->a = a;// 设置请求的参数
request->b = b;
// 3. 发送异步请求, 返回时调用回调函数
client_->async_send_request(request, std::bind(&ServiceClient01::result_callback_, this,std::placeholders::_1));
};
private:
// 声明客户端
rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client_;
// 定义一个回调函数,用于处理客户端请求的结果
void result_callback_(rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedFuture result_future)
{
auto response = result_future.get();// 获取共享未来的结果
RCLCPP_INFO(this->get_logger(), "计算结果:%ld", response->sum);//response是一个指针,sum是一个成员变量,存储了计算的结果。
}
};
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<ServiceClient01>("service_client_01");
//增加这一行,node->send_request(5, 6);,计算5+6结果
node->send_request(5, 6);
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
1.3在src中创建服务器
创建service_server_01.cpp
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"
class ServiceServer01 : public rclcpp::Node
{
public:
ServiceServer01(std::string name) : Node(name) {
// 打印节点启动信息
RCLCPP_INFO(this->get_logger(), "节点已启动:%s.", name.c_str());
// 创建服务
add_ints_server_ = this->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints_srv", std::bind(&ServiceServer01::handle_add_two_ints, this, std::placeholders::_1, std::placeholders::_2));
}
private:
// 声明一个服务
rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtr add_ints_server_;
// 处理两个整数的加法请求
void handle_add_two_ints(const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> request, std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> response)
{
RCLCPP_INFO(this->get_logger(), "收到a: %ld b: %ld", request->a,request->b);// 打印收到的a和b的值
response->sum = request->a + request->b;// 将a和b相加的结果赋值给sum
}
};
int main(int argc, char** argv)
{
rclcpp::init(argc, argv);// 初始化ROS2节点
auto node = std::make_shared<ServiceServer01>("service_server_01");// 创建一个ServiceServer01对象,并命名为service_server_01
rclcpp::spin(node);// 进入事件循环,等待回调函数
rclcpp::shutdown();// 关闭ROS2节点
return 0;
}
1.4编辑CMikeLists.txt文件
注意要放到ament_package() 代码段之前
find_package(example_interfaces REQUIRED)
#----------------------service_client_01-----------------------#
add_executable(service_client_01 src/service_client_01.cpp)
ament_target_dependencies(service_client_01 rclcpp example_interfaces)
install(TARGETS
service_client_01
DESTINATION lib/${PROJECT_NAME}
)
#----------------------service_server_01-----------------------#
add_executable(service_server_01 src/service_server_01.cpp)
ament_target_dependencies(service_server_01 rclcpp example_interfaces)
install(TARGETS
service_server_01
DESTINATION lib/${PROJECT_NAME}
)
1.5编辑package.xml文件
注意放到 <depend>rclcpp</depend>下面即可,如果还有依赖也是一样的也是
<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>
编译运行
2.1回到工作空间主目录下编译 colcon build
2.2加载可查询库中
source install/setup.bash #载入当前ros2的文件节点路径
运行
//先运行客户端
ros2 run example_cpp service_client_01
//再运行服务器
ros2 run example_cpp service_server_01
结果
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。