ROS Kinetic通信编程:话题、服务、动作编程

文章目录

  • 一、话题编程
  • 二、服务编程
  • 三、动作编程

接上篇,继续学习ROS通信编程基础

一、话题编程

步骤:

  • 创建发布者
    • 初始化ROS节点
    • 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
    • 按照一定频率循环发布消息
  • 创建订阅者
    • 初始化ROS节点
    • 订阅需要的话题
    • 循环等待话题消息,接受到消息后进行回调函数
    • 回调函数中完成消息处理
  • 添加编译选项
    • 设置需要编译的代码和生成的可执行文件
    • 设置链接库
    • 设置依赖
  • 运行可执行程序

talker.cpp

#include<sstream>
#include"ros/ros.h"
#include"std_msgs/String.h"
int main(int argc,char **argv)
{//ROS节点初始化ros::init(argc,argv,"talker");//创建节点句柄ros::NodeHandle n;//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::Stringros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter",1000);//设置循环的频率ros::Rate loop_rate(10);int count=0;while(ros::ok()){//初始化std_msgs::String类型的消息std_msgs::String msg;std::stringstream ss;ss<<"hello world"<<count;msg.data=ss.str();//发布消息ROS_INFO("%s",msg.data.c_str());chatter_pub.publish(msg);//循环等待回调函数ros::spinOnce();//接受循环频率延时loop_rate.sleep();++count;}return 0;
}

listener.cpp

#include"ros/ros.h"
#include"std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{//将接收到的消息打印处理ROS_INFO("I heard:{%s}",msg->data.c_str());
}
int main(int argc,char **argv)
{//初始化ROS节点ros::init(argc,argv,"listener");//创建节点句柄ros::NodeHandle n;//创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallbackros::Subscriber sub=n.subscribe("chatter",1000,chatterCallback);//循环等待回调函数ros::spin();return 0;
}

在CMakeLists.txt末尾添加编译选项

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})

编译

cd catkin_ws
catkin_make

在这里插入图片描述
运行程序

# 以下是对于Ubantu 16.04的操作,其他版本的也许操作会简洁很多
roscore
#打开新终端
cd ~/catkin_ws
#下面这一步是为了保证rosrun命令能够找到相应的功能包,有可以省去这一步骤的方法,各位可以自行查找
source ~/catkin_ws/devel/setup.bash
rosrun learning_communication talker
#打开新终端
cd ~/catkin_ws
source ~/catkin_ws/devel/setup.bash
rosrun learning_communication listener

在这里插入图片描述
如图,发送了hello world的同时接收了hello world。

二、服务编程

定义服务请求与应答的方式

  • 定义srv文件
     mkdir ~/catkin_ws/src/learning_communication/srvsudo nano AddTwoInts.srv
    
  • AddTwoInts.srv
    int64 a
    int64 b
    ---
    int64 sum
    
  • 用gedit打开package.xml,在里面添加功能包依赖
    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>
    
  • 在CMakeLists.txt添加编译选项
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
步骤:

  • 创建服务器
    • 初始化ROS节点
    • 创建Serve实例
    • 循环等待服务请求,进入回调函数
    • 在回调函数中完成服务功能的处理,并反馈应答数据
  • 创建客户端
    • 初始化ROS节点
    • 创建一个Client实例
    • 发布服务请求数据
    • 等待Serve处理之后的应答结果
  • 添加编译选项
    • 设置需要编译的代码和生成的可执行文件
    • 设置链接库
    • 设置依赖
  • 运行可执行程序
    server.cpp
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
//service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{//将输入的参数中的请求数据相加,结果放到应答变量中res.sum=req.a+req.b;ROS_INFO("request: x=%1d,y=%1d",(long int)req.a,(long int)req.b);ROS_INFO("sending back response:[%1d]",(long int)res.sum);return true;
}
int main(int argc,char **argv)
{//ROS节点初始化ros::init(argc,argv,"add_two_ints_server");//创建节点句柄ros::NodeHandle n;//创建一个名为add_two_ints的server,注册回调函数add()ros::ServiceServer service=n.advertiseService("add_two_ints",add);//循环等待回调函数ROS_INFO("Ready to add two ints.");ros::spin();return 0;
}

