当前位置: 首页 > 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

 

相关文章:

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

通信最后一个&#xff0c;也是不太容易理解的方式action&#xff0c;复杂且重要 1、创建action数据结构 创建工作空间和模块就不多说了 在模块 src/action_moudle/action/Counter.action 下创建文件 Counter.action int32 target # Goal: 目标 --- int32 current_value…...

大数据治理:构建数据驱动的智能决策体系

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

k8s微服务

一 、什么是微服务 用控制器来完成集群的工作负载&#xff0c;那么应用如何暴漏出去&#xff1f;需要通过微服务暴漏出去后才能被访问 Service是一组提供相同服务的Pod对外开放的接口。 借助Service&#xff0c;应用可以实现服务发现和负载均衡。 service默认只支持4层负载均…...

【Java】Java 的反射机制(一):反射概述

Java 的反射机制&#xff08;一&#xff09;&#xff1a;反射概述 1.反射概述1.1 静态语言 / 动态语言1.1.1 动态语言1.1.2 静态语言 1.2 Java Reflection1.3 Java 反射机制提供的功能1.4 反射的优点和缺陷1.5 反射相关的主要 API1.6 代码示例 2.Class 类2.1 什么是 Class 类2.…...

Monorepo pnpm 模式管理多个 web 项目

Monorepo pnpm 模式管理多个 web 项目 Monorepo pnpm 模式管理多个 web 项目项目地址git flow 工作流程pnpm workspace.npmrc初始化项目架构引入Husky规范git提交配置eslint和prettiereslint 配置prettier 配置 配置lint-staged创建项目创建shared项目全局安装 vue在 packages …...

2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者,看是有点意料之外,其实也在情理之中。

近日&#xff0c;2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者&#xff0c;这是历史上首次出现这样的情况。这项奖项原本只授予对自然现象和物质的物理学研究作出重大贡献的科学家&#xff0c;如今却将全球范围内对机器学习和神经网络的研究和开发作为了一种能…...

《深入理解 C++策略模式的变体:编程灵活性的新维度》

在 C编程的广阔领域中&#xff0c;设计模式起着至关重要的作用&#xff0c;它们为软件架构提供了可复用的解决方案。其中&#xff0c;策略模式是一种非常强大的设计模式&#xff0c;它允许算法的行为在运行时根据不同的策略进行改变。而策略模式的变体则进一步扩展了其灵活性和…...

一起体验AI动手实验,OceanBase 2024 年度发布会精彩预告

2024年OceanBase年度发布会将于10月23日在北京望京凯悦酒店举行。此次大会围绕“不止于记录”的主题&#xff0c;共同探讨当前数据库领域的前沿话题&#xff0c;包含主论坛、分论坛、AI 动手实训营、开源技术交流会等多个环节&#xff0c;诚邀全国各地的企业和开发者共同参与&a…...

Download Vmware Fusion (free for person)

1. web link ProductFiles - Support Portal - Broadcom support portal 2. Register user (Required) use your email to register a account 3. login and download note: the username is the email name....

【Java数据结构】二叉树

【本节目标】 1. 掌握树的基本概念 2. 掌握二叉树概念及特性 3. 掌握二叉树的基本操作 4. 完成二叉树相关的面试题练习 一. 树型结构 1 概念★ 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集…...

虎牙Android面试题及参考答案

给个数组,找出数组中第 k 大的数(利用快排思想 / 用小顶堆,他说可以用大顶堆?) 利用快排思想:快速排序的核心思想是分治和分区。在找数组中第 k 大的数时,每次选择一个基准元素,将数组分为两部分,左边部分小于基准元素,右边部分大于基准元素。如果基准元素最终的下标…...

C++:错误代码分析<2>

&#x1f30f;主页&#xff1a;R6bandito_ &#x1f680;所属专栏&#xff1a;C/C错误代码收集整理 源码 考虑以下代码&#xff1a; void do_some_work() {std::cout << "Do some work" << std::endl; }int main(int argc, const char* argv[]) {std::…...

