ros开发之action详解

在ROS(Robot Operating System)中,Action 是一种高级通信机制,适用于需要长时间运行的任务,并且这些任务可以分解为多个步骤或需要实时反馈的场景。Action 通信结合了 Goal(目标)Feedback(反馈)Result(结果) 的特性,非常适合处理复杂的任务。

以下是 Action 通常使用的场景及其作用,以及几个经典的应用情景:


Action 的作用

  1. 支持长时间运行的任务

    • Action 允许任务在后台运行,客户端不需要阻塞等待任务完成。
    • 例如,机器人导航到目标点可能需要几分钟,Action 可以持续提供反馈。
  2. 实时反馈

    • 在任务执行过程中,Action Server 可以不断向客户端发送反馈信息。
    • 例如,机器人移动时,可以实时反馈当前位置。
  3. 任务取消和状态管理

    • 客户端可以随时取消任务,Action Server 会处理取消逻辑。
    • 例如,用户在机器人导航过程中取消目标点。
  4. 任务结果返回

    • 任务完成后,Action Server 会返回最终结果。
    • 例如,机器人到达目标点后,返回成功或失败的状态。

Action 的经典应用场景

1. 机器人导航(Navigation)
  • 场景描述
    • 机器人需要从当前位置移动到目标位置。
    • 导航过程可能需要较长时间,且需要实时反馈机器人的位置和状态。
  • Action 的作用
    • Goal:目标位置(如坐标点)。
    • Feedback:机器人当前的位置、速度、剩余距离等。
    • Result:是否成功到达目标位置。
  • 示例
    • ROS 中的 move_base 包就是一个典型的 Action Server,用于实现机器人导航。
2. 机械臂运动控制(Arm Motion Planning)
  • 场景描述
    • 机械臂需要从当前位置移动到目标姿态(如抓取物体)。
    • 运动规划过程可能需要较长时间,且需要实时反馈机械臂的状态。
  • Action 的作用
    • Goal:目标姿态(如关节角度或末端执行器位置)。
    • Feedback:机械臂的当前姿态、运动进度等。
    • Result:是否成功到达目标姿态。
  • 示例
    • ROS 中的 MoveIt! 框架使用 Action 来实现机械臂的运动规划和控制。
3. 物体识别与抓取(Object Detection and Grasping)
  • 场景描述
    • 机器人需要识别桌面上的物体并抓取。
    • 识别和抓取过程可能需要多次尝试,且需要实时反馈识别结果和抓取进度。
  • Action 的作用
    • Goal:目标物体(如物体的位置或类别)。
    • Feedback:识别进度、抓取尝试次数等。
    • Result:是否成功抓取物体。
  • 示例
    • 使用 Action 实现物体识别和抓取任务,结合视觉和机械臂控制。
4. 路径规划与避障(Path Planning and Obstacle Avoidance)
  • 场景描述
    • 机器人在移动过程中需要动态规划路径并避开障碍物。
    • 路径规划过程需要实时反馈当前路径和障碍物信息。
  • Action 的作用
    • Goal:目标位置。
    • Feedback:当前路径、障碍物信息、规划进度等。
    • Result:是否成功规划并到达目标位置。
  • 示例
    • ROS 中的 global_plannerlocal_planner 使用 Action 实现路径规划和避障。
5. 长时间任务监控(Long-running Task Monitoring)
  • 场景描述
    • 机器人执行一个长时间任务(如清洁、巡检等),需要实时监控任务进度。
  • Action 的作用
    • Goal:任务目标(如清洁区域或巡检路线)。
    • Feedback:任务进度、当前状态等。
    • Result:任务是否成功完成。
  • 示例
    • 使用 Action 实现清洁机器人或巡检机器人的任务监控。
6. 多步任务执行(Multi-step Task Execution)
  • 场景描述
    • 机器人需要执行一个多步骤的任务(如打开门、进入房间、关闭门)。
    • 每个步骤可能需要较长时间,且需要实时反馈当前步骤的状态。
  • Action 的作用
    • Goal:任务目标(如进入房间)。
    • Feedback:当前步骤、步骤进度等。
    • Result:任务是否成功完成。
  • 示例
    • 使用 Action 实现多步骤任务的执行和监控。