client.cpp

#include<cstdlib>
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
int main(int argc,char **argv)
{//ROS节点初始化ros::init(argc,argv,"add_two_ints_client");//从终端命令行获取两个加数if(argc!=3){ROS_INFO("usage:add_two_ints_client X Y");return 1;}//创建节点句柄ros::NodeHandle n;//创建一个client,请求add_two_ints_service//service消息类型是learning_communication::AddTwoIntsros::ServiceClient client=n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");//创建learning_communication::AddTwoInts类型的service消息learning_communication::AddTwoInts srv;srv.request.a=atoll(argv[1]);srv.request.b=atoll(argv[2]);//发布service请求,等待加法运算的应答请求if(client.call(srv)){ROS_INFO("sum: %1d",(long int)srv.response.sum);}else{ROS_INFO("Failed to call service add_two_ints");return 1;}return 0;
}

关于编译时一直出现这样的报错,注意看是不是有些比如这个符号“_”没打。
在这里插入图片描述
添加编译设置
在这里插入图片描述
编译通过
在这里插入图片描述
输入指令

roscore
#打开新终端
source ~/catkin_ws/devel/setup.bash
rosrun learning_communication server
#打开新终端
source ~/catkin_ws/devel/setup.bash
rosrun learning_communication client 11 12

在这里插入图片描述

三、动作编程

动作是一种基于ROS消息实现的问答通信机制,它包含连续反馈,可以在任务过程中止运行。
动作(Action)的接口
在这里插入图片描述
练习ROS动作编程: 客户端发送一个运动坐标,模拟机器人运动到目标位置的过程。包括服务端和客户端的代码实现,要求带有实时位置反馈。

创建工作区间

#创建功能包
cd catkin_ws/src/
catkin_create_pkg learn_action std_msgs rospy roscpp
#编译功能包
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash

在这里插入图片描述
创建action文件夹,并在里面创建TurtleMove.action文件

# Define the goal 
float64 turtle_target_x  
# Specify Turtle's target position 
float64 turtle_target_y 
float64 turtle_target_theta 
---
# Define the result 
float64 turtle_final_x 
float64 turtle_final_y 
float64 turtle_final_theta 
--- 
# Define a feedback message 
float64 present_turtle_x 
float64 present_turtle_y 
float64 present_turtle_theta

在learn_action的src文件夹下,创建TurtleMove_server.cpp文件和TurtleMove_client.cpp文件
在这里插入图片描述
TurtleMove_server.cpp

  /*      此程序通过通过动作编程实现由client发布一个目标位置    然后控制Turtle运动到目标位置的过程  */ 