怎么ping网络ip地址通不通

怎么Ping网络IP地址通不通&#xff1f;要检查网络中的IP地址是否连通&#xff0c;可以使用‌Ping命令。Ping命令通过发送ICMP&#xff08;Internet Control Message Protocol&#xff0c;因特网控制消息协议&#xff09;Echo请求报文并等待回应&#xff0c;来判断目标主机是否可…...

前端新机部署

编辑器&#xff1a;vscode 下载地址 vscode常用插件 显示代码修改历史、作者等信息 GitLens Nodejs版本 Node版本管理工具 Nvm下载地址 nvm常用命令&#xff1a; nvm ls // 查看安装的所有node.js的版本nvm list available //查看可以安装的所有node.js版本nvm install 版本…...

对比 Babel、SWC 和 Oxc:JavaScript 和 TypeScript 工具的未来

随着现代前端开发的快速演变&#xff0c;JavaScript 和 TypeScript 的工具链不断更新&#xff0c;以满足开发者对性能和效率的需求。我们将对比三款流行的工具&#xff1a;Babel、SWC 和 Oxc&#xff0c;重点分析它们的特点、性能、应用场景以及适用性。 1. Babel&#xff1a;…...

MySQL SELECT 查询(三):查询常用函数大全

MySQL SELECT 查询&#xff08;三&#xff09;&#xff1a;查询常用函数大全 1. 单行函数 单行函数是 SQL 中一类重要的函数&#xff0c;它们可以对单行数据进行处理&#xff0c;并返回单个结果。单行函数可以嵌套使用&#xff0c;并提供灵活的数据处理能力。 1.1 定义 只对单…...

axios 的 get 请求传参数

在使用 Axios 发起 GET 请求时&#xff0c;参数通常是通过 URL 的查询字符串来传递的。Axios 提供了一个简洁的接口来构建这样的请求&#xff0c;并自动将参数附加到 URL 上。 以下是一个使用 Axios 发起 GET 请求并传递参数的示例&#xff1a; const axios require(axios);…...

用C++编写信息管理系统(歌单信息管理)

C语言是面向过程的编程语言&#xff0c;而C是面向对象的编程语言&#xff0c;在书写代码时风格有所不同&#xff08;也存在很多共性&#xff09;。 程序说明 本次系统程序使用的是C语言进行编写&#xff0c;主要考虑怎么实现面向对象的问题。 因为本次程序属于小型系统程序&…...

对层级聚类树进行模块分割,定位基因在哪个模块中

