ROS2贪吃龟练习工程

本文是ROS2基础知识的综合小应用,练习如何创建工作包,创建Node,定义Topic和Service,以及通过LaunchFile启动多个节点。基础知识可以参考:ROS2基础编程,ROS2 Topics和Services,ROS2 LaunchFile和Parameter
更多内容,访问专栏目录获取实时更新。

创建工作包

ros2 pkg create turtlesim_greedy_turtle --build-type ament_python

创建节点

touch turtle_controller.py
touch turtle_spawner.py
chmod +x turtle_controller.py
chmod +x turtle_spawner.py

添加依赖

<depend>rclpy</depend>
<depend>turtlesim</depend>
<depend>geometry_msgs</depend>
<depend>my_robot_interfaces</depend>

创建Msg
Turtle.msg

string name
float64 x
float64 y
float64 theta

TurtleArray.msg

Turtle[] turtles

创建Srv
CatchTurtle.srv

string name
---
bool success

添加节点控制Turtle
turtle_controller.py

#!/usr/bin/env python3
import rclpy
import math
from functools import partial
from rclpy.node import Node
from turtlesim.msg import Pose
from geometry_msgs.msg import Twist
from my_robot_interfaces.msg import Turtle
from my_robot_interfaces.msg import TurtleArray
from my_robot_interfaces.srv import CatchTurtleclass TurtleControllerNode(Node):def __init__(self):super().__init__("turtle_controller")self.pose = Noneself.turtle_to_catch = Noneself.pose_subscriber = self.create_subscription(Pose, "turtle1/pose", self.callback_turtle_pose, 10)self.cmd_vel_publisher = self.create_publisher(Twist, "turtle1/cmd_vel", 10)self.alive_turtles_subscriber = self.create_subscription(TurtleArray, "alive_turtles", self.callback_alive_turtles, 10)self.control_loop_timer = self.create_timer(0.01, self.control_loop)def callback_turtle_pose(self, msg):self.pose = msgdef control_loop(self):if self.pose == None or self.turtle_to_catch == None:return# calcu the distance between current position and target positiondist_x = self.turtle_to_catch.x - self.pose.xdist_y = self.turtle_to_catch.y - self.pose.ydistance  = math.sqrt(dist_x * dist_x + dist_y * dist_y)# construct cmd_vel msg to control the turtlemsg = Twist()if distance <= 0.5:  # target reachedmsg.linear.x = 0.0   # stop the turtlemsg.angular.z = 0.0self.call_catch_turtle_server(self.turtle_to_catch.name)self.turtle_to_catch = Noneelse:                # move to the target positionmsg.linear.x = 2 * distance  # optimizegoal_theta = math.atan2(dist_y, dist_x)  # orientationdiff = goal_theta - self.pose.thetaif diff > math.pi:diff -= 2 * math.pielif diff < -math.pi:diff += 2 * math.pimsg.angular.z = 6 * diff  # optimizeself.cmd_vel_publisher.publish(msg)def callback_alive_turtles(self, msg):if len(msg.turtles) > 0:self.turtle_to_catch = msg.turtles[0]def call_catch_turtle_server(self, turtle_name):client = self.create_client(CatchTurtle, "catch_turtle")while not client.wait_for_service(1.0):self.get_logger().warn("Waiting for server...")request = CatchTurtle.Request()request.name = turtle_namefuture = client.call_async(request)future.add_done_callback(partial(self.callback_call_catch_turtle, turtle_name=turtle_name))def callback_call_catch_turtle(self, future, turtle_name):try:response = future.result()if not response.success:self.get_logger().error("Turtle " + str(turtle_name) + " could not be caught")except Exception as e:self.get_logger().error("Service call failed %r" & (e,))def main(args=None):rclpy.init(args=args)node = TurtleControllerNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

添加节点产生或移除Turtle