#include <ros/ros.h> 
#include <actionlib/server/simple_action_server.h> 
#include "learn_action/TurtleMoveAction.h" 
#include <turtlesim/Pose.h>  
#include <turtlesim/Spawn.h> 
#include <geometry_msgs/Twist.h>   
typedef actionlib::SimpleActionServer<learn_action::TurtleMoveAction> Server;   
struct Myturtle 
{     float x;     float y;     float theta; }turtle_original_pose,turtle_target_pose;   ros::Publisher turtle_vel;  void posecallback(const turtlesim::PoseConstPtr& msg)  {    ROS_INFO("Turtle1_position:(%f,%f,%f)",msg->x,msg->y,msg->theta);   turtle_original_pose.x=msg->x;    turtle_original_pose.y=msg->y;   turtle_original_pose.theta=msg->theta;  }   // 收到action的goal后调用该回调函数 void execute(const learn_action::TurtleMoveGoalConstPtr& goal, Server* as) {     learn_action::TurtleMoveFeedback feedback;       ROS_INFO("TurtleMove is working.");     turtle_target_pose.x=goal->turtle_target_x;     turtle_target_pose.y=goal->turtle_target_y;      turtle_target_pose.theta=goal->turtle_target_theta;          geometry_msgs::Twist vel_msgs;     float break_flag;          while(1)     {           ros::Rate r(10);                  vel_msgs.angular.z = 4.0 * (atan2(turtle_target_pose.y-turtle_original_pose.y,                                    turtle_target_pose.x-turtle_original_pose.x)-turtle_original_pose.theta);         vel_msgs.linear.x = 0.5 * sqrt(pow(turtle_target_pose.x-turtle_original_pose.x, 2) +                                       pow(turtle_target_pose.y-turtle_original_pose.y, 2));          break_flag=sqrt(pow(turtle_target_pose.x-turtle_original_pose.x, 2) +                                         pow(turtle_target_pose.y-turtle_original_pose.y, 2));         turtle_vel.publish(vel_msgs);feedback.present_turtle_x=turtle_original_pose.x;         feedback.present_turtle_y=turtle_original_pose.y;         feedback.present_turtle_theta=turtle_original_pose.theta;         as->publishFeedback(feedback);         ROS_INFO("break_flag=%f",break_flag);         if(break_flag<0.1) break;         r.sleep();     }         // 当action完成后,向客户端返回结果         ROS_INFO("TurtleMove is finished.");         as->setSucceeded();
}   
int main(int argc, char** argv) 
{     ros::init(argc, argv, "TurtleMove_server");     ros::NodeHandle n,turtle_node;     ros::Subscriber sub =turtle_node.subscribe("turtle1/pose",10,&posecallback);//订阅小乌龟的位置信息     turtle_vel = turtle_node.advertise<geometry_msgs::Twist>("turtle1/cmd_vel",10);//发布控制小乌龟运动的速度     // 定义一个服务器         Server server(n, "TurtleMove", boost::bind(&execute, _1, &server), false);        // 服务器开始运行         server.start();         ROS_INFO("server has started.");     ros::spin();       return 0;
} 

TurtleMove_client.cpp

#include <actionlib/client/simple_action_client.h> 
#include "learn_action/TurtleMoveAction.h" 
#include <turtlesim/Pose.h>  
#include <turtlesim/Spawn.h> 
#include <geometry_msgs/Twist.h>   
typedef actionlib::SimpleActionClient<learn_action::TurtleMoveAction> Client;   
struct Myturtle 
{     float x;     float y;   float theta; 
}turtle_present_pose;   
// 当action完成后会调用该回调函数一次 
void doneCb(const actionlib::SimpleClientGoalState& state,         const learn_action::TurtleMoveResultConstPtr& result) 
{     ROS_INFO("Yay! The TurtleMove is finished!");     ros::shutdown(); 
}   
// 当action激活后会调用该回调函数一次 
void activeCb() 
{     ROS_INFO("Goal just went active"); 
}   
// 收到feedback后调用该回调函数 
void feedbackCb(const learn_action::TurtleMoveFeedbackConstPtr& feedback) 
{     ROS_INFO(" present_pose : %f  %f  %f", feedback->present_turtle_x,                    feedback->present_turtle_y,feedback->present_turtle_theta); 
}   
int main(int argc, char** argv) 
{     ros::init(argc, argv, "TurtleMove_client");       // 定义一个客户端     Client client("TurtleMove", true);       // 等待服务器端     ROS_INFO("Waiting for action server to start.");     client.waitForServer();     ROS_INFO("Action server started, sending goal.");      // 创建一个action的goal     learn_action::TurtleMoveGoal goal;    goal.turtle_target_x = 1;     goal.turtle_target_y = 1;     goal.turtle_target_theta = 0;       // 发送action的goal给服务器端,并且设置回调函数     client.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);       ros::spin();      return 0; 
} 

在package.xml里面添加依赖

<build_depend>message_generation</build_depend>  
<build_depend>actionlib</build_depend>  
<build_depend>actionlib_msgs</build_depend>
<exec_depend>message_runtime</exec_depend>  
<exec_depend>actionlib</exec_depend>  
<exec_depend>actionlib_msgs</exec_depend> 

添加完就是这样
在这里插入图片描述
修改learn_action里面的CMakeLists.txt,添加代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加编译选项

