ROS的二维LaserScan转为三维pcl::PointXYZ

ROS的二维LaserScan转为三维pcl::PointXYZ

做实验用的单线rplidar a1输出的是LaserScan,想转换成三维的PoinCloud2格式的,然后通过订阅串口发来的数据来确定Z轴的值 ,本来想在直接在驱动节点里转为PointCloud2的,但PCL库也太大了,买的弱鸡arm的开发板放不下,编译也太慢了,说到底还是我自己憨憨,应该有更好的办法哈哈。总之 ,就在上位机搞个单独的节点来转换。首先了解下数据格式

LaserScan
好像大概是这样

然后就
大概这样 再参考下各位大佬的程序
主要是这个部分

 cloud_msg.header.frame_id = "laser";

    cloud_msg.height = 16;

    int count = scan_msg.scan_time / scan_msg.time_increment;
    cloud_msg.width  = count;
    cloud_msg.points.resize(cloud_msg.width * cloud_msg.height);
    for(int i = count; i < count+count; i++) {
        float degree = RAD2DEG(scan_msg.angle_min + scan_msg.angle_increment * (i-count));
        if(scan_msg.ranges[(i-count)])
        {
            cloud_msg.points[i].x = scan_msg.ranges[(i-count)]*cos(DEG2RAD(degree));
            cloud_msg.points[i].y = scan_msg.ranges[(i-count)]*sin(DEG2RAD(degree));
            cloud_msg.points[i].z = k.data;
        }
        }





整个程序是这样的


```cpp

#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"

#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <boost/foreach.hpp>
#include "std_msgs/Float64.h"
ros::Publisher cloud;
std_msgs::Float64 height;
typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
pcl::PointCloud<pcl::PointXYZ> cloud_msg;
sensor_msgs::LaserScan scan;
void scan_pcl(sensor_msgs::LaserScan scan_msg, std_msgs::Float64 k){

    cloud_msg.header.frame_id = "laser";

    cloud_msg.height = 16;

    int count = scan_msg.scan_time / scan_msg.time_increment;
    cloud_msg.width  = count;
    cloud_msg.points.resize(cloud_msg.width * cloud_msg.height);
    for(int i = count; i < count+count; i++) {
        float degree = RAD2DEG(scan_msg.angle_min + scan_msg.angle_increment * (i-count));
        if(scan_msg.ranges[(i-count)])
        {
            cloud_msg.points[i].x = scan_msg.ranges[(i-count)]*cos(DEG2RAD(degree));
            cloud_msg.points[i].y = scan_msg.ranges[(i-count)]*sin(DEG2RAD(degree));
            cloud_msg.points[i].z = k.data;
        }
        else
        {
            cloud_msg.points[i].x = 6*cos(DEG2RAD(degree));
            cloud_msg.points[i].y = 6*sin(DEG2RAD(degree));
            cloud_msg.points[i].z = k.data;
        }
        ROS_INFO(": [%f, %f]", degree, scan_msg.ranges[(i-count)]);
    }
    cloud.publish(cloud_msg);

}
void myCallback(const std_msgs::Float64&msg){


   height=msg;
}
void callback(const sensor_msgs::LaserScan &msg){


    scan=msg;
    scan_pcl(scan,height);

}
int main(int argc,char * argv[])
{

    ros::init(argc, argv, "scan_pcl");
    ros::NodeHandle nh;
    ros::Rate r(5); //执行频率5Hz
    ros::Subscriber height_sub = nh.subscribe("/chatter", 1000, myCallback);
    ros::Subscriber scan_sub=nh.subscribe("/scan",1000,callback);
    cloud=nh.advertise<PointCloud>("/point_cloud",1000);
    while (ros::ok()) {

    std_msgs::Float64 height;
    height.data=10;
    //scan_pcl(scan,height);
    ros::spinOnce();
 r.sleep();
}
    return 0;

}

可以可以 再配置下CMakelists 和package
在rviz里订阅下PointCloud
串口收到了10
在这里插入图片描述那堆彩色的点浮在上面啦 可以可以

ROS 2 (Robot Operating System) 中,`sensor_msgs::msg::LaserScan` 类型的数据表示的是激光雷达扫描信息,包含了一系列的测量数据,如角度、强度等。而 `pcl::PointCloud<pcl::PointXYZ>` 是 Point Cloud Library (PCL) 提供的一个结构体,用于存储三维空间中的点云数据,每个点由 x、y 和 z 坐标组成。 要从 `LaserScan` 换为 `pcl::PointCloud<pcl::PointXYZ>`,你需要对激光雷达的数据进行解析,并将其映射到三维坐标上。以下是一个简化版的步骤: 1. 首先,确保已经包含了所需的库头文件,例如: ```cpp #include <ros/ros.h> #include <sensor_msgs/LaserScan.h> #include <pcl_conversions/pcl_conversions.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> ``` 2. 创建一个函数,接收 `sensor_msgs::msg::LaserScan` 数据: ```cpp void laserScanToPointCloud(const sensor_msgs::msg::LaserScan& scan, pcl::PointCloud<pcl::PointXYZ>& lidar_cloud) { // 获取激光扫描范围内的点数 int num_points = scan.ranges.size(); // 初始化点云 lidar_cloud.resize(num_points); for (size_t i = 0; i < num_points; ++i) { double angle = scan.angle_min + i * (scan.angle_increment); double distance = scan.ranges[i]; // 将角度换为x,y坐标(假设激光雷达垂直于地面) float x = distance * cos(angle); float y = distance * sin(angle); // 添加z坐标通常为0,因为激光雷达水平扫描 float z = 0; // 将点添加到点云中 lidar_cloud.points[i].x = x; lidar_cloud.points[i].y = y; lidar_cloud.points[i].z = z; } } ``` 这个函数简单地将激光雷达的线性距离和角度换为笛卡尔坐标,并放入 `lidar_cloud` 中。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值