拷贝数据到 ImageGP (http://www.ehbio.com/Cloud_Platform/front/#/analysis?pageb%27Ng%3D%3D%27)&#xff0c;并设置参数. ID untrt_N61311 untrt_N052611 untrt_N080611 untrt_N061011 trt_N61311 trt_N052611 trt_N080611 trt_N061011 ENSG000…...

机器学习【金融风险与风口评估及其应用】

机器学习【金融风险与风口评估及其应用】 一、机器学习在金融风险评估中的应用1.提升评估准确性2.实现自动化和智能化3.增强风险管理能力4.信用评估5.风险模型6.交易策略7.欺诈检测 二、机器学习在金融风口评估中的应用1.识别市场趋势2.评估创新潜力3.优化投资策略4. 自然语言处…...

SWF逆向工程行业报告:JPEXS Free Flash Decompiler市场份额2025深度分析

SWF逆向工程行业报告&#xff1a;JPEXS Free Flash Decompiler市场份额2025深度分析 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler 在Flash技术逐渐退出主流但仍有大量历史资产需要维护…...

2026 年直播电商如何进化?内容创作与管理的新模式是什么?

核心要点 问题&#xff1a; 为什么很多直播电商团队在 2025 年后明显感到"内容越来越多&#xff0c;但效果越来越不稳定"&#xff1f; 答案&#xff1a; 进入 2026 年&#xff0c;直播电商从"单场爆发"转向"内容体系竞争"。真正拉开差距的&#…...

保姆级教程:在OrangePi 5 Plus上从SSD启动Ubuntu 22.04,并配置ROS2 Humble环境

OrangePi 5 Plus开发板全栈配置指南&#xff1a;从SSD启动到ROS2 Humble环境搭建 拿到一块OrangePi 5 Plus开发板时&#xff0c;如何快速搭建一个稳定高效的开发环境&#xff1f;本文将手把手带你完成从系统烧录到ROS2环境配置的全过程&#xff0c;特别针对ARM64架构的优化方案…...

5分钟搞定OpenClaw+GLM-4.7-Flash:星图平台一键部署体验

5分钟搞定OpenClawGLM-4.7-Flash&#xff1a;星图平台一键部署体验 1. 为什么选择云端部署OpenClaw 作为一个长期折腾本地AI部署的技术爱好者&#xff0c;我深知在个人电脑上配置OpenClaw的痛处。从Node.js版本冲突到模型权重下载失败&#xff0c;再到各种依赖库缺失&#xf…...

从Shadertoy到Cesium:那些GLSL移植时没人告诉你的分辨率陷阱

GLSL跨平台移植中的分辨率适配陷阱与实战解决方案 当我们将Shadertoy上令人惊艳的GLSL效果移植到Cesium等三维引擎时&#xff0c;往往会遇到一个看似简单却影响深远的问题——分辨率适配。这个问题不仅关乎视觉效果还原度&#xff0c;更直接影响着色器在不同设备上的表现一致性…...

从零开始:如何为你的深度学习项目选择最合适的开源数据集

从零开始&#xff1a;如何为你的深度学习项目选择最合适的开源数据集 当你站在深度学习项目的起点&#xff0c;面对琳琅满目的开源数据集时&#xff0c;如何做出明智的选择往往决定了项目的成败。数据集不仅是模型训练的"原材料"&#xff0c;更是影响最终性能的关键变…...

智慧生鲜配送:揭秘生鲜配送商城APP功能版块设计

在数字化消费浪潮中&#xff0c;生鲜配送商城APP成为居民采购食材的重要渠道。其功能版块设计聚焦用户需求&#xff0c;通过智能化、便捷化的操作体验&#xff0c;打造高效生鲜购物场景。以下揭秘其核心功能玩法&#xff0c;解析如何实现“从指尖到餐桌”的流畅服务。一、首页&…...

快马平台快速原型:十分钟用AI生成你的第一个龙虾养殖系统Docker部署方案

最近在研究如何用Docker快速搭建一个龙虾养殖模拟系统&#xff0c;发现用InsCode(快马)平台可以大大简化这个过程。作为一个快速原型验证工具&#xff0c;它让我在十分钟内就完成了从构思到部署的全流程。下面分享下我的实践心得&#xff1a; 项目构思阶段 这个模拟系统需要展示…...

OpenClaw多用户方案:QwQ-32B共享环境下的权限隔离

OpenClaw多用户方案&#xff1a;QwQ-32B共享环境下的权限隔离 1. 为什么需要多用户方案&#xff1f; 去年我在家里搭建了一个OpenClaw自动化环境&#xff0c;原本只是个人使用。直到某天家人看到我用语音指令让AI自动整理照片、生成周报后&#xff0c;纷纷要求"共享&quo…...

AMD显卡福音:实测ROCm7+PyTorch在Windows下跑ComfyUI,比WSL快了多少?

AMD显卡Windows原生AI绘图性能飞跃&#xff1a;ROCm 7与WSL实测对比 当AMD在2025年夏季悄然发布ROCm 7预览版时&#xff0c;很少有人预料到它会给Windows平台的AI绘图体验带来如此显著的改变。作为一名长期在WSL环境下使用AMD显卡进行Stable Diffusion工作的开发者&#xff0c;…...