ROS1入门教程6:复杂行为处理

news2025/2/9 6:40:43

一、新建项目

# 创建工作空间
mkdir -p demo6/src && cd demo6

# 创建功能包
catkin_create_pkg demo roscpp rosmsg actionlib_msgs message_generation tf

二、创建行为

# 创建行为文件夹
mkdir action && cd action

# 创建行为文件
vim Move.action

# 定义行为
uint32 goal
---
uint32 result
---
uint32 feedback

三、创建服务端

#include <iostream>
#include <thread>
#include <atomic>

#include "ros/ros.h"
#include "actionlib/server/action_server.h"
#include "demo/MoveAction.h"

std::atomic<bool> g_isCanceled{false};

void done_cb(actionlib::ServerGoalHandle<demo::MoveAction> goalHandle) {
    ROS_INFO("==> done_cb");
    if (goalHandle.getGoal()->destination > 100) {
        goalHandle.setRejected(); // 拒绝请求
        return;
    }
    goalHandle.setAccepted(); // 同意请求
    ros::Rate rate(1);
    uint32_t distance = 0;
    while (ros::ok() && distance < goalHandle.getGoal()->destination) {
        if (g_isCanceled) {
            goalHandle.setCanceled(); // 取消任务
            return;
        }
        demo::MoveFeedback feedback;
        feedback.distance = distance;
        goalHandle.publishFeedback(feedback);
        ROS_INFO("==> distance: %d", distance);
        rate.sleep();
        ++distance;
    }
    demo::MoveResult result;
    result.result = distance;
    goalHandle.setSucceeded(result); // 执行成功
}

void goal_cb(actionlib::ServerGoalHandle<demo::MoveAction> goalHandle) {
    ROS_INFO("==> goal_cb, goal: %d", goalHandle.getGoal()->destination);
    g_isCanceled = false;
    std::thread t(done_cb, goalHandle);
    t.detach();
}

void cancel_cb(actionlib::ServerGoalHandle<demo::MoveAction> goalHandle) {
    ROS_INFO("==> cancel_cb");
    g_isCanceled = true;
}

int main(int argc, char* argv[]) {
    ros::init(argc, argv, "server");
    ros::NodeHandle nodeHandle;
    std::string actionName = "demo6";
    actionlib::ActionServer<demo::MoveAction> server(
        nodeHandle,
        actionName,
        boost::bind(goal_cb, _1),
        boost::bind(cancel_cb, _1),
        false
    );
    server.start();
    ros::spin();

    return EXIT_SUCCESS;
}

四、创建客户端

#include <iostream>

#include "ros/ros.h"
#include "actionlib/client/action_client.h"
#include "demo/MoveAction.h"

void transition_cb(actionlib::ClientGoalHandle<demo::MoveAction> goalHandle) {
    ROS_INFO("==> transition_cb, state: %s", goalHandle.getCommState().toString().c_str());
}

void feedback_cb(actionlib::ClientGoalHandle<demo::MoveAction> goalHandle, const demo::MoveFeedbackConstPtr &feedback) {
    ROS_INFO("==> feedback_cb, distance: %d", feedback->distance);
}

int main(int argc, char* argv[]) {
    ros::init(argc, argv, "client");
    ros::AsyncSpinner spinner(1);
    spinner.start();
    ros::NodeHandle nodeHandle;
    std::string actionName = "demo6";
    actionlib::ActionClient<demo::MoveAction> client(nodeHandle, actionName); // 创建行为客户端
    client.waitForActionServerToStart(); // 等待行为服务器启动
    demo::MoveGoal goal;
    goal.destination = 5;
    // 注意:必须赋值给一个对象,否则会被释放掉
    const actionlib::ActionClient<demo::MoveAction>::GoalHandle &goalHandle = client.sendGoal( // 发送目标
        goal,
        boost::bind(transition_cb, _1),
        boost::bind(feedback_cb, _1, _2)
    );
    ros::waitForShutdown();
    
    return EXIT_SUCCESS;
}

五、修改编译配置

# 查找catkin库
find_package(catkin REQUIRED COMPONENTS
  actionlib_msgs
  message_generation
  roscpp
  rosmsg
  tf
)

# 添加行为文件
add_action_files(
  FILES
  Move.action
)

# 编译行为文件
generate_messages(
  DEPENDENCIES
  actionlib_msgs
)

# 添加源文件
add_executable(server src/server.cpp)
add_executable(client src/client.cpp)

# 链接catkin库
target_link_libraries(server ${catkin_LIBRARIES})
target_link_libraries(client ${catkin_LIBRARIES})

六、运行效果

服务端:

客户端:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java处理视频思路

1.首先实现断点续传功能。 断点续传实现思路&#xff1a; 前端对文件分块。前端使用多线程一块一块上传&#xff0c;上传前给服务端发一个消息校验该分块是否上传&#xff0c;如果已上传则不再上传。如果从该断点处断网了&#xff0c;下次上传时&#xff0c;前面的分块已经存在…

C#实现调用DLL 套壳读卡程序(桌面程序开发)

背景 正常业务已经支持 读三代卡了&#xff0c;前端调用医保封装好的服务就可以了&#xff0c;但是长护要读卡&#xff0c;就需要去访问万达&#xff0c;他们又搞了一套读卡的动态库&#xff0c;为了能够掉万达的接口&#xff0c;就需要去想办法调用它们提供的动态库方法&…

USB 状态机及状态转换

文章目录 USB 状态机及状态转换连接状态供电状态默认状态地址状态配置状态挂起状态USB 状态机及状态转换 枚举完成之前,USB 设备要经过一系列的状态变化,才能最终完成枚举。这些状态是 连接状态 - attached供电状态 - powered默认状态 - default地址状态 - address配置状态 -…

