ROS2手写自定义点云(PointCloud2)数据并发布

news2025/7/15 11:22:59

目录

  • 前言
  • 实现

前言

继续学习ROS2,最近把navigation2的路径规划部分学习了一遍,但是还没有进行测试,于是先把这个部分先空出来后面再总结。先写一个与避障有关系的如何自己发点云数据。

在nav2里面有一个非常重要的部分就是costmap部分,他决定了你的地图和障碍物信息,在costmap,costmap又分成了静态层,膨胀层,测距层,障碍层和体素(三位像素)层,英文原名分别是static layer, inflation layer, range layer, obstacle layer, and voxel layer

而障碍层和体素层订阅LaserScan话题和PointCloud2,就可以在costmap上生成障碍物信息,我想自己手写一个自定义点云数据来发布,这样可以自己定义障碍物在哪个地方,实现一些基本的测试。

环境

RO2 humble
Ubuntu22.04
navigation2

实现

参考博客
点云发布(pointcloud_publisher)之ROS2案例

点云数据类型包含了以下数据类型

  • uint32 height: 点云数据的高度,即点云数据有多少行。
  • uint32 width: 点云数据的宽度,即点云数据有多少列。
  • sensor_msgs/PointField[] fields: 一个数组,包含点云数据中每个点的属性信息,如x、y、z坐标、颜色信息等。
    • sensor_msgs/PointField[] fields 是一个数组,它包含了点云数据中每个点的属性信息。每个 PointField 表示一个点的属性,比如 x、y、z 坐标,颜色信息等。
    • PointField 包含以下字段:
      string name: 属性的名称。
      uint32 offset: 属性在点云数据中的偏移量,以字节为单位。
      uint8 datatype: 属性的数据类型,如浮点数、整数等。
      uint32 count 属性的数量,如 RGB 颜色信息有 3 个值。
  • bool is_bigendian: 标识点云数据的字节序,是否为大端字节序。
    • 字节序指的是一个多字节数据在内存中存储的顺序。在计算机中,有两种常用的字节序:大端字节序和小端字节序。在大端字节序中,数据的高位字节存储在低地址处,而在小端字节序中,数据的低位字节存储在低地址处
  • uint32 point_step: 每个点占用的字节数,包括每个属性的字节数和对齐字节。
  • uint32 row_step: 一行点云数据占用的字节数,等于width * point_step。
  • uint8[] data: 点云数据的二进制表示,每个点按照fields中定义的顺序存储。

但是其实根据官方给出的示例代码,我们能够改出我们想要的点云数据代码

官方例程

# Copyright 2020 Evan Flynn
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import numpy as np

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import PointCloud2
from sensor_msgs.msg import PointField
from sensor_msgs_py import point_cloud2
from std_msgs.msg import Header


class PointCloudPublisher(Node):

    rate = 30
    moving = True
    width = 100
    height = 100

    header = Header()
    header.frame_id = 'map'

    dtype = PointField.FLOAT32
    point_step = 16
    fields = [PointField(name='x', offset=0, datatype=dtype, count=1),
              PointField(name='y', offset=4, datatype=dtype, count=1),
              PointField(name='z', offset=8, datatype=dtype, count=1),
              PointField(name='intensity', offset=12, datatype=dtype, count=1)]

    def __init__(self):
        super().__init__('pc_publisher')
        self.publisher_ = self.create_publisher(PointCloud2, 'test_cloud', 10)
        timer_period = 1 / self.rate
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.counter = 0

    def timer_callback(self):
        self.header.stamp = self.get_clock().now().to_msg()
        x, y = np.meshgrid(np.linspace(-2, 2, self.width), np.linspace(-2, 2, self.height))
        z = 0.5 * np.sin(2*x-self.counter/10.0) * np.sin(2*y)
        points = np.array([x, y, z, z]).reshape(4, -1).T
        pc2_msg = point_cloud2.create_cloud(self.header, self.fields, points)
        self.publisher_.publish(pc2_msg)

        if self.moving:
            self.counter += 1