add_executable(TurtleMove_client src/TurtleMove_client.cpp)
target_link_libraries(TurtleMove_client ${catkin_LIBRARIES})
add_dependencies(TurtleMove_client ${PROJECT_NAME}_gencpp)  add_executable(TurtleMove_server src/TurtleMove_server.cpp)
target_link_libraries(TurtleMove_server ${catkin_LIBRARIES})
add_dependencies(TurtleMove_server ${PROJECT_NAME}_gencpp) 

编译
在这里插入图片描述

roscore
#开一个新终端窗口
source ./devel/setup.bash
rosrun turtlesim turtlesim.node
#新终端
source ./devel/setup.bash
rosrun learn_action TurtleMove_server
#新终端
source ./devel/setup.bash
rosrun learn_action TurtleMove_client

运行结果如下
在这里插入图片描述

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

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

相关文章

stm32-编码器测速

一、编码器简介 编码电机 旋转编码器 A,B相分别接通道一和二的引脚&#xff0c;VCC&#xff0c;GND接单片机VCC&#xff0c;GND 二、正交编码器工作原理 以前的代码是通过触发外部中断&#xff0c;然后在中断函数里手动进行计次。使用编码器接口的好处就是节约软件资源。对于频…

从0开始回顾MySQL---事务四大特性

事务概述 事务是一个最小的工作单元。在数据库当中&#xff0c;事务表示一件完整的事儿。一个业务的完成可能需要多条DML语句共同配合才能完成&#xff0c;例如转账业务&#xff0c;需要执行两条DML语句&#xff0c;先更新张三账户的余额&#xff0c;再更新李四账户的余额&…

实现elasticsearch和数据库的数据同步

1. 数据同步 elasticsearch中的酒店数据来自于mysql数据库&#xff0c;因此mysql数据发生改变时&#xff0c;elasticsearch也必须跟着改变&#xff0c;这个就是elasticsearch与mysql之间的数据同步。 1.1. 思路分析 常见的数据同步方案有三种&#xff1a; 同步调用 异步通知…

面试题手撕篇

参考博客 开始之前&#xff0c;理解递归 手写 浅拷贝 function shallow(target){if(target instanceof Array){return [...resObj]}else{return Object.assign({},target);} }手写深拷贝 const _sampleDeepClone target > {// 补全代码return JSON.parse(JSON.stringify…

EtherCAT开源主站 IGH 介绍及主站伺服控制过程

目录 前言 IGH EtherCAT主站介绍 主要特点和功能 使用场景 SOEM 主站介绍 SOEM 的特点和功能 SOEM 的使用场景 IGH 主站 和 SOEM对比 1. 功能和复杂性 2. 资源消耗和移植性 3. 使用场景 EtherCAT 通信原理 EtherCAT主站控制伺服过程 位置规划模式 原点复归模式…

Ansible非标记语言YAML与任务剧本Playbook

前言 上篇介绍了 Ansible 单模块&#xff08;AD-Hoc&#xff09;的相关内容Ansible自动化运维Inventory与Ad-Hoc-CSDN博客&#xff0c;Ad-Hoc 命令是一次性的、即时执行的命令&#xff0c;用于在远程主机上执行特定任务&#xff0c;这些命令通常用于快速执行简单的任务。当需要…

MS08-067 漏洞利用与安全加固

文章目录 环境说明1 MS08_067 简介2 MS08_067 复现过程3 MS08_067 安全加固 环境说明 渗透机操作系统&#xff1a;2024.1漏洞复现操作系统: Windows XP Professional with Service Pack 2- VL (English)安全加固复现操作系统&#xff1a;Windows XP Professional with Service …

C语言案例2,请编程序将“China“译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母,变为Glmre,持续更新~