Action 的优势

  1. 异步通信
    • 客户端不需要阻塞等待任务完成,可以同时处理其他任务。
  2. 实时反馈
    • 客户端可以实时了解任务进度,便于监控和调整。
  3. 任务管理
    • 支持任务取消、暂停和恢复,适合复杂的任务场景。
  4. 模块化设计
    • 将任务目标、反馈和结果分离,便于扩展和维护。

总结

Action 通信在 ROS 中广泛应用于需要长时间运行、实时反馈和任务管理的场景。经典的应用包括机器人导航、机械臂控制、物体抓取、路径规划等。通过 Action,ROS 提供了一种高效、灵活的通信机制,适用于复杂的机器人任务。

我们结合机器人导航具体看以下action代码
在机器人导航场景中,Action通信 的客户端和服务端分别对应不同的功能模块。以下是详细的解释:


1. 客户端节点(Client)

对应模块
  • 在机器人导航中,客户端通常是 任务规划模块用户交互模块
  • 例如:
    • 用户通过界面发送导航目标。
    • 高级任务规划器(如任务调度系统)发送导航指令。
主要职责
  1. 发送导航目标
    • 客户端向服务端发送目标位置(如地图坐标或目标点名称)。
    • 目标通常包括位置(x, y)和方向(theta)。
  2. 接收反馈
    • 客户端实时接收服务端发送的反馈信息,如机器人当前位置、速度、剩余距离等。
    • 反馈信息可以用于显示导航进度或调整任务。
  3. 处理结果
    • 客户端接收服务端返回的最终结果,如是否成功到达目标位置。
    • 根据结果决定下一步操作(如重新规划路径或结束任务)。
逻辑流程
  1. 创建 Action Client。
  2. 等待 Action Server 启动。
  3. 发送导航目标。
  4. 监听反馈信息并处理。
  5. 接收最终结果并处理。

2. 服务端节点(Server)

对应模块
  • 在机器人导航中,服务端通常是 导航栈(Navigation Stack) 的核心模块。
  • 例如:
    • move_base 是 ROS 中常用的导航 Action Server。
主要职责
  1. 接收导航目标
    • 服务端接收客户端发送的目标位置。
  2. 路径规划
    • 根据目标位置和当前地图,使用全局规划器(如 A* 或 Dijkstra)生成一条全局路径。
  3. 局部控制
    • 使用局部规划器(如 DWA 或 TEB)控制机器人沿路径移动,同时避开动态障碍物。
  4. 发布反馈
    • 实时向客户端发送反馈信息,如机器人当前位置、速度、剩余距离等。
  5. 返回结果
    • 当机器人到达目标位置或任务失败时,返回最终结果。
逻辑流程
  1. 创建 Action Server。
  2. 等待客户端发送目标。
  3. 接收目标后,启动路径规划和局部控制。
  4. 在导航过程中,实时发布反馈信息。
  5. 导航完成后,返回结果。

3. 具体逻辑示例

以下是一个典型的机器人导航场景中,客户端和服务端的逻辑流程:

客户端逻辑
  1. 初始化
    • 创建 Action Client,连接到 move_base Action Server。
  2. 发送目标
    • 用户输入目标位置(如 x=5.0, y=3.0, theta=0.0)。
    • 客户端将目标发送给服务端。
  3. 监听反馈
    • 实时接收服务端发送的反馈信息,如机器人当前位置。
    • 在界面上显示导航进度。
  4. 处理结果
    • 如果导航成功,显示“到达目标”。
    • 如果导航失败,显示“任务失败”并提示用户重新规划。
服务端逻辑
  1. 初始化
    • 创建 Action Server,等待客户端连接。
  2. 接收目标
    • 接收客户端发送的目标位置。
  3. 路径规划
    • 使用全局规划器生成一条从当前位置到目标位置的路径。
  4. 局部控制
    • 控制机器人沿路径移动,同时避开动态障碍物。
  5. 发布反馈
    • 实时发布机器人当前位置、速度、剩余距离等信息。
  6. 返回结果
    • 如果机器人到达目标位置,返回“成功”。
    • 如果任务失败(如路径被阻塞),返回“失败”。