#!/usr/bin/env python3
import rclpy
import random
import math
from functools import partial
from rclpy.node import Node
from turtlesim.srv import Spawn
from turtlesim.srv import Kill
from my_robot_interfaces.msg import Turtle
from my_robot_interfaces.msg import TurtleArray
from my_robot_interfaces.srv import CatchTurtleclass TurtleSpawnerNode(Node):def __init__(self):super().__init__("turtle_spawner")self.declare_parameter("spawn_frequency", 1.0)self.declare_parameter("turtle_name_prefix", "turtle")self.spawn_frequency = self.get_parameter("spawn_frequency").valueself.turtle_name_prefix = self.get_parameter("turtle_name_prefix").valueself.turtle_counter = 0self.alive_turtles = []self.spawn_turtle_timer = self.create_timer(1.0 / self.spawn_frequency, self.spawn_new_turtle)self.alive_turtles_publisher = self.create_publisher(TurtleArray, "alive_turtles", 10)self.catch_turtle_service = self.create_service(CatchTurtle, "catch_turtle", self.callback_catch_turtle)def spawn_new_turtle(self):self.turtle_counter += 1name = self.turtle_name_prefix + "_" + str(self.turtle_counter)x = random.uniform(0.0, 10.0)y = random.uniform(0.0, 10.0)theta = random.uniform(0.0, 2 * math.pi)self.call_spawn_server(name, x, y, theta)def call_spawn_server(self, turtle_name, x, y, theta):client = self.create_client(Spawn, "spawn")while not client.wait_for_service(1.0):self.get_logger().warn("Waiting for server...")request = Spawn.Request()request.name = turtle_namerequest.x = xrequest.y = yrequest.theta = thetafuture = client.call_async(request)future.add_done_callback(partial(self.callback_call_spawn, turtle_name=turtle_name, x=x, y=y, theta=theta))def callback_call_spawn(self, future, turtle_name, x, y, theta):try:response = future.result()if response.name != "":self.get_logger().info("Turtle " + response.name + " is now alive")new_turtle = Turtle()new_turtle.name = turtle_namenew_turtle.x = xnew_turtle.y = ynew_turtle.theta = thetaself.alive_turtles.append(new_turtle)self.publish_alive_turtles()except Exception as e:self.get_logger().error("Service call failed %r" % (e,))def publish_alive_turtles(self):msg = TurtleArray()msg.turtles = self.alive_turtlesself.alive_turtles_publisher.publish(msg)def callback_catch_turtle(self, request, response):self.call_kill_server(request.name)response.success = Truereturn responsedef call_kill_server(self, turtle_name):client = self.create_client(Kill, "kill")while not client.wait_for_service(1.0):self.get_logger().warn("Waiting for server...")request = Kill.Request()request.name = turtle_namefuture = client.call_async(request)future.add_done_callback(partial(self.callback_call_kill, turtle_name=turtle_name))def callback_call_kill(self, future, turtle_name):try:future.result()for (i, turtle) in enumerate(self.alive_turtles):if turtle.name == turtle_name:del self.alive_turtles[i]self.publish_alive_turtles()breakexcept Exception as e:self.get_logger().error("Service call failed %r" & (e,))def main(args=None):rclpy.init(args=args)node = TurtleSpawnerNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

创建LaunchFile
在这里插入图片描述

不要忘记更新my_robot_bringup工作包的package.xml添加依赖

通过LaunchFile启动

ros2 launch my_robot_bringup turtlesim_greedy_turtle.launch.py

最终的效果:
在这里插入图片描述

如有错误,欢迎留言或来信指正:hbin6358@163.com

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

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

相关文章

python使用多种方法计算列表元素平方的技巧

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、使用列表推导式进行元素平方 二、使用map函数进行元素平方 三、循环遍历列表进行元素平…

外卖系统开发的技术栈和架构设计

