ros2 action server示例、拓展、练习

注意:以下代码全部由ai生成,没有大问题,运用时需根据报错逐步调试

action server示例

goalresultfeedback 作为类的成员变量的 C++ 示例代码:

示例代码

#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"class MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()){// 创建 Action 服务器action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));// 创建服务service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;// 处理目标rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal;  // 存储目标return rclcpp_action::GoalResponse::YES;}// 处理取消请求rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}// 处理已接受的目标void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}// 执行目标void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){for (int i = 1; i <= 5; ++i) {feedback_->current_value = i * goal_->goal_value;goal_handle->publish_feedback(feedback_);RCLCPP_INFO(this->get_logger(), "Feedback: %f", feedback_->current_value);std::this_thread::sleep_for(std::chrono::seconds(1));}// 设置结果result_->result_value = goal_->goal_value * 10;goal_handle->succeed(result_);RCLCPP_INFO(this->get_logger(), "Action succeeded with result: %f", result_->result_value);}// 处理服务void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2;  // 示例处理RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}

代码说明

  • 成员变量

    • goal_: 存储接收到的目标。
    • result_: 存储结果信息。
    • feedback_: 存储反馈信息。
  • handle_goal 方法中,接收到的目标被存储到 goal_ 中。

  • execute 方法中,根据 goal_ 的值生成反馈,并发布反馈和结果。

拓展1 在execute中创建一个导航action client,并发布。

要在 execute 方法中创建一个导航目标点的 Action 客户端并发布一个固定点,你需要确保在代码中添加相关的导航 Action 依赖。以下是更新后的 C++ 示例代码:

示例代码

#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"
#include "nav2_msgs/action/navigate_to_pose.hpp" // 导航 Actionclass MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;using NavigateToPose = nav2_msgs::action::NavigateToPose;using NavigateToPoseClient = rclcpp_action::Client<NavigateToPose>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()),navigate_client_(rclcpp_action::create_client<NavigateToPose>(this, "navigate_to_pose")){action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;rclcpp_action::Client<NavigateToPose>::SharedPtr navigate_client_;rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal;return rclcpp_action::GoalResponse::YES;}rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){// 创建导航目标点auto navigation_goal = NavigateToPose::Goal();navigation_goal.pose.header.frame_id = "map"; // 或者其他适当的坐标框架navigation_goal.pose.header.stamp = this->now();navigation_goal.pose.pose.position.x = 1.0; // 固定点的坐标navigation_goal.pose.pose.position.y = 1.0;navigation_goal.pose.pose.orientation.w = 1.0; // 方向// 调用导航客户端if (!navigate_client_->wait_for_action_server(std::chrono::seconds(5))) {RCLCPP_ERROR(this->get_logger(), "Navigation action server not available");goal_handle->abort(result_);return;}auto send_goal_options = rclcpp_action::Client<NavigateToPose>::SendGoalOptions();send_goal_options.result_callback = [](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &) {RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Navigation goal accepted");};auto goal_handle_navigation = navigate_client_->async_send_goal(navigation_goal, send_goal_options);// 处理导航反馈while (rclcpp::ok()) {// 这里可以添加导航反馈处理逻辑std::this_thread::sleep_for(std::chrono::milliseconds(500));}// 返回结果result_->result_value = goal_->goal_value * 10;goal_handle->succeed(result_);RCLCPP_INFO(this->get_logger(), "Action succeeded with result: %f", result_->result_value);}void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2;RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}

代码说明

  1. 导航 Action 客户端

    • 创建 NavigateToPose 的 Action 客户端。
    • 使用 navigate_client_ 来发送导航目标。
  2. 导航目标点

    • execute 方法中定义固定的导航目标点(例如 (1.0, 1.0))。
    • 设置导航目标的坐标和方向。
  3. 异步发送目标

    • 使用 async_send_goal 方法发送导航目标,处理结果和反馈。
    • 可以在循环中添加对导航状态的反馈处理逻辑。

使用

  1. 确保导航 Action 服务器(例如 Nav2)正在运行。
  2. 启动此 Action 服务器节点。
  3. 在客户端调用 Action 和服务,观察服务器的导航行为。