一.题目 /* 请编程序将“China”译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。 例如,字母“A”后面第4个字母是“E”&#xff0c;用“E”代替“A”。因此,“China”应译为“Glmre”。 请编一程序,用赋初值的方法使cl,c2&#xff0c;c3,c4,c5 这5个变量的值分…

YoloV5改进策略:下采样改进|HWD改进下采样

摘要 本文使用HWD改进下采样&#xff0c;在YoloV5的测试中实现涨点。 论文解读 在卷积神经网络&#xff08;CNNs&#xff09;中&#xff0c;极大池化或跨行卷积等下采样操作被广泛用于聚合局部特征、扩大感受野和最小化计算开销。然而&#xff0c;对于语义分割任务&#xff…

HTML_CSS练习:HTML注释

一、代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>HTML注释</title> </head> <body><marquee loop"1">马龙强<!--下面的输入框是可以滚动的&#x…

【Python】清理conda缓存的常用命令

最近发现磁盘空间不足&#xff0c;很大一部分都被anaconda占据了&#xff0c;下面是一些清除conda缓存的命令 清理所有环境的Anaconda包缓存 删除所有未使用的包以及缓存的索引和临时文件 conda clean --all清理某一特定环境的Anaconda包缓存 conda clean --all -n 环境名清…

【ansible】ansible的介绍和安装

前言运维自动化 云计算核心职能 搭建平台架构 日常运营保障 性能效率优化 相关工具 代码管理&#xff08;SCM&#xff09;&#xff1a;GitHub、GitLab、BitBucket、SubVersion 构建工具&#xff1a;maven、Ant、Gradle 自动部署&#xff1a;Capistrano、CodeDeploy 持续…

字符串函数(C语言详解)

1.字符串简介 字符串是一串连续的且以\0结尾的字符 char arr[]"zhangsan";//将字符串存到数组里面 char*a"lisi";//常量字符串 char arr1[]{z,h,a,n,g};//字符数组 注意&#xff1a; 1.以第一种形式初始化字符串时&#xff0c;计算机会自动在字符串末尾加…

GraspNet-baseline复现----Linux-Ubuntu

1.基本环境 Ubuntu 20.04Cuda 11.0 、cuDNN 80.0Python 3.7.16PyTorch 1.7.0 2.环境配置 PyTorch的版本对Cuda和Python的版本都有依赖&#xff0c;所以基本步骤是 确定需要安装的PyTorch版本 —> 通过 网站 确定对应的cuda版本和python版本 —> 创建虚拟环境配置环境。…

Node.js基础+原型链污染

Node.js基础 概述&#xff1a;简单来说Node.js就是运行在服务端的JavaScript&#xff0c;Node.js是一个基于Chrome JavaScript运行时建立的一个平台 大小写变换&#xff1a; toUpperCase&#xff08;&#xff09;&#xff1a;将小写字母转为大写字母&#xff0c;如果是其他字…

【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件详细说明

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…

使用FFmpeg源码配置程序configure查看所有支持的编码器/解码器/封装/解封装及网络协议

查看支持编码器: configure --list-encoders 查看支持编码器: configure --list-decoders 查看所有支持的封装: configure --list-muxers 查看所有支持的解封装: configure --list-demuxers 查看所有支持的网络通信协议: configure --list-protocols

解决jsp request.getParameter乱码问题(兼容Tomcat 6~8三个版本)

JSP页面写法&#xff1a; <% page contentType"text/html; charsetutf-8" language"java" %> <% page import"java.io.*" %> <%! int getServerVersion(HttpServletRequest request) {ServletContext application request.getS…

移远通信亮相AWE 2024,以科技力量推动智能家居产业加速发展

科技的飞速发展&#xff0c;为我们的生活带来了诸多便利&#xff0c;从传统的家电产品到智能化的家居设备&#xff0c;我们的居家生活正朝着更智能、更便捷的方向变革。 3月14日&#xff0c;中国家电及消费电子博览会&#xff08;Appliance&electronics World Expo&#xf…

【物联网】Modbus 协议及Qinghub物联网平台应用

Modbus 协议简介 QingHub设计器在设计物联网数据采集时不可避免的需要针对Modbus协议的设备做相关数据采集&#xff0c;这里就我们的实际项目经验分享Modbus协议 你可以通过QingHub作业直接体验试用&#xff0c;也可以根据手册开发相应的代码块。 qinghub项目已经全面开源。 …