开发一个功能完备且高效的外卖系统&#xff0c;需要选择合适的技术栈并设计良好的系统架构。本文将详细介绍外卖系统开发过程中常用的技术栈以及架构设计的关键要点&#xff0c;帮助开发者构建一个高性能、可扩展且易维护的外卖平台。 1. 技术栈选择 选择合适的技术栈是开发…

工控一体机5寸显示器电容触摸屏(YA05WK)产品规格说明书

如果您对工控一体机有任何疑问或需求&#xff0c;或者对如何集成工控一体机到您的业务感兴趣&#xff0c;可移步控芯捷科技。 一、硬件功能介绍 YA05WK是我公司推出的一款新型安卓屏&#xff0c;4核Cortex-A7 架构&#xff0c;主频1.2GHz的CPU。采用12V供电&#xff0c;标配5寸…

UML 在 vs-code上的快速使用

UML 在 vs-code上的快速使用 1.软件准备工作2.创建第一张甘特图2.1 创建 UML文件: xxxx. puml2.2 输入甘特图代码2.3 VS code 生成甘特图 结束 。 1.软件准备工作 使用的软件为&#xff1a;VS CODE使用插件 &#xff1a; PluntUML2.创建第一张甘特图 2.1 创建 UML文件: xxxx. …

认识NoSql

SQL是结构化的&#xff0c;NoSql是非结构化的 SQL是关联的&#xff1a; Nosql是无关联的&#xff1a; SQL采用的是SQL查询&#xff1a; 语法固定&#xff0c;好处是&#xff1a;只要是关系型数据库&#xff08;Mysql,Oracle&#xff09;&#xff0c;都能够使用相同的语句进行查…

计算机毕业设计 | SpringBoot个人博客管理系统(附源码)

1&#xff0c;绪论 1.1 背景调研 在互联网飞速发展的今天&#xff0c;互联网已经成为人们快速获取、发布和传递信息的重要渠道&#xff0c;它在人们政治、经济、生活等各个方面发挥着重要的作用。互联网上发布信息主要是通过网站来实现的&#xff0c;获取信息也是要在互联网中…

Javascript 基础知识 —— 重写数组方法

1、写一个函数&#xff0c;实现深度克隆对象 const obj {name: "LIYUFAN",age: 25,career: "初级前端工程师",info: {field: ["JS", "CSS", "HTML"],framework: ["React", "Vue", "Angular"…

521源码-免费手游下载-【烽火中原H5】深度体验:横版网页国战手游及WIN学习手工端

【烽火中原H5】深度体验&#xff1a;横版网页国战手游及WIN学习手工端全面解析,烽火中原H5】横板网页国战手游WIN学习手工端语音视频教程营运后台CDK授权后台, 喜欢国战手游的玩家们&#xff0c;你们期待已久的【烽火中原H5】现已上线&#xff01;这款游戏以横版网页的形式呈现…

揭开神秘的“位移主题”面纱 no.16

Kafka中神秘的内部主题&#xff08;Internal Topic&#xff09;__consumer_offsets。 consumer_offsets在Kafka源码中有个更为正式的名字&#xff0c;叫*位移主题*&#xff0c;即Offsets Topic。为了方便今天的讨论&#xff0c;我将统一使用位移主题来指代consumer_offsets。需…

记录贴 Elasticsearch的RestClient进行DSL查询

must&#xff1a;必须匹配每个子查询&#xff0c;类似“与” should&#xff1a;选择性匹配子查询&#xff0c;类似“或” must_not&#xff1a;必须不匹配&#xff0c;不参与算分&#xff0c;类似“非” filter&#xff1a;必须匹配&#xff0c;不参与算分 import cn.huto…

Kali 我来了

Kali 我来了 1、官网下载2、修改密码3、开启SSH远程登录服务4、关闭kali图形化界面 1、官网下载 官方链接: https://www.kali.org/ 下载链接: https://cdimage.kali.org/kali-2024.1/kali-linux-2024.1-vmware-amd64.7z 解压后 直接导入 VmWare 就可使用可爱的小 Kali 了。 …