拓展2 针对send_goal_options配置结构,创建一个新成员函数,替代上一段的lambda函数, 并使用send_goal_options的所有成员

好的,下面是更新后的代码示例,其中我们创建了一个新的成员函数来处理 send_goal_options 的配置,替代了之前使用的 Lambda 函数。这一新函数将使用 send_goal_options 的所有成员。

更新后的示例代码

#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"
#include "nav2_msgs/action/navigate_to_pose.hpp" // 导航 Actionclass MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;using NavigateToPose = nav2_msgs::action::NavigateToPose;using NavigateToPoseClient = rclcpp_action::Client<NavigateToPose>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()),navigate_client_(rclcpp_action::create_client<NavigateToPose>(this, "navigate_to_pose")){action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;rclcpp_action::Client<NavigateToPose>::SharedPtr navigate_client_;rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal;return rclcpp_action::GoalResponse::YES;}rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){// 创建导航目标点auto navigation_goal = NavigateToPose::Goal();navigation_goal.pose.header.frame_id = "map";navigation_goal.pose.header.stamp = this->now();navigation_goal.pose.pose.position.x = 1.0;navigation_goal.pose.pose.position.y = 1.0;navigation_goal.pose.pose.orientation.w = 1.0;// 调用导航客户端if (!navigate_client_->wait_for_action_server(std::chrono::seconds(5))) {RCLCPP_ERROR(this->get_logger(), "Navigation action server not available");goal_handle->abort(result_);return;}// 使用新成员函数配置 send_goal_optionsconfigure_send_goal_options(goal_handle, navigation_goal);}void configure_send_goal_options(const std::shared_ptr<GoalHandleMyAction> goal_handle, const NavigateToPose::Goal &navigation_goal){auto send_goal_options = rclcpp_action::Client<NavigateToPose>::SendGoalOptions();// 设置 result_callbacksend_goal_options.result_callback = [this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle) {if (goal_handle->get_status() == rclcpp_action::GoalStatus::SUCCEEDED) {RCLCPP_INFO(this->get_logger(), "Navigation goal succeeded");} else {RCLCPP_ERROR(this->get_logger(), "Navigation goal failed");}};// 设置 feedback_callbacksend_goal_options.feedback_callback = [this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle, const std::shared_ptr<const NavigateToPose::Feedback> feedback) {RCLCPP_INFO(this->get_logger(), "Navigation feedback: current position %f, %f",feedback->current_pose.position.x, feedback->current_pose.position.y);};// 设置 goal_response_callbacksend_goal_options.goal_response_callback = [](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle) {if (goal_handle) {RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Navigation goal accepted");} else {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Navigation goal rejected");}};// 发送导航目标auto goal_handle_navigation = navigate_client_->async_send_goal(navigation_goal, send_goal_options);}void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2;RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}

代码说明

  1. 新成员函数 configure_send_goal_options

    • 此函数负责配置 send_goal_options 的所有成员,包括 result_callbackfeedback_callbackgoal_response_callback
    • 通过捕获 this,可以在回调中访问类的成员函数和变量。
  2. 回调函数的实现

    • result_callback: 检查导航目标的状态,并根据成功或失败打印日志信息。
    • feedback_callback: 输出当前导航位置的反馈信息。
    • goal_response_callback: 检查目标是否被接受,并输出相应的日志信息。
  3. 调用导航目标

    • execute 方法中,调用 configure_send_goal_options 来配置并发送导航目标。

这种方式将发送目标的逻辑与配置的回调逻辑分离,使代码更清晰、可维护。如果你有其他问题或者需要进一步的解释,请随时告诉我!

注意:只要设置了 send_goal_options.feedback_callback,回调函数就会在导航服务器发送反馈时被调用,可以在函数内部获取并处理这些反馈信息。
示例:
将其改写为

send_goal_options.feedback_callback = 
[this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle
, const std::shared_ptr<const NavigateToPose::Feedback> feedback) 
{};

根据定义