def main(args=None):
    rclpy.init(args=args)
    pc_publisher = PointCloudPublisher()
    rclpy.spin(pc_publisher)
    pc_publisher.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

效果如下
请添加图片描述

解释

官方的代码其实看起来很容易理解的,他的话题每隔1/30s发布一次,即1/30s更新一次点云数据点,在初始化对象的时候,他先初始化其fields数据格式,并设置好点云数据的大小,偏移量,数据类型。
点云的数据头就用通用的self.header.stamp = self.get_clock().now().to_msg()得到即可

最关键的其实就是他点云数据的生成。
首先你要先设定你的xyz数据格式,他为了实现一个面波动的效果,因此不是特别容易理解,但最本质的原理其实就是要把你的点的坐标表示出来即可。

因此改写一个平面移动的点云数据也会显得比较简单,只需要改写最关键的xyz点的坐标即可

# 在-2到2之间按照均匀步长生成width和height个点
y, z = np.meshgrid(np.linspace(-2, 2, self.width),np.linspace(-2, 2, self.height))    
# 按照正弦的速率来回移动
x = 0.5 * np.sin(np.ones((100, 100))-self.counter/10.0)
points = np.array([x, y, z, np.ones((100, 100))*255]).reshape(4, -1).T

效果如下:
请添加图片描述

这样,我们就可以让costmap中的体素层和障碍层订阅到障碍物信息,并让其在map上动态显示出来了。

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

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

相关文章

Python是未来的编程语言?学Python前景如何?薪资高吗?

Python是一种强大的语言,为世界各地的开发人员提供了多种用途。根据TIOBE指数,Python的排名还在继续攀升。开发人员和技术专业人员也不断发现Python的新用途,包括数据分析和机器学习等。 Python现在有着庞大的用户基础,并且它深深…

经纬度坐标点和距离之间的转换

1.纬度相同,经度不同 在纬度相同的情况下: 经度每隔0.00001度,距离相差约1米; 每隔0.0001度,距离相差约10米; 每隔0.001度,距离相差约100米; 每隔0.01度,距离相差约1000米…

Linux 远程登录

Linux 一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的 Linux 服务器。 这时我们就需要远程登录到Linux服务器来管理维护系统。 Linux 系统中是通过 ssh 服务实现的远程登录功能,默认 ssh 服务端口号为 22。 Window 系统…

SpringCloud+Dubbo3 = 王炸 !

前言 全链路异步化的大趋势来了 随着业务的发展,微服务应用的流量越来越大,使用到的资源也越来越多。 在微服务架构下,大量的应用都是 SpringCloud 分布式架构,这种架构总体上是全链路同步模式。 全链路同步模式不仅造成了资源…

第二章 runtime-core初始化核心流程和runtime-core更新核心流程

runtime-core初始化核心流程 1 创建app 2 进行初始化 2.1 基于组件生成虚拟节点 2.2 进行render 调用patch 根据不同的vnode类型进行不同类型的组件处理 组件 2.2.1 创建component instance对象 2.2.2 setup component 初始化props slots 各种 2.2.3 setupRenderEffect…

通过Docker部署rancher

先创建k8s集群 https://blog.csdn.net/weixin_44371237/article/details/123974335 环境准备 一台linux主机,4G内存 通过Docker部署rancher 启动rancher docker run --privileged -d --restartunless-stopped -p 80:80 -p 443:443 rancher/rancher查看本地镜像…

python基础:简单实现从网页中获取小说名单列表并存入文件中

python基础:简单实现从网页中获取小说名单列表并存入文件中1.技术储备 requests:requests是使用Apache2 licensed 许可证的HTTP库,可以用于网页数据请求 requests.get():发起网络请求的一种方式,类似的还有post、 put、 delete、…

[MySQL]基本数据类型及表的基本操作

哈喽,大家好!我是保护小周ღ,本期为大家带来的是 MySQL 数据库常用的数据类型,数据表的基本操作:创建、删除、修改表,针对修改表的结构进行了讲解,随后是如何向数据表中添加数据,浅浅…

