ROS2核心概念之代码示例三

ros1 和 ros2的区别 为什么用ros2.00.概述1.基本概念基本概念:ROS网络(ROS Graph)概念简介:节点(Nodes)客户端程序库发现2. ros2 的目标3. ros2 的架构4. ros1 和ros2的通信模型 0.概述 其实是为了解决ros1中的一些问题 主要是从下面几个文章整过来 古月居的博客https://www.guyuehome.com/805 Why ROS 2? http://desi... 阅读详情

上一节写到service,这一节写Action。

ROS2核心概念代码

Action

class MoveCircleActionServer : public rclcpp::Node
{
    public:
        // 定义一个自定义的动作接口类,便于后续使用
        using CustomAction = learning_interface::action::MoveCircle;
        // 定义一个处理动作请求、取消、执行的服务器端
        using GoalHandle = rclcpp_action::ServerGoalHandle<CustomAction>;

        explicit MoveCircleActionServer(const rclcpp::NodeOptions & action_server_options = rclcpp::NodeOptions())
        : Node("action_move_server", action_server_options)                                     // ROS2节点父类初始化
        {
            using namespace std::placeholders;

            this->action_server_ = rclcpp_action::create_server<CustomAction>(                  // 创建动作服务器(接口类型、动作名、回调函数)
                this->get_node_base_interface(),
                this->get_node_clock_interface(),
                this->get_node_logging_interface(),
                this->get_node_waitables_interface(),
                "move_circle",
                std::bind(&MoveCircleActionServer::handle_goal, this, _1, _2),
                std::bind(&MoveCircleActionServer::handle_cancel, this, _1),
                std::bind(&MoveCircleActionServer::handle_accepted, this, _1));
        }

    private:
        rclcpp_action::Server<CustomAction>::SharedPtr action_server_;  // 动作服务器

        // 响应动作目标的请求
        rclcpp_action::GoalResponse handle_goal(
            const rclcpp_action::GoalUUID & uuid,
            std::shared_ptr<const CustomAction::Goal> goal_request)                             
        {
            RCLCPP_INFO(this->get_logger(), "Server: Received goal request: %d", goal_request->enable);
            (void)uuid;

            // 如请求为enable则接受运动请求,否则就拒绝
            if (goal_request->enable)                                                           
            {
                return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
            }
            else
            {
                return rclcpp_action::GoalResponse::REJECT;
            }
        }

        // 响应动作取消的请求
        rclcpp_action::CancelResponse handle_cancel(
            const std::shared_ptr<GoalHandle> goal_handle_canceled_)                            
        {
            RCLCPP_INFO(this->get_logger(), "Server: Received request to cancel action");
            (void) goal_handle_canceled_; 
            return rclcpp_action::CancelResponse::ACCEPT;
        }

        // 处理动作接受后具体执行的过程
        void handle_accepted(const std::shared_ptr<GoalHandle> goal_handle_accepted_)          
        {
            using namespace std::placeholders;
            // 在线程中执行动作过程
            std::thread{std::bind(&MoveCircleActionServer::execute, this, _1), goal_handle_accepted_}.detach(); 
        }


        void execute(const std::shared_ptr<GoalHandle> goal_handle_)
        {
            const auto requested_goal = goal_handle_->get_goal();       // 动作目标
            auto feedback = std::make_shared<CustomAction::Feedback>(); // 动作反馈
            auto result = std::make_shared<CustomAction::Result>();     // 动作结果

            RCLCPP_INFO(this->get_logger(), "Server: Executing goal");
            rclcpp::Rate loop_rate(1);

            // 动作执行的过程
            for (int i = 0; (i < 361) && rclcpp::ok(); i=i+30)
            {
                // 检查是否取消动作
                if (goal_handle_->is_canceling())
                {
                    result->finish = false;
                    goal_handle_->canceled(result);
                    RCLCPP_INFO(this->get_logger(), "Server: Goal canceled");
                    return;
                }

                // 更新反馈状态
                feedback->state = i;
                // 发布反馈状态
                goal_handle_->publish_feedback(feedback);
                RCLCPP_INFO(this->get_logger(), "Server: Publish feedback");

                loop_rate.sleep();
            }

            // 动作执行完成
            if (rclcpp::ok())
            {
                result->finish = true;
                goal_handle_->succeed(result);
                RCLCPP_INFO(this->get_logger(), "Server: Goal succeeded");
            }
        }
};

