ROS——多个海龟追踪一个海龟实验

目标

  • 通过键盘控制一个海龟(领航龟)的移动,其余生成的海龟通过监听实现追踪
  • 定期获取领航龟和其余龟的坐标信息,通过广播告知其余龟,进行相应移动
  • 其余龟负责监听

疑惑点(已解决)

int main(int argc, char** argv) 是 C 和 C++ 程序中主函数 (main) 的常见定义形式。这个函数是程序的入口点,操作系统在启动程序时首先调用 main 函数。

参数解释:

int argc:代表 “argument count”,是一个整型变量,表示传递给程序的命令行参数的数量(包括程序名称本身)。例如,如果你的程序名为 myprog,并且在命令行下以 myprog arg1 arg2 的方式运行,那么 argc 将为 3(程序名 myprog 计为第一个参数)。
char** argv:代表 “argument vector”,是一个字符指针数组的指针,每个元素都是指向一个字符串的指针。这个数组包含了所有通过命令行传递给程序的参数。argv[0] 总是指向程序的名称,而 argv[1]、argv[2] 等分别指向后续的各个参数。每个参数都是一个以空字符 ‘\0’ 结尾的字符串。
main 函数返回类型为 int,通常用来表示程序的退出状态。返回值为 0 表示程序正常结束,非零值则表示有错误发生,具体的数值可以根据需要定义,但通常的约定是返回负数或非零正数表示异常终止。

生成海龟

在这里插入图片描述

生成执行文件及相关依赖

add_executable(fllow_broadcaster src/turtle_broadcaster.cpp)
target_link_libraries(fllow_broadcaster ${catkin_LIBRARIES})add_executable(fllow_listener src/turtle_listener.cpp)
target_link_libraries(fllow_listener ${catkin_LIBRARIES})add_executable(create_turtle src/spawn_turtle.cpp)
target_link_libraries(create_turtle ${catkin_LIBRARIES})

xml配置

<launch><node pkg="turtlesim" type="turtlesim_node" name="sim" /><node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen" /><!-- 生成多个海龟,这里的type指的是可执行文件的自定义名字--><node pkg="Fllowing_test" type="create_turtle" name="c_turtle" args="a b c d e f g" /> <!-- 构建多个海龟广播--><node pkg="Fllowing_test" type="fllow_broadcaster" args="turtle1" name="turtle1_broadcaster" /> <node pkg="Fllowing_test" type="fllow_broadcaster" args="a" name="turtle2_broadcaster" /><node pkg="Fllowing_test" type="fllow_broadcaster" args="b" name="turtle3_broadcaster" /><node pkg="Fllowing_test" type="fllow_broadcaster" args="c" name="turtle4_broadcaster" /><node pkg="Fllowing_test" type="fllow_broadcaster" args="d" name="turtle5_broadcaster" /><node pkg="Fllowing_test" type="fllow_broadcaster" args="e" name="turtle6_broadcaster" /><node pkg="Fllowing_test" type="fllow_broadcaster" args="f" name="turtle7_broadcaster" /> <node pkg="Fllowing_test" type="fllow_broadcaster" args="g" name="turtle8_broadcaster" /> <!-- 设置多个海龟之间的监听关系 --><node pkg="Fllowing_test" type="fllow_listener" args="turtle1 a" name="turtle1_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="a b" name="turtle2_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="b c" name="turtle3_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="c d" name="turtle4_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="d e" name="turtle5_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="e f" name="turtle6_tf_listener" /><node pkg="Fllowing_test" type="fllow_listener" args="f g" name="turtle7_tf_listener" />
</launch>

spawn_turtle.cpp

  • 测试指令:rosrun Fllowing_test create_turtle a b c d e (后续字母 + i 是自定义海龟名字)
#include <ros/ros.h>
#include <turtlesim/Spawn.h>int main(int argc ,char **argv){int i;if(argc < 2) {ROS_ERROR("Turtle's name can't be empty");return -1;}ros::init(argc,argv,"Create_turtle");ros::NodeHandle node;ros::service::waitForService("spawn");ros::ServiceClient create_turtle_client = node.serviceClient<turtlesim::Spawn>("spawn");turtlesim::Spawn srv;  //用于配置海龟信息for(i = 1;i < argc;++i){srv.request.x = i;srv.request.y = i;srv.request.theta = 0;srv.request.name = *(argv+i);create_turtle_client.call(srv);     //发送请求生成海龟的服务}return 0;
}

turtle_broadcaster