#goal definition
geometry_msgs/PoseStamped pose
string behavior_tree
---
#result definition
std_msgs/Empty result
---
#feedback definition
geometry_msgs/PoseStamped current_pose
builtin_interfaces/Duration navigation_time
builtin_interfaces/Duration estimated_time_remaining
int16 number_of_recoveries
float32 distance_remaining
】

action的客户端也能获取
【geometry_msgs/PoseStamped current_pose
builtin_interfaces/Duration navigation_time
builtin_interfaces/Duration estimated_time_remaining
int16 number_of_recoveries
float32 distance_remaining】
这些信息

练习1

1.实现拓展中创建的navigation的导航action与自定义的action通信
2.找到isaac_mission_client实现其中自定义action与isaac_mission_client的通信,注意参考mqtt协议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454670.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机输出方波

从P1.0上输出一个方波,高电平5ms&#xff0c;低电平10ms. &#xff03;include〈reg51。h〉 unsigned char flag; sbit outP1^0&#xff1b; void main() &#xff5b; flag0&#xff1b; TMOD0X02; TH06&#xff1b; TL06; TR01&#xff1b; EA1&#xff1b; ET0…

Redis JSON介绍和命令大全

Redis JSON介绍和命令大全 Redis JSON先说说JSON是什么再说说JSON Path先推荐两个网站JSONPath JAVA clents Redis JSON 安装内存json命令语法命令url命令解释JSON.ARRAPPENDJSON.ARRINDEXJSON.ARRINSERTJSON.ARRLENJSON.ARRPOPJSON.ARRTRIMJSON.CLEARJSON.DEBUG MEMORYJSON.DE…

centOS部署Jenkins实现项目可持续自动化部署

个人看的是尚硅谷的视频&#xff0c;跟着实战&#xff0c;但因为视频是21年的&#xff0c;所以很容易出现jenkins插件不适配问题。 因而个人直接用较新版的jdk和jenkins. 先切换到root用户 sudo su一、安装jdk 先查询可安装版本 yum list java*安装jdk&#xff08;只复制圈…

【算法】归并排序概念及例题运用

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

爬虫日常实战

爬取美团新闻信息&#xff0c;此处采用两种方法实现&#xff1a; 注意点&#xff1a;因为此处的数据都是动态数据&#xff0c;所以一定要考虑好向下滑动数据包会更新的情况&#xff0c;不然就只能读取当前页即第一页数据&#xff0c;方法一通过更新ajax数据包网址页数&#xf…

vscode 预览markdown 文件

1. 点击左边扩展 2. 搜索“Markdown Preview Enhanced” 3. 选第一个安装即可 4. 重启vscode 5. 打开一个markdown 文件 6. 点击右上角的预览按钮

[mysql]mysql的全部单行函数

单行函数 几乎我们认识的语言都会对一些常用的功能进行,封装,有些叫函数,有些叫方法(Java),后期我们还可以自定义函数. 现在我们就当大家是没有语言基础,我们来从头开始讲.不过大家肯定接触过,中学说的函数,yf(x)f代表的就是function的缩写,这里其y2x1fx代表的就是封装的内容…

FileLink内外网文件交换——致力企业高效安全文件共享

随着数字化转型的推进&#xff0c;企业之间的文件交流需求日益增加。然而&#xff0c;传统的文件传输方式往往无法满足速度和安全性的双重要求。FileLink作为一款专注于跨网文件交换的工具&#xff0c;致力于为企业提供高效、安全的文件共享解决方案。 应用场景一&#xff1a;项…

C++大沥2019年真题——数字圈

Hi&#xff01;大家好&#xff01;Im#张亿&#xff0c;今天来讲C大沥2019年真题——数字圈 题目描述 当我们写数字时会发现有些数字有封闭区域&#xff0c;有的数字没有封闭区域。 数字 0 有一个封闭区域&#xff0c;数字 1、2、 3 都没有封闭区域&#xff0c;数字 4 有一个封…

word中的内容旋转90度