QT线程 QtConcurrent (深入理解)

QT多线程专栏共有16篇文章,从初识线程到、QMutex锁、QSemaphore信号量、Emit、Sgnals、Slot主线程子线程互相传值同步变量、QWaitCondition、事件循环、QObjects、线程安全、线程同步、线程异步、QThreadPool线程池、ObjectThread多线程操作、 moveToThread等线程操作进行了全…

Linux-Ubuntu之串口通信

Linux-Ubuntu之串口通信 一&#xff0c;串口通信1.串口通信寄存器配置2.串口通信软件实现①手动波特率②自动波特率③主函数 二&#xff0c;printf和scanf实现串口的输入显示 一&#xff0c;串口通信 1.串口通信寄存器配置 串口通信利用接口是这个TTL&#xff0c;下载程序用的…

阿尔萨斯(JVisualVM)JVM监控工具

文章目录 前言阿尔萨斯(JVisualVM)JVM监控工具1. 阿尔萨斯的功能2. JVisualVM启动3. 使用 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff…

41 stack类与queue类

目录 一、简介 &#xff08;一&#xff09;stack类 &#xff08;二&#xff09;queue类 二、使用与模拟实现 &#xff08;一&#xff09;stack类 1、使用 2、OJ题 &#xff08;1&#xff09;最小栈 &#xff08;2&#xff09;栈的弹出压入序列 &#xff08;3&#xf…

wangEditor富文本插件在vue项目中使用和媒体上传的实现

wangEditor是前端一个比较流行的简洁易用&#xff0c;功能强大的前端富文本编辑器&#xff0c;支持 JS Vue React&#xff0c;提供了很多丰富的功能&#xff0c;下面手把手教你实现wangWditor富文本插件在vue项目中配置&#xff0c;保存、图片上传等功能。无脑ctrlc即可 基本功…

VMwareTools安装(ubuntu23)

1.打开VMware&#xff0c;菜单栏虚拟机->安装VMwareTools 2.点开光驱&#xff0c;把压缩包复制到桌面 3.解压 如何开启sudo权限&#xff1a; sudo passwd root 之后输入密码查看解压文件夹&#xff0c;执行vmware-install.pl文件 安装过程中碰见如下报错信息&#xff1a;…

jangow-01-1.0.1靶机

靶机 ip&#xff1a;192.168.152.155 把靶机的网络模式调成和攻击机kali一样的网络模式&#xff0c;我的kali是NAT模式, 在系统启动时(长按shift键)直到显示以下界面 ,我们选第二个&#xff0c;按回车。 继续选择第二个&#xff0c;这次按 e 进入编辑页面 接下来&#xff0c;…

C# GDI+数码管数字控件

调用方法 int zhi 15;private void button1_Click(object sender, EventArgs e){if (zhi > 19){zhi 0;}lcdDisplayControl1.DisplayText zhi.ToString();} 运行效果 控件代码 using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using …

Cilium:BPF 和 XDP 参考指南(2021)

大家觉得有意义和帮助记得及时关注和点赞!!! BPF 是 Linux 内核中一个非常灵活与高效的类虚拟机&#xff08;virtual machine-like&#xff09;组件&#xff0c; 能够在许多内核 hook 点安全地执行字节码&#xff08;bytecode &#xff09;。很多 内核子系统都已经使用了 BPF&a…

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…

机器学习-高斯混合模型

文章目录 高斯混合模型对无标签的数据集&#xff1a;使用高斯混合模型进行聚类对有标签的数据集&#xff1a;使用高斯混合模型进行分类总结 高斯混合模型 对无标签的数据集&#xff1a;使用高斯混合模型进行聚类 对有标签的数据集&#xff1a;使用高斯混合模型进行分类 总结

GitLab 服务变更提醒:中国大陆、澳门和香港用户停止提供服务(GitLab 服务停止)

目录 前言 一. 变更详情 1. 停止服务区域 2. 邮件通知 3. 新的服务提供商 4. 关键日期 5. 行动建议 二. 迁移指南 三. 注意事项 四. 相关推荐 前言 近期&#xff0c;许多位于中国大陆、澳门和香港的 GitLab 用户收到了一封来自 GitLab 官方的重要通知。根据这封邮件…

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…

css绘制圆并绘制圆的半径

<div class"item1"></div>.item1 {position: relative;width: 420px;height: 420px;border-radius: 50%; /* 圆形 */color: white; /* 文本颜色 */background-color: rgba(154, 227, 36, 0.4); } .item1::before {content: "";position: absol…

【原理图专题】CIS库中有两部分组成的器件怎么查看符号库

在ICS库使用过程中&#xff0c;会遇到比如运放、MOS管等是由两个符号构成的一个器件。比如下图所示的器件&#xff1a; 为了方便我们知道内部结构&#xff0c;很可能把器件拆成两部分&#xff0c;一部分是PMOS&#xff0c;一部分是NMOS。包括大的MCU或芯片也是这样&#xff0c;…

HarmonyOS NEXT 实战之元服务:静态案例效果---查看国内航班服务

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; Index代码 import { authen…

ID读卡器TCP协议Delphi7小程序开发

Delphi 7是一款功能强大的快速应用程序开发工具&#xff0c;它提供了丰富的开发环境和组件库&#xff0c;支持多种操作系统和数据库连接&#xff0c;方便开发者进行高效的程序设计。然而&#xff0c;由于它是一款较旧的开发环境&#xff0c;在使用时需要注意兼容性和安全问题。…