// 例程产生 tf 数据,并计算、发布 turtle2的速度指令
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>std::string turtle_name;//pose回调函数
void poseCallback(const turtlesim::PoseConstPtr& msg){//创建tf的广播器static tf::TransformBroadcaster br;//初始化tf数据tf::Transform transform;transform.setOrigin(tf::Vector3(msg->x,msg->y,0.0));   //当前海龟的坐标信息tf::Quaternion q;q.setRPY(0,0,msg->theta);   //当前海龟的RPY旋转状态transform.setRotation(q);//广播world与海龟坐标系之间的tf数据br.sendTransform(tf::StampedTransform(transform,ros::Time::now(),"world",turtle_name));
}int main(int argc,char** argv){ros::init(argc,argv,"turtle_broadcaster");//输入参数作为海龟的名字if(argc < 2){ROS_ERROR("need turtle name as argument!");return -1;}turtle_name = argv[1];   //argv[0]是程序文件名,argv[1]以及后续才是参数列表//订阅海龟位置ros::NodeHandle node;ros::Subscriber sub = node.subscribe(turtle_name+"/pose",10,&poseCallback);// 循环等待回调函数ros::spin();return 0;
}

turtle_listener.cpp

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <turtlesim/Spawn.h>
#include <geometry_msgs/Twist.h>
#include <string>
using namespace std;int main(int argc,char **argv){//拼接海龟驱动指令string driver_cmd("/");driver_cmd.append(argv[2]);driver_cmd.append("/cmd_vel");if(argc < 3){ROS_ERROR("need turtle name as argument!");return -1;}ros::init(argc,argv,"turtle_listener");ros::NodeHandle node;//请求产生海龟对象ros::service::waitForService("/spawn");ros::ServiceClient turtle = node.serviceClient<turtlesim::Spawn>("/spawn");turtlesim::Spawn srv_add_turtle;turtle.call(srv_add_turtle);//创建发布速度控制指令的发布者,控制海龟移动的ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>(driver_cmd,10);//创建tf的监听器tf::TransformListener listener;ros::Rate rate(10.0);while(node.ok()){//获取坐标系之间的tf数据tf::StampedTransform transform;try{// 判断坐标系中是否存在相应海龟节点,持续三秒,向广播者发送位置信息请求listener.waitForTransform(argv[2],argv[1],ros::Time(0),ros::Duration(3.0));// 获取实时位置,将四元数存到transform变量中listener.lookupTransform(argv[2],argv[1],ros::Time(0),transform);}catch(tf::TransformException &ex){ROS_ERROR("%s",ex.what());ros::Duration(1.0).sleep();continue;}//根据turtle1与turtle2坐标系之间的位置关系,配置移动信息,并发布turtle2的速度指令geometry_msgs::Twist vel_msg;vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),transform.getOrigin().x());vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(),2) + pow(transform.getOrigin().y(),2));turtle_vel.publish(vel_msg);rate.sleep();}return 0;
}

实验结果呈现

在这里插入图片描述

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

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

相关文章

k8s 部署RuoYi-Vue-Plus之redis搭建

1.直接部署一个pod 需要挂载存储款, 可参考 之前文章设置 https://blog.csdn.net/weimeibuqieryu/article/details/140183843 2.部署yaml 先创建命名空间ruoyi, 有就不用创建了 kubectl create namespace ruoyi创建部署文件 redis-deploy.yaml kind: PersistentVolume api…

程序员学长 | 快速学会一个算法,xLSTM

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学会一个算法&#xff0c;xLSTM 今天给大家分享一个超强的算法模型&#xff0c;xLSTM。 xLSTM&#xff08;Extended Long Short-Term Memory&…

Spring Boot的无缝衔接:深入解析与实践

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ &#x1f680;The begin&#x1f697;点点关注&#xff0c;收藏不迷路&#x1f6a9; 引言 在快速迭代的软件开发环境中&#xff0c;无缝衔接是提升开发效率、降低维护成本、增强系统稳定性的关键。Spring Boo…

Electron开发 - 如何在主进程Main中让node-fetch使用系统代理

背景 开发过程中&#xff0c;用户设置的系统代理是不同的&#xff0c;比如公司内的服务器&#xff0c;所以就要动态地使用系统代理来访问&#xff0c;但是主进程默认为控制台级别的请求&#xff0c;不走系统代理&#xff0c;除非你指定系统代理配置&#xff0c;这个就就有了这…

轻松上手MYSQL:MYSQL事务隔离级别的奇幻之旅

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索MYSQL索引数据结构之旅✨ &#x1f44b; 大家好&#xff01;文本学习…

【话题】IT专业入门,高考假期预习指南

IT专业入门&#xff0c;高考假期预习指南 亲爱的高考学子们&#xff0c; 七月的阳光&#xff0c;如同你们的梦想&#xff0c;炽热而明亮。当你们手中的笔落下最后一道题的答案&#xff0c;那不仅仅是对过去十二年寒窗苦读的告别&#xff0c;更是对未知世界探索的启程号角。你们…

ExtruOnt——为工业 4.0 系统描述制造机械类型的本体

概述 论文地址 &#xff1a;https://arxiv.org/abs/2401.11848 原文地址&#xff1a;https://ai-scholar.tech/articles/ontology/ExtruOnt 在工业 4.0 应用场景中&#xff0c;以机器可解释代码提供的、语义丰富的制造机械描述可以得到有效利用。然而&#xff0c;目前显然还缺…

无锡哲讯:SAP赋能汽车零配件行业,加速企业数字化转型

