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

ROS2 通信三大件之动作 -- Action

通信最后一个,也是不太容易理解的方式action,复杂且重要

1、创建action数据结构

创建工作空间和模块就不多说了

在模块  src/action_moudle/action/Counter.action  下创建文件 Counter.action

int32 target  # Goal: 目标 
---
int32 current_value  # Result: 结果
---
int32[] sequence  # Feedback: 中间状态反馈

需要注意的是 这几个值不要搞混,结果和中间状态容易搞错

添加依赖:src/action_moudle/package.xml

  <depend>rclcpp_action</depend> <depend>rosidl_default_generators</depend><depend>rosidl_default_runtime</depend><member_of_group>rosidl_interface_packages</member_of_group>

src/action_moudle/CMakeLists.txt

find_package(rosidl_default_generators REQUIRED)
find_package(rclcpp_action REQUIRED)# 设置消息和服务文件路径
set(action_FILES"action/Counter.action"
)# 添加消息和服务生成目标
rosidl_generate_interfaces(${PROJECT_NAME}${action_FILES}DEPENDENCIES std_msgs
)# 安装 Action 文件
install(DIRECTORY action/DESTINATION share/${PROJECT_NAME}/action
)

编译后生成install/action_moudle/include/action_moudle/action_moudle/action/counter.hpp

c6a140fc2d6a41b99d5792586c679cf9.png

至此action文件生成

2、编写Count计时的Action服务端和客户端代码

AI生成的代码靠不住,改了很多才编译过

src/action_moudle/src/action_server.cpp

#include "rclcpp/rclcpp.hpp"
#include "action_moudle/action/counter.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include <memory>
#include <vector>using Counter = action_moudle::action::Counter;
using namespace std::placeholders;class CounterActionServer : public rclcpp::Node
{
public:CounterActionServer() : Node("counter_action_server"){action_server_ =rclcpp_action::create_server<Counter>(this, "counter", std::bind(&CounterActionServer::handle_goal, this, _1, _2),std::bind(&CounterActionServer::handle_cancel, this, _1), std::bind(&CounterActionServer::handle_accepted, this, _1));}private:rclcpp_action::Server<Counter>::SharedPtr action_server_;rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID& uuid, std::shared_ptr<const Counter::Goal> goal){(void)uuid;RCLCPP_INFO(this->get_logger(), "Received goal request with target: %ld", goal->target);return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;}rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<rclcpp_action::ServerGoalHandle<Counter>> goal_handle){RCLCPP_INFO(this->get_logger(), "Received request to cancel goal");return rclcpp_action::CancelResponse::ACCEPT;}void handle_accepted(const std::shared_ptr<rclcpp_action::ServerGoalHandle<Counter>> goal_handle){using namespace std::placeholders;std::thread{std::bind(&CounterActionServer::execute, this, _1), goal_handle}.detach();}void execute(const std::shared_ptr<rclcpp_action::ServerGoalHandle<Counter>> goal_handle){RCLCPP_INFO(this->get_logger(), "Executing goal");rclcpp::Rate loop_rate(1);const auto   goal     = goal_handle->get_goal();auto         feedback = std::make_shared<Counter::Feedback>();auto         result   = std::make_shared<Counter::Result>();result->current_value = 0;feedback->sequence.push_back(0);if (goal_handle->is_canceling()){goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(), "Goal canceled");return;}goal_handle->publish_feedback(feedback);for (int i = 1; i <= goal->target; ++i){result->current_value = i;feedback->sequence.push_back(i);if (goal_handle->is_canceling()){goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(), "Goal canceled");return;}goal_handle->publish_feedback(feedback);loop_rate.sleep();}goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(), "Returning result");}
};int main(int argc, char* argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<CounterActionServer>());rclcpp::shutdown();return 0;
}

src/action_moudle/src/action_client.cpp