// ROS2节点主入口main函数
int main(int argc, char * argv[])                                
{
    // ROS2 C++接口初始化
    rclcpp::init(argc, argv);                        
    
    // 创建ROS2节点对象并进行初始化             
    rclcpp::spin(std::make_shared<MoveCircleActionServer>());   
    
    // 关闭ROS2 C++接口  
    rclcpp::shutdown();                                           
    
    return 0;
}

上边的是server端,看看下边的client端;代码如下:

class MoveCircleActionClient : public rclcpp::Node
{
    public:
        // 定义一个自定义的动作接口类,便于后续使用
        using CustomAction = learning_interface::action::MoveCircle;
        // 定义一个处理动作请求、取消、执行的客户端类
        using GoalHandle = rclcpp_action::ClientGoalHandle<CustomAction>;

        explicit MoveCircleActionClient(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
        : Node("action_move_client", node_options)                            // ROS2节点父类初始化
        {
            this->client_ptr_ = rclcpp_action::create_client<CustomAction>(   // 创建动作客户端(接口类型、动作名)
                this->get_node_base_interface(),
                this->get_node_graph_interface(),
                this->get_node_logging_interface(),
                this->get_node_waitables_interface(),
                "move_circle");
        }

        // 创建一个发送动作目标的函数
        void send_goal(bool enable)
        {
            // 检查动作服务器是否可以使用
            if (!this->client_ptr_->wait_for_action_server(std::chrono::seconds(10))) 
            {
                RCLCPP_ERROR(this->get_logger(), "Client: Action server not available after waiting");
                rclcpp::shutdown();
                return;
            }

            // 绑定动作请求、取消、执行的回调函数
            auto send_goal_options = rclcpp_action::Client<CustomAction>::SendGoalOptions();
            using namespace std::placeholders;
            send_goal_options.goal_response_callback =
                std::bind(&MoveCircleActionClient::goal_response_callback, this, _1);
            send_goal_options.feedback_callback =
                std::bind(&MoveCircleActionClient::feedback_callback, this, _1, _2);
            send_goal_options.result_callback =
                std::bind(&MoveCircleActionClient::result_callback, this, _1);

            // 创建一个动作目标的消息
            auto goal_msg = CustomAction::Goal();
            goal_msg.enable = enable;
            // 异步方式发送动作的目标
            RCLCPP_INFO(this->get_logger(), "Client: Sending goal");
                this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
        }

    private:
        rclcpp_action::Client<CustomAction>::SharedPtr client_ptr_;

        // 创建一个服务器收到目标之后反馈时的回调函数
        void goal_response_callback(GoalHandle::SharedPtr goal_message)
		{
			if (!goal_message)
			{
				RCLCPP_ERROR(this->get_logger(), "Client: Goal was rejected by server");
				rclcpp::shutdown(); // Shut down client node
			}
			else
			{
				RCLCPP_INFO(this->get_logger(), "Client: Goal accepted by server, waiting for result");
			}
		}

        // 创建处理周期反馈消息的回调函数
        void feedback_callback(
            GoalHandle::SharedPtr,
            const std::shared_ptr<const CustomAction::Feedback> feedback_message)
        {
            std::stringstream ss;
            ss << "Client: Received feedback: "<< feedback_message->state;
            RCLCPP_INFO(this->get_logger(), "%s", ss.str().c_str());
        }

        // 创建一个收到最终结果的回调函数
        void result_callback(const GoalHandle::WrappedResult & result_message)
        {
            switch (result_message.code)
            {
                case rclcpp_action::ResultCode::SUCCEEDED:
                    break;
                case rclcpp_action::ResultCode::ABORTED:
                    RCLCPP_ERROR(this->get_logger(), "Client: Goal was aborted");
                    rclcpp::shutdown(); // 关闭客户端节点
                    return;
                case rclcpp_action::ResultCode::CANCELED:
                    RCLCPP_ERROR(this->get_logger(), "Client: Goal was canceled");
                    rclcpp::shutdown(); // 关闭客户端节点
                    return;
                default:
                    RCLCPP_ERROR(this->get_logger(), "Client: Unknown result code");
                    rclcpp::shutdown(); // 关闭客户端节点
                    return;
            }
            RCLCPP_INFO(this->get_logger(), "Client: Result received: %s", (result_message.result->finish ? "true" : "false"));
            rclcpp::shutdown();         // 关闭客户端节点
        }
};

// ROS2节点主入口main函数
int main(int argc, char * argv[])                                    
{
    // ROS2 C++接口初始化
    rclcpp::init(argc, argv);   
    
    // 创建一个客户端指针                                     
    auto action_client = std::make_shared<MoveCircleActionClient>(); 
    
    // 发送动作目标
    action_client->send_goal(true);     
    
    // 创建ROS2节点对象并进行初始化                            
    rclcpp::spin(action_client);  
    
    // 关闭ROS2 C++接口                                   
    rclcpp::shutdown();                                              
    
    return 0;
}

这段代码,就是客户端发起一个动作,服务器接收到,然后反馈,最后收到结果,然后重新调整。通过这样的例子,可以看懂ROS2的action是怎么用的,以及如何自定义动作,自定义消息。

这篇就写到这里,代码没什么复杂的,关键是要学会c++,c++不熟悉的,可以看看这里。

赵虚左Ros2-核心篇讲义学习-第二三章 ROS2通信机制核心 在ROS2中通信方式虽然有多种,但是不同通信方式的组成要素都是类似的,比如:通信是双方或多方行为、通信时都需要将不同的通信对象关联、都有各自的模型、交互数据时也必然涉及到数据载体等等。本节将会介绍通信中涉及到的一些术语。话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。 阅读详情

相关推荐

ros2通信核心之DDS简介

DDS(Data Distribution Service,数据分发服务)是一种用于实时系统的通信中间件,它为分布式应用程序提供可靠、高效的数据传输。ROS 2 使用 DDS 作为其底层通信机制,因此理解 DDS 的基本概念对于 ROS 2 编程至关重要。

elais_h的博客 3327

古月·ROS2入门21讲——学习笔记(一)核心概念部分1-14讲

数量也并不是唯一的。

weixin_45897172的博客 9902

ROS2 概念以及通信方式

ROS 2(Robot Operating System 2)是一个用于机器人开发的开源平台,它提供了一系列工具和库,用于构建机器人应用程序。相较于前身ROS(ROS 1),ROS 2在设计上考虑了更多的实时性、安全性和可靠性因素,因此适用于更广泛的应用场景和硬件平台。以下是ROS 2的一些关键特点和概念:分布式架构:ROS 2支持分布式架构,允许节点在多个物理机器上运行,通过网络进行通信。这种架构支持更复杂和大规模的机器人系统。实时性:ROS 2引入了实时通信机制,如数据流控制(DDS),以支持严格的实时

qq_50284870的博客 3084

ROS 2从入门到精通系列(一):什么是ROS2 - 核心概念和架构

ROS 2是新一代机器人操作系统框架,相比ROS 1在实时性、安全认证和跨平台支持等方面有显著改进。其核心架构包含节点(Node)、话题(Topic)、服务(Service)和动作(Action)四大通信机制,采用DDS中间件实现高效通信。ROS 2提供完整的工具链和算法库,支持LTS长期支持版本,适用于从开发到生产的全流程。系统采用分布式计算模型,通过状态机管理节点生命周期,为机器人软件开发提供了标准化、模块化的解决方案。

weixin_52694742的博客 5283

ROS2架构介绍

ROS 2 并非简单地对 ROS 1 进行升级,而是一次彻底的重新设计。它通过引入 DDS 作为通信核心,并结合现代软件工程实践,成功解决了 ROS 1 在多机器人系统、实时性、安全性和跨平台支持等方面的诸多痛点。其分层架构、标准化的生命周期管理、丰富的 QoS 策略以及内建的安全机制,使得 ROS 2 能够更好地满足现代复杂机器人应用在可靠性、性能和安全性方面的严苛需求。

weixin_39475026的博客 2519

ROS2 - 核心概念

ROS 2是一个基于强类型、匿名发布/订阅机制的中间件,它允许在不同进程之间传递消息。任何ROS 2系统的核心都是ROS图。ROS图是指ROS系统中的节点网络以及它们之间进行通信的连接。这些概念将帮助您开始了解ROS 2的基础知识。

机器人控制与仿真应用 706

ROS2核心概念之代码示例二

上一节主要写了Node,Topic的代码示例,这一节继续写未写完的。

yajunjiao的专栏 871

【生物识别模组介绍】静脉识别模组

静脉识别技术是依据流动的静脉血液中的血红蛋白对近红外光有所吸收,通过近红外光照射手指、手掌、面部、腕部呈现的分布图像,再使用特定的算法对图像进行特征提取、分析比对,从而进行身份认证识别。静脉结构相同几率为34亿分之一,每个人的静脉结构具有独特性,而且静脉特征图像自成年后终身不变,不受外部环境、疾病等影响,是人体最稳定的生物特征之一。商务合作联系:newmagicmission@gmail.com图1.0。

upupDay's blog 898

ROS 2 核心概念详解与区分指南

摘要:ROS 2核心概念包含节点(独立执行单元)、功能包(软件容器)、接口(通信协议规范)、话题(单向数据流)、服务(同步请求/响应)和动作(异步长时任务)。节点类比餐厅服务员,功能包如工具集,接口定义通信格式。话题适用于持续数据流,服务处理即时命令,动作管理带反馈的长任务。通过ros2命令行工具可查看各组件,实际应用如机器人导航系统使用这些机制协同工作。理解这些概念的关系(见图表)是构建ROS 2系统的基础,建议结合turtlesim等示例实践掌握。

m0_55260921的博客 1180

openMVS ---dense point cloud(代码理解)

openMVS ---dense point cloud(代码理解)0 代码实现原理1 代码实现步骤1.1 参数传递1.2 loading .mvs数据1.3 稠密重建1.3.0 相关变量及概念1.3.1 ComputeDepthMaps(data) --计算多张深度图1.3.1.1. pre1.3.1.2 为每一张depth map Select view(s) !!!1.3.1.2.1 N neighbors --- global score + filter1.3.1.2.2 MRF ---- t

小rivaaaa的博客 5328

【全开源】旅游系统源码(Uniapp+FastAdmin+ThinkPHP)

通过源码的灵活配置和定制开发,我们可以根据旅游企业的实际需求,快速构建出符合其业务特点的旅游系统。旅游系统源码,作为这一变革的基石,为旅游业的数字化转型提供了强有力的支撑。通过深入研究和应用旅游系统源码,我们能够构建出更加智能、便捷、个性化的旅游服务平台,满足游客日益增长的旅游需求。国际化发展:随着全球化的深入发展,旅游系统源码也将迎来国际化的发展机遇,为国内外游客提供更加便捷、高效的旅游服务。跨界融合:旅游系统源码将与更多领域进行跨界融合,如与交通、餐饮、购物等行业的结合,为游客提供更加丰富的旅游体验。

2401_84413757的博客 2147

【ROS2】核心概念4——话题(node)

ROS2的Topic,节点间异步传递数据的“桥梁”,基于发布/订阅模型(如传感器数据流)。

进一寸有一寸的欢喜 1371

【Bug已解决】Claude Team Plan 购买席位报错 Payment failed 解决方案

方案适用场景推荐指数检查账单历史状态排查的第一步⭐⭐⭐⭐⭐更换支付方式类型快速尝试是否能绕开问题⭐⭐⭐联系官方支持团队最终解决问题的正规渠道⭐⭐⭐⭐⭐临时过渡方案紧急用人需求的应急处理⭐⭐⭐关注官方修复进度确认属于系统性缺陷的场景⭐⭐⭐⭐Claude Team Plan 增购席位报的问题,社区反馈和实际排查表明很大概率属于平台计费系统在处理按比例分摊费用这类复杂计算链路时的系统性缺陷,而不是用户自身的支付信息填写有误。先排除自身账单历史是否存在异常。

一键难忘的博客 4177

ROS2核心概念之服务

话题通信可以实现多个ROS节点之间数据的单向传输,使用这种异步通信机制,发布者无法准确知道订阅者是否收到消息,本节我们将一起学习ROS另外一种常用的通信方法——服务,可以实现类似你问我答的同步通信效果。

Graceful_scenery的博客 1028

英伟达DeepStream学习笔记7——DeepStream接入USB相机并实现广角摄像头的畸变矫正

deepstream官方提供了一个畸变矫正的例子,包含了鱼眼和普通广角的矫正。我目前准备做一个广角的畸变矫正,我已经使用opencv实现功能,目前增加到deepstream框架中。示例代码在\opt\nvidia\deepstream\deepstream-5.0\sources\apps\sample_apps\deepstream-dewarper-test 中,鱼眼矫正——deepstream官方版 https://developer.nvidia.com/blog/calibration-trans

耶律大石的博客 1599

uniapp [微信小程序] - 实现语音播报功能+实时收款播报,使用同声传译插件做文字转语音播报类似微信/支付宝收款播报小程序语音识别和朗读,手机提醒播放自定义收款语音信息(音频+收款金额+文案)

uniapp-实现语音播报功能,实时收款播报,uni-app/vue 文字转语音朗读(附小程序语音识别和朗读)uniapp小程序使用文字转语音播报类似支付宝收款播报小程序语音识别和朗读)IOS苹果手机播报没有声音,生成语音并播放,微信小程序接入官方wechatSi(微信同声传译)uniapp小程序使用文字转语音播报类似支付宝收款播报,uni-app 小程序端实现文字语音播报,uniAPP文本转语音,uniapp 文字转语音文字播报,手机静音播放没声音,收款方提示音 文字转语音朗读 同声传译,uniapp小程