LabVIEW机器设备的振动监测

振动监测是工业和机械维护中重要的一部分&#xff0c;通过检测和分析机械振动&#xff0c;提前发现潜在故障&#xff0c;确保设备的可靠运行。LabVIEW是一种强大的图形化编程环境&#xff0c;非常适合用于振动监测系统的开发和实施。以下从多个角度详细介绍LabVIEW在振动监测中…

管理能力学习笔记十一:如何通过反馈做好辅导

关于辅导的常见错误 辅导过于细致 辅导的首要障碍: 不相信对方的潜力需要有成长型思维&#xff1a;即便员工现在不OK&#xff0c;未来会更好因材施教&#xff1a;对不同风格的下属&#xff0c;采取不同的辅导风格 凡事亲力亲为 作为管理者&#xff0c;我们要做的是&#xf…

【Unity2D 2022:Particle System】添加粒子特效

一、创建粒子系统游戏物体 1. 创建粒子系统游戏物体Smog Effect 2. 给粒子特效添加精灵贴图 &#xff08;1&#xff09;启用Texture Sheet Animation&#xff08;纹理表动画&#xff09; &#xff08;2&#xff09;点击加号添加一个纹理&#xff0c;并将两张厌恶图片导入到纹理…

【YashanDB知识库】OCI驱动类问题定位方法

【标题】OCI驱动类问题定位方法 【需求分类】故障分析 【关键字】OCI 【需求描述】由于我们的OCI接口目前尚不完善&#xff0c;经常会遇见OCI接口能力不足导致应用功能无法运行的问题&#xff0c;需要定位手段确定底层是哪个接口报错 【需求原因分析】方便一线数据库管理员…

使用jdk自带jhat工具排查OOM问题

使用jdk自带jhat工具排查OOM问题 OOM java.lang.OutOfMemoryError: Java heap space排查步骤 编写一个测试类 public class TestJVM {Testpublic void test1() throws InstantiationException, IllegalAccessException {List<A> list new ArrayList<>();for (i…

做抖音小店什么类目最容易爆单?搞懂这三点就明白了!

大家好&#xff0c;我是电商糖果 我们刚接触电商的时候&#xff0c;一定经常听一些同行念叨&#xff0c;选择大于努力&#xff0c;类目大于一切。 很多电商人把选类目比做定生死。 类目选对了&#xff0c;让你轻松飞升不是问题&#xff0c;类目选错了&#xff0c;基本被判了…

【YOLOv10】使用yolov10训练自己的数据集/验证 /推理 /导出模型/ONNX模型的使用

YOLOv10: 实时端到端的目标检测。 性能 YOLOv10比最先进的YOLOv9延迟时间更低&#xff0c;测试结果可以与YOLOv9媲美&#xff0c;可能会成为YOLO系列模型部署的“新选择”。 目录 1 数据准备 2 配置文件 3 训练 4 验证 5 预测 6 导出模型 7 ONNX模型的使用 官方论文地址…

学习笔记——动态路由协议——OSPF(OSPF网络类型1)

五、OSPF网络类型 网络类型&#xff1a;是指运行OSPF网段的二层链路类型。 1、OSPF网络类型简介 (1) OSPF网络类型 MA(Multi-Access &#xff0c;多路访问)在一个网段内的节点数量不限制(一条链路上有多个访问点)。MA的网络一般分为两种&#xff1a; 1)广播式多路访问网络…

oracle数据库无法连接问题排查

查看数据库告警日志如下图。发现问题时间段&#xff0c;没有数据库服务故障报错&#xff0c;但是存在较多TNS-12535、12560、12170、00505错误&#xff1a; 通过检查问题时间段应用日志&#xff0c;也记录了Caused by:java.sql.SQLRecoverableException: IO 错误: Connection r…