在vsto、Aspose.Words 中&#xff0c;默认没有直接的 API 可以让表格整体旋转 90 度。然而&#xff0c;我们可以通过一些方式来实现类似的效果&#xff0c;具体思路如下&#xff1a; 将表格插入到一个形状&#xff08;Shape&#xff09;或文本框中&#xff0c;然后旋转该形状。…

《RECONX: RECONSTRUCT ANY SCENE FROM SPARSEVIEWS WITH VIDEO DIFFUSION MODEL》论文阅读

论文地址&#xff1a;https://arxiv.org/pdf/2408.16767 项目地址&#xff1a;GitHub - liuff19/ReconX: ReconX: Reconstruct Any Scene from Sparse Views with Video Diffusion Model ---------------------------------------------------------------------------------…

2019年计算机网络408真题解析

第一题&#xff1a; 解析&#xff1a;OSI参考模型第5层完成的功能 首先&#xff0c;我们需要对OSI参考模型很熟悉&#xff1a;从下到上依次是&#xff1a;物理层-数据链路层-网络层- 运输层-会话层-表示层-应用层&#xff0c;由此可知&#xff0c;题目要问的是会话层的主要功能…

什么是感知与计算融合?

感知与计算融合&#xff08;Perception-Computing Fusion&#xff09;是指将感知技术&#xff08;如传感器、摄像头等&#xff09;与计算技术&#xff08;如数据处理、人工智能等&#xff09;有机结合&#xff0c;以实现对环境的更深层次理解和智能反应的过程。该技术广泛应用于…

基于SSM品牌银饰售卖系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;促销活动管理&#xff0c;饰品管理&#xff0c;我的收藏管理&#xff0c;系统管理&#xff0c;订单管理 用户账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;…

新书速览|Android智能座舱开发:从源码到实践

《Android智能座舱开发:从源码到实践》 本书内容 《Android智能座舱开发:从源码到实践》是一本专注于Android智能座舱系统开发与优化的实战指南。《Android智能座舱开发:从源码到实践》共9章&#xff0c;第1章从搭建源码编译环境开始&#xff0c;详细指导读者如何下载和编译An…

活体人脸识别技术总结及实践

文章目录 1、背景2、人脸反伪装技术2.1 活体人脸识别常见模式2.2 学术上反伪装研究 3、工程实现3.1 Silent-Face3.2 Silent-Face模型转rknn3.3 Silent-Face模型的限制 1、背景 1.1 什么是活体检测&#xff1f; 在人脸识别之前&#xff0c;先判断一下屏幕前摄像头捕捉到的人脸是…

深度解析RLS(Recursive Least Squares)算法

目录 一、引言二、RLS算法的基本思想三、RLS算法的数学推导四、RLS算法的特点五、RLS算法的应用场景六、RLS算法的局限性七、总结 一、引言 在自适应滤波领域&#xff0c;LMS&#xff08;Least Mean Squares&#xff09;算法因其计算简单、实现方便而广受欢迎。然而&#xff0…

【leetcode|哈希表、动态规划】最长连续序列、最大子数组和

目录 最长连续序列 解法一&#xff1a;暴力枚举 复杂度 解法二&#xff1a;优化解法一省去二层循环中不必要的遍历 复杂度 最大子数组和 解法一&#xff1a;暴力枚举 复杂度 解法二&#xff1a;贪心 复杂度 解法三&#xff1a;动态规划 复杂度 最长连续序列 输入输…

【数据结构与算法】时间、空间复杂度详解

大家有没有遇到过&#xff0c;为什么有些程序跑得飞快&#xff0c;而有些程序却慢得让人抓狂&#xff1f;我们可能都是这样认为的&#xff1a;他写的程序效率高等等&#xff0c;确实如此。但这背后隐藏着两个重要的概念&#xff1a;时间复杂度和空间复杂度。它们就像程序的“效…

算法题总结(十九)——图论

图论 DFS框架 void dfs(参数) { if (终止条件) {存放结果;return; }for (选择&#xff1a;本节点所连接的其他节点) {处理节点;dfs(图&#xff0c;选择的节点); // 递归回溯&#xff0c;撤销处理结果 } }深搜三部曲 确认递归函数&#xff0c;参数确认终止条件处理目前搜索节…