ros2 launch 集合 gazebo yolov8 rviz2
目录
1. ros2 yolov8 检测需要以来一些库,分别是:rclpy cv_bridge std_msgs sensor_msgs sensor_msgs_py vision_msgs
2. 创建一个新的功能包
3. 建立 yolo_launch.py 里面先加载gazebo和rviz2,在创建好本地的yolov8的node文件后也加入进来。
4. 创建好本地的yolov8的node文件
5. 修改setup.py文件
6. 编译包
7. 运行launch文件
1. ros2 yolov8 检测需要以来一些库,分别是:rclpy cv_bridge std_msgs sensor_msgs sensor_msgs_py vision_msgs
(1) rclpy Python语言的ROS Client Library,操作ROS2的节点话题服务
(2) cv-bridge 在ROS图像消息和OpenCV图像之间进行转换的一个功能包
(3) std-msgs 一种标准消息类型包,包含了一些常用的基本数据类型的消息定义
以上设计的是图像依赖的,下面两个是获取其他数据类型的
---------------------------------------------------------------
(4) sensor-msgs-py point_cloud2模块
(5) vision-msgs ROS的与算法无关的计算机视觉消息类型,ROS视觉信息介绍该软件包定义了一组消息,以统一ROS中的计算机视觉和对象检测工作
# 库安装命令如下:
sudo apt-get install ros-galactic-rclpy
sudo apt-get install ros-galactic-cv-bridge
sudo apt-get install ros-galactic-std-msgs
sudo apt-get install ros-galactic-sensor-msgs-py
sudo apt-get install ros-galactic-vision-msgs
2. 创建一个新的功能包
ros2 pkg create ros_yolov8 --build-type ament_python --node-name detect_node --dependencies rclpy cv_bridge std_msgs sensor_msgs sensor_msgs_py vision_msgs
运行结果:
going to create a new package package name: ros_yolov8 destination directory: package format: 3 version: 0.0.0 description: TODO: Package description maintainer: licenses: ['TODO: License declaration'] build type: ament_python dependencies: ['rclpy', 'cv_bridge', 'std_msgs', 'sensor_msgs', 'sensor_msgs_py', 'vision_msgs'] node_name: detect_node creating folder ./ros_yolov8 creating ./ros_yolov8/package.xml creating source folder creating folder ./ros_yolov8/ros_yolov8 creating ./ros_yolov8/setup.py creating ./ros_yolov8/setup.cfg creating folder ./ros_yolov8/resource creating ./ros_yolov8/resource/ros_yolov8 creating ./ros_yolov8/ros_yolov8/__init__.py creating folder ./ros_yolov8/test creating ./ros_yolov8/test/test_copyright.py creating ./ros_yolov8/test/test_flake8.py creating ./ros_yolov8/test/test_pep257.py creating ./ros_yolov8/ros_yolov8/detect_node.py
# ./ros_yolov8/package.xml
<?xml version="1.0"?>
......<depend>rclpy</depend>
<depend>cv_bridge</depend>
<depend>std_msgs</depend>
<depend>sensor_msgs</depend>
<depend>sensor_msgs_py</depend>
<depend>vision_msgs</depend>......
</package>
3. 建立 yolo_launch.py 里面先加载gazebo和rviz2,在创建好本地的yolov8的node文件后也加入进来。
# 创建一个新目录来存储(launch)启动文件
cd ./ros_yolov8 && mkdir launch
cd ./ros_yolov8/launch && touch detect_demo.launch.py
tree ./ros_yolov8/launch
运行结果:
./ros_yolov8/launch └── detect_demo.launch.py
#!/usr/bin/python3
# ./ros_yolov8/launch/detect_demo.launch.pyimport osfrom ament_index_python.packages import get_package_share_directoryfrom launch import LaunchDescription
from launch_ros.actions import Nodefrom launch.substitutions import LaunchConfiguration
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfConditionfrom launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSourcedef generate_launch_description():# all kinds of file pathros_root_path = "/xxx/ros2_ws"try:pkg_name = "ros_yolov8"share_pkg_path = get_package_share_directory(pkg_name)except:share_pkg_path = os.path.join(ros_root_path, "install", pkg_name, "share", pkg_name)print(f"{share_pkg_path=}")assert os.path.exists(share_pkg_path)# -1-Include the Gazebo launch file, provided by the gazebo_ros packageworld_file_path = os.path.join(share_pkg_path, 'worlds', 'yolo.world')# 包含其它的launch文件 :/opt/ros/galactic/share/gazebo_ros/launch/gazebo.launch.py# $ ros2 launch /opt/ros/galactic/share/gazebo_ros/launch/gazebo.launch.py world:=/xxx/yolo.worldgazebo_ros_dirpath = get_package_share_directory('gazebo_ros')print(f"{gazebo_ros_dirpath=}")gazebo_launch_filepath = os.path.join(gazebo_ros_dirpath, 'launch', 'gazebo.launch.py')print(f"{gazebo_launch_filepath=}")assert os.path.exists(gazebo_launch_filepath)# -2-Include the Rviz2 config file, provided by the rviz2 package# /opt/ros/galactic/lib/rviz2/rviz2# $ ros2 run rviz2 rviz2 -d # start rviz2rviz_filepath = os.path.join(share_pkg_path, 'rviz2', 'yolo.rviz')print(f"{rviz_filepath=}")assert os.path.exists(rviz_filepath)# Nodesgazebo_cmd = IncludeLaunchDescription(PythonLaunchDescriptionSource([gazebo_launch_filepath]),launch_arguments={'world': world_file_path}.items())static_transform_cmd = Node(package='tf2_ros',executable='static_transform_publisher',name='static_transform_publisher',arguments=["0", "0", "0", "0", "0", "0", "map", "camera_link_optical"],output='screen')start_rviz_cmd = Node(package='rviz2',executable='rviz2',name='rviz2',arguments=['-d', rviz_filepath],output='screen')# Launch arguments# start yolov8_nodestart_yolov8_node = Node(package='ros_yolov8',executable='yolov8_node',name='yolov8_node',output='screen',arguments=["-model", "/xxx/yolo.pt"])# Add everything to launch description and returnld = LaunchDescription()ld.add_action(gazebo_cmd)ld.add_action(static_transform_cmd)ld.add_action(start_rviz_cmd)ld.add_action(start_yolov8_node)return ld"""
/opt/ros/galactic/lib/tf2_ros/static_transform_publisher
# ros2 run tf2_ros static_transform_publisher "0" "0" "0" "0" "0" "0" "map" "camera_link_optical"
# -2-1- map axis between origin and world
"""
4. 创建好本地的yolov8的node文件
# ./ros_yolov8/ros_yolov8/yolov8_node.pyimport os
import sys
import time
import argparse
import random
import torch
# ROS2的客户端库(python) rclpy
import rclpy
from rclpy.qos import qos_profile_sensor_data
from rclpy.node import Node
# image-----below----
# topic sensor_msgs/msg/Image to cv2
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
# yolov8
from ultralytics import YOLOdef parse_argument():parser = argparse.ArgumentParser(description='detect image from topic (gazebo)')parser.add_argument('-model', type=str, default='/xxx/yolo.pt')parser.add_argument('-device', type=str, default='cpu')parser.add_argument('-conf_threshold', type=float, default=0.5)parser.add_argument('-iou_threshold', type=float, default=0.7)parser.add_argument('-enable', type=bool, default=True)parser.add_argument('-input_image_topic', type=str, default='/camera/image_raw')parser.add_argument('-show_inference_image', type=bool, default=True)parser.add_argument('-save', type=bool, default=False)args, unknown = parser.parse_known_args()return argsclass Yolov8Node(Node):# Node constructordef __init__(self) -> None:super().__init__("yolov8_node")# node paramsself.args = parse_argument()#self._class_to_color = {}self.cv_bridge = CvBridge()# yoloself.yolo = YOLO(self.args.model)self.yolo.fuse()print(f"{self.args.device=}")self.yolo.to(self.args.device)# topic publishers & subscribersself._infer_pub = self.create_publisher(Image, "inference_image", 10)self._image_sub = self.create_subscription(Image,self.args.input_image_topic,self.image_cb,qos_profile_sensor_data)def image_cb(self, msg: Image) -> None:# if self.args.enable:# record start timefps_start_t = time.time()# convert to cv image & predictcv_image = self.cv_bridge.imgmsg_to_cv2(msg)infer_start_t = time.perf_counter()results = self.yolo.predict(source=cv_image,verbose=False,stream=False,conf=self.args.conf_threshold,iou=self.args.iou_threshold,show=self.args.show_inference_image,mode="predict",save=self.args.save)end_time = time.perf_counter()# visualize the results on the frameannotated_image = results[0].plot()# record the end time and calculate FPSfps = 1.0 / (end_time - fps_start_t)cv2.putText(annotated_image, "FPS: {:.2f}".format(fps), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)results = results[0].cpu()for b in results.boxes:label = self.yolo.names[int(b.cls)]score = float(b.conf)if score < self.args.conf_threshold:continue# get boxes valuesbox = b.xywh[0]x_center = float(box[0])y_center = float(box[1])x_size = float(box[2])y_size = float(box[3])x_min = round(x_center - x_size / 2.0)x_max = round(x_center + x_size / 2.0)y_min = round(y_center - y_size / 2.0)y_max = round(y_center + y_size / 2.0)# draw boxes for debuggingif label not in self._class_to_color:r = random.randint(0, 255)g = random.randint(0, 255)b = random.randint(0, 255)self._class_to_color[label] = (r, g, b)color = self._class_to_color[label]cv2.rectangle(cv_image, (x_min, y_min), (x_max, y_max), color, 2)label = "{} ({:.3f})".format(label, score)pos = (x_min + 5, y_min + 25)font = cv2.FONT_HERSHEY_SIMPLEXcv2.putText(cv_image, label, pos, font,1, color, 1, cv2.LINE_AA)# append msgself._infer_pub.publish(self.cv_bridge.cv2_to_imgmsg(annotated_image, encoding=msg.encoding))def main():rclpy.init()node = Yolov8Node()rclpy.spin(node)node.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()
5. 修改setup.py文件
# ./ros_yolov8/setup.py
from setuptools import setup
import os
from glob import globpackage_name = 'ros_yolov8'setup(name=package_name,version='0.0.0',packages=[package_name],# new ros2_ws/install/{package_name}/share/*, copy from src/{package_name}/*data_files=[('share/ament_index/resource_index/packages', ['resource/' + package_name]),('share/' + package_name, ['package.xml']),# During installation, we need to copy the launch files(os.path.join('share', package_name, "launch"), glob('launch/*launch.[pxy][yma]*')),# Same with the RViz2 configuration file.(os.path.join('share', package_name, "rviz2"), glob('rviz2/*')),# And the Gazebo world files.(os.path.join('share', package_name, "worlds"), glob('worlds/*')),# And the config files.(os.path.join('share', package_name, "config"), glob('config/*')),],
......
6. 编译包
source /opt/ros/galactic/setup.bash
colcon build --packages-select ros-yolov8
. install/setup.bash
7. 运行launch文件
ros2 launch /xxx/ros_yolov8/launch/detect_demo.launch.py
# 或
ros2 launch ros_yolov8 detect_demo.launch.py
相关文章:
ros2 launch 集合 gazebo yolov8 rviz2
目录 1. ros2 yolov8 检测需要以来一些库,分别是:rclpy cv_bridge std_msgs sensor_msgs sensor_msgs_py vision_msgs 2. 创建一个新的功能包 3. 建立 yolo_launch.py 里面先加载gazebo和rviz2,在创建好本地的yolov8的node文件后也加入进来。 4. 创建好本地的yol…...
SD NAND【商业】
SD NAND【商业】 前言版权推荐SD NAND外观NAND与TF卡的区别雷龙CS SD NAND(贴片式TF卡)性能体验及应用 最后 前言 2023-7-23 16:20:19 因为本人对硬件了解不是很多,所以该篇参考自官方文档。 以下内容源自《【商业】》 仅供学习交流使用 版权 禁止其他平台发布…...
实现任意进制(2—32)转换
2020/01/01 实现原理参考代码测试样例其他补充后记交流 实现原理 本程序借助10进制数为中介数据,实现任意进制数之间的相互转换(2-36进制范围) 需要注意的是,数值范围不可超出 long long int 所表示的范围,即所输入需…...
Spring Boot 集成 Redis 三种模式实践汇总
背景 项目的某个模块集成了 SpringBoot Redis 包,客户端使用 Lettuce,Redis 测试环境单机模式。但是现场反馈的 Redis 环境是集群,如果简单的修改 spring.redis 配置为集群的配置信息,程序能否能无缝衔接呢? 本文记录…...
MySQL DQL语法
MySQL DQL语法 DQL语法简介 DQL(Data Query Language)语句是一种用于从数据库中检索数据的语言。它主要用于数据查询和数据分析,而不是对数据库中的数据进行更新、插入或删除。DQL语句通常用于获取特定条件下的数据,进行聚合计算…...
算法之线性表1.1.1(7)带头结点链表的反向输出
设L为带头结点的单链表,编写算法实现从尾到头反向输出每个节点的值。 算法思想: 方法一:将链表压栈再输出,时间复杂度为O(n),空间复杂度为O(n) 方法二:用头插法重新建立单链表在输出,时间复杂度为O(n),空…...
设计模式三:抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种方式来创建一系列相关或相互依赖的对象,而无需指定具体实现类。 在软件开发中,有时候需要根据不同的条件或环境来创建一组相关的对象。抽象工…...
Linux用户权限问题详解
Linux用户权限问题详解 【一】Linux权限的概念(1)用户类型(2)如何切换用户(3)用户相关的一些命令 【二】Linux文件权限管理(1)文件访问者的分类(2)文件类型和…...
flask中的session介绍
flask中的session介绍 在Flask中,session是一个用于存储特定用户会话数据的字典对象。它在不同请求之间保存数据。它通过在客户端设置一个签名的cookie,将所有的会话数据存储在客户端。以下是如何在Flask应用中使用session的基本步骤: 首先…...
记录联想拯救者R720重装系统
文章目录 bios里找不到U盘启动项2023.7.23重装系统后数据记录C盘内存修改默认AppData的路径(亲测,没用) bios里找不到U盘启动项 制作好启动盘后,开机按F2进入bios后,找不到U盘启动项,如下图所示࿱…...
Spring Alibaba Sentinel实现集群限流demo
1.背景 1.什么是单机限流? 小伙伴们或许遇到过下图这样的限流配置 又或者是这样的Nacos动态配置限流规则: 以上这些是什么限流?没错,就是单机限流,那么单机限流有什么弊端呢? 假设我们集群部署3台机器&a…...
102、SOA、分布式、微服务之间有什么关系和区别?
SOA、分布式、微服务之间有什么关系和区别? 分布式架构是指将单体架构中的各个部分拆分,然后部署到不同的机器或进程中去,SOA和微服务基本上都是分布式架构师SOA是一种面向服务的架构,系统的所有服务都注册在总线上,当调用服务时…...
Ubuntu 20.04下的录屏与视频剪辑软件
ubuntu20.04下的录屏与视频剪辑 一、录屏软件SimpleScreenRecorder安装与使用 1、安装 2、设置录制窗口参数 3、开始录制 二、视频剪辑软件kdenlive的安装 1、安装 2、启动 一、录屏软件SimpleScreenRecorder安装与使用 1、安装 (1)直接在终端输入以下命…...
面试题 -- iOS数据存储
文章目录 一、如果后期需要增加数据库中的字段怎么实现,如果不使用CoreData呢?二、SQLite 数据存储是怎么用?三、简单描述下客户端的缓存机制?四、实现过多线程的Core Data 么?NSPersistentStoreCoordinator࿰…...
spring复习:(51)environment、systemProperties、systemEnvironment三个bean是在哪里被添加到容器的?
一、主类: package cn.edu.tju.study.service.anno;import cn.edu.tju.study.service.anno.config.MyConfig; import cn.edu.tju.study.service.anno.domain.Person; import com.sun.javafx.runtime.SystemProperties; import org.springframework.context.annotat…...
element ui 上传控件携带参数到后端
1.携带固定参数: 2.携带不固定参数: <el-row> <el-col :span"24"> <el-upload :multiple"false" :show-file-list"false" :on-success"f_h…...
scrapy分布式+指纹去重原理
1,指纹去重原理存在于 scrapy.util.requests 里面 需要安装的包 pip install scrapy-redis-cluster # 安装模块 pip install scrapy-redis-cluster0.4 # 安装模块时指定版本 pip install --upgrade scrapy-redis-cluster # 升级模块版本 2,setting配置 …...
FileHub使用教程:Github Token获取步骤,使用快人一步
FileHub介绍 filehub是我开发的一个免费文件存储软件,可存万物。软件仓库:GitHub - Sjj1024/s-hub: 一个使用github作为资源存储的软件 软件下载地址:。有问题可以留言或者提Issue, 使用第一步:获取Github Token 使…...
嵌入式开发:单片机嵌入式Linux学习路径
SOC(System on a Chip)的本质区别在于架构和功能。低端SOC如基于Cortex-M架构的芯片,如STM32和NXP LPC1xxx系列,不具备MMU(Memory Management Unit),适用于轻量级实时操作系统如uCOS和FreeRTOS。…...
Libvirt的virsh工具常用命令
在使用Libvirt的virsh工具时,以下是常见的一些命令: 连接到Hypervisor: virsh -c <URI>:连接到指定的Hypervisor,例如 virsh -c qemu:///system 连接到本地的QEMU/KVM Hypervisor。 虚拟机管理: list…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