🏆 前端领域优质创作者 3795

【ROS2】ROS2简介及学习资源汇总

但最初的ROS是面向科研领域的,有一些局限性,如今机器人商业需求日趋突显,最初的ROS也因丰富功能的集成使得原始建构和设计的不足愈发明显,所以ROS的研发团队重新设计了更加优秀的ROS2。:ROS2不仅支持Linux和MacOS,还增加了对Windows和RTOS(实时操作系统)的支持,使得ROS2能够在更广泛的平台上运行,提高了开发的灵活性和适用范围。:ROS2使用Python编写的launch文件,相比ROS1中的XML格式,提供了更多的功能性和灵活性,使得启动和配置更加直观和便捷。

淋曦的进击手记 6604

TenserRt平台SMOKE 3D目标检测部署完整教程:从理论到实践

本教程详细介绍了在RK3588平台上部署SMOKE 3D目标检测模型的完整流程。SMOKE是一种创新的单阶段单目3D检测方法,通过关键点估计直接预测3D目标信息,有效解决了深度信息缺失等挑战。文章从理论基础出发,解析了SMOKE的核心算法和网络架构,包括DLA-34主干网络和关键点中心化策略。同时提供了详细的Docker环境配置、模型导出到ONNX格式的实践指南,以及TensorRT引擎构建和性能优化的关键技术要点。该教程为开发者在嵌入式平台上实现高效3D目标检测提供了完整的技术参考。