4. 代码示例

以下是一个简化的客户端和服务端代码示例:

客户端代码
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <move_base_msgs/MoveBaseAction.h>

// 定义反馈回调函数
void feedbackCB(const move_base_msgs::MoveBaseFeedbackConstPtr &feedback) {
    // 打印反馈信息
    ROS_INFO("Current Position: x=%f, y=%f", 
             feedback->base_position.pose.position.x, 
             feedback->base_position.pose.position.y);
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "navigation_client");
    ros::NodeHandle nh;

    // 创建Action Client,连接到move_base
    actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> client("move_base", true);

    // 等待Action Server启动
    ROS_INFO("Waiting for action server to start.");
    client.waitForServer();
    ROS_INFO("Action server started, sending goal.");

    // 创建目标
    move_base_msgs::MoveBaseGoal goal;
    goal.target_pose.header.frame_id = "map";
    goal.target_pose.header.stamp = ros::Time::now();
    goal.target_pose.pose.position.x = 5.0;  // 目标位置的x坐标
    goal.target_pose.pose.position.y = 3.0;  // 目标位置的y坐标
    goal.target_pose.pose.orientation.w = 1.0;  // 目标方向

    // 发送目标,并绑定反馈回调函数
    client.sendGoal(goal, &feedbackCB);

    // 等待结果
    client.waitForResult();
    if (client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
        ROS_INFO("Goal reached!");
    } else {
        ROS_INFO("Failed to reach goal.");
    }

    return 0;
}
服务端代码
#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include <move_base_msgs/MoveBaseAction.h>

class MoveBaseServer {
public:
    MoveBaseServer(std::string name) :
        as_(nh_, name, boost::bind(&MoveBaseServer::executeCB, this, _1), false),
        action_name_(name) {
        as_.start();
        ROS_INFO("%s: Action Server started.", action_name_.c_str());
    }

    void executeCB(const move_base_msgs::MoveBaseGoalConstPtr &goal) {
        // 模拟导航过程
        ros::Rate rate(1);
        bool success = true;

        for (int i = 0; i < 5; ++i) {
            // 检查任务是否被取消
            if (as_.isPreemptRequested() || !ros::ok()) {
                as_.setPreempted();
                success = false;
                break;
            }

            // 发布反馈
            move_base_msgs::MoveBaseFeedback feedback;
            feedback.base_position.header.stamp = ros::Time::now();
            feedback.base_position.pose.position.x = i * 1.0;
            feedback.base_position.pose.position.y = i * 0.5;
            as_.publishFeedback(feedback);

            rate.sleep();
        }

        // 返回结果
        if (success) {
            move_base_msgs::MoveBaseResult result;
            result.result = "Goal reached!";
            as_.setSucceeded(result);
        }
    }

private:
    ros::NodeHandle nh_;
    actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction> as_;
    std::string action_name_;
};

int main(int argc, char** argv) {
    ros::init(argc, argv, "move_base_server");
    MoveBaseServer server("move_base");
    ros::spin();
    return 0;
}

以上代码中有两处地方解释以下
第一点是MoveBaseServer构造函数中使用初始化列表 初始化Action Server,这里使用boost库中的bind函数绑定回调函数 executeCB,用于处理客户端发送的目标。这是ros1的写法,在ros2中Boost 被逐步替换为 C++11/14/17 的标准库功能(如 std::bind),我们可以直接使用 std::bind来绑定回调函数

第二点是参数的类型,接收端接收参数的类型一定是加上ConstPtr,这是一个固定的规则,是 ROS 中 Action 通信机制的一部分。
比如move_base_msgs::MoveBaseGoalConstPtr 是 move_base_msgs::MoveBaseGoal 的智能指针类型。

ConstPtr 表示这是一个常量指针(即指向常量数据的指针),确保回调函数不会修改目标数据。

不管是goal还是feedback模块,都需要遵循,

5. 总结

  • 客户端:负责发送导航目标、接收反馈和处理结果。
  • 服务端:负责路径规划、局部控制、发布反馈和返回结果。
  • 典型应用:机器人导航、机械臂控制、物体抓取等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值