Vulnhub_Venom

目录 一 测试 (一)信息收集 1 端口服务探测 2 目录扫描 3 前端源码信息收集 (二)漏洞发现 1 前端注释敏感信息泄露 2 CVE-2018-19422-Subrion CMS v 4.2.1任意文件上传 (三)提权 1 sudo…

4万字c++讲解+区分c和c++,不来可惜了(含代码+解析)

目录 1 C简介 1.1 起源 1.2 应用范围 1.3 C和C 2开发工具 3 基本语法 3.1 注释 3.2关键字 3.3标识符 4 数据类型 4.1基本数据类型 4.2 数据类型在不同系统中所占空间大小 4.3 typedef声明 4.4 枚举类型 5 变量 5.1 变量的声明和定义 5.2 变量的作用域 6 运算符…

面试之设计模式(简单工厂模式)

案例 在面试时,面试官让你通过面对对象语言,用Java实现计算器控制台程序,要求输入两个数和运算符号,得出结果。大家可能想到是如下: public static void main(String[] args) {Scanner scanner new Scanner(System.…

一文让你了解SpringCloud五大核心组件

🏆今日学习目标: 🍀SpringCloud五大核心组件 ✅创作者:林在闪闪发光 ⏰预计时间:30分钟 🎉个人主页:林在闪闪发光的个人主页 🍁林在闪闪发光的个人社区,欢迎你的加入: 林…

2021-08-29

服务器 主:172.17.0.2 master 备:172.17.0.3 slave1 lvs虚拟IP:172.17.0.100 #nginx下载地址 http://nginx.org/download/ 本地文件路径 1.dockerfile构建nginx FROM centos:7 ADD nginx-1.6.0.tar.gz /usr/local COPY nginx_install.sh /usr/local RUN sh …

毕业设计(1)-AFLGO的安装

AFLGO是一个模糊测试工具,在CSDN上的安装教程不多,自己在安装过程中也出现了很多教程之外的错误,最后反复安装了2天终于安装成功这里记录一下安装工程中的错误 使用的平台:Ubuntu18.04 配置: 内存:6G&…

StreamAPI

StreamAPI 最近开发用上了 Java8的StreamAPI,(咋现在才用?嗯哼,项目需要)自己也不怎么会,来总结一波吧! 别认为好抽象!!!干他就完事 一.StreamAPI介绍 就是用来处理集合的数据 其实到后面会发现和SQL的语句是差不多的~哈哈?你不信?往下面看 Stream:英文翻译叫做流 举个粟子…

华为OD机试 - 最多等和不相交连续子序列(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…

老学长的浙大MPA现场复试经验分享

作为一名在浙大MPA项目已经毕业的考生来说,很荣幸受到杭州达立易考周老师的邀请,给大家分享下我的复试经验,因为听周老师说是这几年浙大MPA因疫情情况,已经连续几年都是线上个人复试了,而今年疫情社会面较为平稳的情况…

【LoRa模块】关键参数记录

记录lora以及lorawa关键射频参数 这里写目录标题1. LoRa LoRaWAN LPWAN 三者区分2. LoRaWAN网路架构的特点3.关键参数4.参数定义1. LoRa LoRaWAN LPWAN 三者区分 2. LoRaWAN网路架构的特点 终端点的通讯是双向的 (bi-directional)LoRaWAN 数据速率可以从 0.3 kbps 到 50 kbps扩…

7 个 JavaScript Web API 来构建你不知道的未来网站

随着技术的日新月异,为开发人员提供了令人难以置信的新工具和API。但据了解,在100 多个 API中,只有5%被开发人员积极使用。让我们来看看一些有用的Web API,它们可以帮助您将网站推向月球!🌕🚀1.…

spring5.x-IOC模块源码学习

上文:spring5.x介绍及搭配spring源码阅读环境IOC介绍spring的IOC和DI演示案例com.hong.model.Userpackage com.hong.model;import org.springframework.stereotype.Component;import java.io.Serializable;/** * ClassName User * Description 用户 * Author csh * …