LXY_LOVE36的博客 371

ROS2核心概念之通信接口

接口的概念在各个领域随处可见,无论是硬件结构还是软件开发,都有广泛的应用。所以什么是接口,它是一种相互关系,只有彼此匹配,才能建立连接。回到ROS的通信系统,它的主要目的就是传输数据,那就得让大家高效的建立连接,并且准确包装和解析传输的数据内容,话题、服务等机制也就诞生了,他们传输的数据,都要符合通信接口的标准定义;比如摄像头驱动发布的图像话题,由每个像素点的RGB三原色值组成;控制机器人运动的速度指令,由线速度和角速度组成;进行机器人配置的服务,有配置的参数和反馈的结果组成等等;

Graceful_scenery的博客 992

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

【2】 ROS2学习——核心概念的学习Ⅰ(节点、话题、服务)

话题和服务是ROS中最为常用的两种数据通信方法,前者适合传感器、控制指令等周期性、单向传输的数据,后者适合一问一答,同步性要求更高的数据,

weixin_46444742的博客 2109

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【ros/ros2】ros1和ros2的区别-要点记录

ros1和ros2的区别,要点记录

shuaixio的博客 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

ROS2学习(四).ROS 2 核心概念

ROS 2 Galactic环境配置官方流程流程执行配置脚本将配置命令加入shell启动脚本中将colcon_cd加入shell启动脚本中安装前提系统要求安装选择安装流程设置语言区域设置源安装ROS2包环境配置验证样例参考 ROS2在shell环境中使用了组合工作区workspace。 Workspace : 系统上使用ROS2进行开发的位置,跟我们一般的工作区概念是一致的。 核心ROS2工作区被称为底层underlay,其他的本地工作区被称为覆盖层overlay。 通常我们使用ROS2开发时,将同时拥有几