汽车零配件行业作为汽车工业的重要支撑&#xff0c;正处在一个快速变化和高度竞争的市场环境中。随着科技的不断进步和消费者需求的日益多样化&#xff0c;如何通过高效的资源管理和生产流程优化&#xff0c;提升竞争力&#xff0c;已成为汽车零配件企业亟待解决的问题。无锡哲…

玩转springboot之springboot项目监测

项目监测 springboot中提供了actuator项目来进行监测和度量 基于springboot2.x版本 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency> actuator中提…

【数智化人物展】天云数据CEO雷涛:大模型连接数据库 为数智化提供高价值数据...

雷涛 本文由天云数据CEO雷涛投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 这几天&#xff0c;奥特曼讲SQL数据库和大模型结合起来会产生什么样的化学变化引起行业关注。为…

大模型备案全网最详细流程【附附件】

本文要点&#xff1a;大模型备案最详细说明&#xff0c;大模型备案条件有哪些&#xff0c;《算法安全自评估报告》模板&#xff0c;大模型算法备案&#xff0c;大模型上线备案&#xff0c;生成式人工智能(大语言模型)安全评估要点&#xff0c;网信办大模型备案。 大模型备案安…

Geoserver源码解读五 Catalog

系列文章目录 Geoserver源码解读一 环境搭建 Geoserver源码解读二 主入口 Geoserver源码解读三 GeoServerBasePage Geoserver源码解读四 REST服务 Geoserver源码解读五 Catalog 目录 系列文章目录 前言 一、定义 二、前置知识点 1.Spring 的 Bean 生命周期 ApplicationCon…

中国石油大学(华东)24计算机考研数据速览,计科学硕复试线288分!

中国石油大学&#xff08;华东&#xff09;计算机与通信工程学院是中国石油大学(华东)十三个教学院部之一&#xff0c;其前身是创建于1984年的计算机科学系&#xff0c;2001年撤系建院。伴随着学校50多年的风雨历程&#xff0c;计算机与通信工程学院也已经有了20多年的发展历史…

神经网络和算力共享结合:基于深度学习的算力资源智能分配机制;一种支持跨云、跨边缘计算平台的协同训练框架(联邦学习);模型自适应优化策略

目录 神经网络和算力共享结合 论文标题 摘要 引言 理论基础 技术实现 创新点 实验验证 结论与展望 基于深度学习的算力资源智能分配机制 一、机制概述 二、关键技术 三、应用场景 四、优势与挑战 优势 挑战 五、未来展望 一种支持跨云、跨边缘计算平台的协同…

5.pwn Linux的延迟绑定机制

动态链接库 我们程序开发过程中都会用到系统函数&#xff0c;比如read&#xff0c;write&#xff0c;open等等 这些系统函数不需要我们实现&#xff0c;因为系统已经帮你完成这些工作&#xff0c;只需要调用即可&#xff0c;存放这些函数的库文件就是动态链接库。 通常情况下&…

[激光原理与应用-100]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 4 - 3C电池行业应用 - 不同的电池类型、焊接方式类型

目录 前言&#xff1a; 一、激光在3C行业的应用概述 1.1 概述 1.2 激光焊接在3C-电池行业的应用 1.3 动力电池的激光焊接工艺 1.3.1 概述 1.3.2 动力电池常见的焊接应用 1.电池壳体与盖板焊接 2.电池防爆阀密封 焊接 二、不同的电池的外形 2.1 软包锂电池 2.1.1 概述…

《机器学习》读书笔记:总结“第4章 决策树”中的概念

&#x1f4a0;决策树 基于树结构进行决策。 一棵决策树包括&#xff1a; 一个 根节点&#xff08;起点&#xff09;若干 叶节点&#xff08;没有下游节点的节点&#xff09;若干 内部节点(分支节点) 即&#xff1a; #mermaid-svg-Mxe3d0kNg29PM2n8 {font-family:"treb…

Open3D 删除点云中重叠的点(方法二)

目录 一、概述 1.1原理 1.2应用 二、代码实现 三、实现效果 3.1原始点云 3.2处理后点云 3.3数据对比 一、概述 在点云处理中&#xff0c;重叠点&#xff08;即重复点&#xff09;可能会对数据分析和处理的结果产生负面影响。因此&#xff0c;删除重叠点是点云预处理中常…

NextJs - SSR渲染解决antd首屏加载CSS样式的闪烁问题

NextJs - SSR渲染解决antd首屏加载CSS样式的闪烁问题 闪烁现状解决方案 闪烁现状 我们写一个非常简单的页面&#xff1a; import { Button } from antdexport default async function Page() {return <><Button typeprimary>AAA</Button></> }NextJs…

《昇思25天学习打卡营第14天|onereal》

第14天学习内容如下&#xff1a; Diffusion扩散模型 本文基于Hugging Face&#xff1a;The Annotated Diffusion Model一文翻译迁移而来&#xff0c;同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成功运行。如您下载本文档为Python文件&#xff0c…