#include "rclcpp/rclcpp.hpp"
#include "action_moudle/action/counter.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include <memory>using Counter = action_moudle::action::Counter;
using namespace std::placeholders;class CounterActionClient : public rclcpp::Node
{
public:CounterActionClient() : Node("counter_action_client"){action_client_ = rclcpp_action::create_client<Counter>(this, "counter");while (!action_client_->wait_for_action_server()){if (!rclcpp::ok()){RCLCPP_ERROR(this->get_logger(), "Interrupted while waiting for the action server. Exiting.");return;}RCLCPP_INFO(this->get_logger(), "Action server not available, waiting again...");}auto goal   = Counter::Goal();goal.target = 10;auto send_goal_options                   = rclcpp_action::Client<Counter>::SendGoalOptions();send_goal_options.goal_response_callback = std::bind(&CounterActionClient::goal_response_callback, this, std::placeholders::_1);send_goal_options.feedback_callback      = std::bind(&CounterActionClient::feedback_callback, this, std::placeholders::_1, std::placeholders::_2);send_goal_options.result_callback        = std::bind(&CounterActionClient::result_callback, this, std::placeholders::_1);action_client_->async_send_goal(goal, send_goal_options);}private:rclcpp_action::Client<Counter>::SharedPtr action_client_;void goal_response_callback(rclcpp_action::ClientGoalHandle<Counter>::SharedPtr goal_handle){if (!goal_handle){RCLCPP_INFO(this->get_logger(), "Goal rejected");}else{RCLCPP_INFO(this->get_logger(), "Goal accepted");}}// void goal_response_callback(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<Counter>>> future)// {//     auto goal_handle = future.get();//     if (!goal_handle)//     {//         RCLCPP_INFO(this->get_logger(), "Goal rejected");//     }//     else//     {//         RCLCPP_INFO(this->get_logger(), "Goal accepted");//     }// }void feedback_callback(std::shared_ptr<rclcpp_action::ClientGoalHandle<Counter>>, const std::shared_ptr<const Counter::Feedback> feedback){// RCLCPP_INFO(this->get_logger(), "Current value: %ld", feedback->current_value);RCLCPP_INFO(this->get_logger(), "Sequence value: %s", print_sequence(feedback->sequence).c_str());}void result_callback(const rclcpp_action::ClientGoalHandle<Counter>::WrappedResult& result){switch (result.code){case rclcpp_action::ResultCode::SUCCEEDED:RCLCPP_INFO(this->get_logger(), "Result: %d", result.result->current_value);break;case rclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(), "Goal was aborted");break;case rclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(), "Goal was canceled");break;default:RCLCPP_ERROR(this->get_logger(), "Unknown result code");break;}rclcpp::shutdown();}std::string print_sequence(const std::vector<int32_t>& sequence){std::stringstream ss;ss << "[";for (size_t i = 0; i < sequence.size(); ++i){if (i > 0){ss << ", ";}ss << sequence[i];}ss << "]";return ss.str();}
};int main(int argc, char* argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<CounterActionClient>());rclcpp::shutdown();return 0;
}

src/action_moudle/CMakeLists.txt  添加

find_package(action_moudle REQUIRED)
find_package(rclcpp_action REQUIRED)# 创建可执行文件
add_executable(action_server src/action_server.cpp)
ament_target_dependencies(action_server rclcpp std_msgs action_moudle rclcpp_action)add_executable(action_client src/action_client.cpp)
ament_target_dependencies(action_client rclcpp std_msgs action_moudle rclcpp_action)# 安装目标
install(TARGETSaction_server action_clientDESTINATION lib/${PROJECT_NAME}
)

3、编译后测试

edaa2982375c40b588702640e4975cf9.png

 

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

相关文章:

  • 大数据治理:构建数据驱动的智能决策体系
  • k8s微服务
  • 【Java】Java 的反射机制(一):反射概述
  • Monorepo pnpm 模式管理多个 web 项目
  • 2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者,看是有点意料之外,其实也在情理之中。
  • 《深入理解 C++策略模式的变体:编程灵活性的新维度》
  • 一起体验AI动手实验,OceanBase 2024 年度发布会精彩预告
  • Download Vmware Fusion (free for person)
  • 【Java数据结构】二叉树
  • 虎牙Android面试题及参考答案
  • C++:错误代码分析<2>
  • 怎么ping网络ip地址通不通
  • 前端新机部署
  • 对比 Babel、SWC 和 Oxc:JavaScript 和 TypeScript 工具的未来
  • MySQL SELECT 查询(三):查询常用函数大全
  • axios 的 get 请求传参数
  • 用C++编写信息管理系统(歌单信息管理)
  • 对层级聚类树进行模块分割,定位基因在哪个模块中
  • 机器学习【金融风险与风口评估及其应用】
  • 【计算机网络 - 基础问题】每日 3 题(三十八)
  • 深入浅出MongoDB(五)
  • 【conda】创建、激活、删除虚拟环境
  • 关于int*的*号归属权问题
  • leetcode---素数,最小质因子,最大公约数
  • 基于stm32的蓝牙模块实验
  • C语言解决TopK问题
  • 磁盘存储链式结构——B树与B+树
  • 如何批量从sql语句中提取表名
  • 怎么把音频的速度调慢?6个方法调节音频速度
  • K8s-services+pod详解1