amuro_ray027的博客 1273

ROS2极简总结-核心概念(一)

参考文献:ROS2 Foundation - An introduction to core concepts 纲要 计算图(Computation Graph) 节点(Node) 节点组成(Node Composition) 主题和消息(Topics and Messages) 执行器(Executor) 服务(Services) 行动(Actions) 参数(Params) 启动文件(Launch files) 1 计算图 计算图(Computation Graph)用于显示ROS

zhangrelay的专栏 3898

ROS2核心概念之代码示例一

上一篇主要写了些概念,可以参考之前文章。这一篇主要写下代码的demo,主要参考了古月居的代码。

yajunjiao的专栏 350

什么是ROS2

它的主要组成包括ROS Mastar、 ROS Node等,不同的功能可以由不同的节点实现,节点之间可以通过发布和订阅话题来传递消息,它的本质是基于TCP/IP的Socket通信机制。ROS2继承了部分ROS1的概念,如应用节点、消息通信、服务通信、Action通信等,同时引入很多新的概念,如基于RTPS(Real-Time Publish-Subscribe)协议的DDS,服务质量(Qos)等,这些新引入的特性是ROS2支持更快的通信,更彻底的分布式。通信基于TCP实现,实时性差、系统开销大;

3714
上一篇: ROS2核心概念之代码示例二
下一篇: ROS2核心概念之代码示例四
1随便写写1
博客等级 码龄16年 2261粉丝 161原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值