激光雷达每个点的ring值和相对时间计算

该代码段展示了如何处理激光雷达(LiDAR)数据,计算点云中每个点的对应时间。它使用了16线激光雷达的配置,计算每个点在竖直和水平方向上的角度,并根据扫描频率得出相对时间。程序会清除超出预设线范围的点,并更新点的时间戳信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前最新的激光雷达驱动已包含这两个值的计算,但有些数据集上却没有
代码来自:https://github.com/ZikangYuan/kaist2bag.git

  const int N_SCAN = 16;  //16线
  const int Horizon_SCAN = 1800; // 每线1800个点的数据
  const float ang_res_x = 0.2; // 水平上每条线间隔0.2°
  const float ang_res_y = 2.0; // 竖直方向上每条线间隔2°
  const float ang_bottom = 15.0+0.1; // 竖直方向上起始角度是负角度,与水平方向相差15.1°
  const int  SCAN_RATE = 10; //雷达的扫描频率
void VelodyneConverter::calculateTime(pcl::PointCloud<velodyne_ros::Point> &pcl_cloud, int64_t timestamp)
    {
        //设置一个长度为16的vector,用来存放(是否是每条ring的第一个点的标志位)
        std::vector<bool> is_first;
        is_first.resize(N_SCAN);
        fill(is_first.begin(), is_first.end(), true);
        //设置一个长度为16的vector,用来存放(每条ring的第一个点的偏航角)
        std::vector<double> yaw_first_point;
        yaw_first_point.resize(N_SCAN);
        fill(yaw_first_point.begin(), yaw_first_point.end(), 0.0);

        int i = 0;

        while (i < pcl_cloud.points.size())
        {
            // 计算竖直方向上的角度(雷达的第几线)
            verticalAngle = atan2(pcl_cloud.points[i].z, sqrt(pcl_cloud.points[i].x * pcl_cloud.points[i].x + pcl_cloud.points[i].y * pcl_cloud.points[i].y)) * 180 / M_PI;

            // rowIdn计算出该点激光雷达是竖直方向上第几线的
            // 从下往上计数,-15度记为初始线,第0线,一共16线(N_SCAN=16)
            rowIdn = (verticalAngle + ang_bottom) / ang_res_y;
            // std::cout << "ring : " << rowIdn << std::endl;
            // std::cout << i << " point rowIdn :  " << rowIdn << std::endl;

            if (rowIdn < 0 || rowIdn >= N_SCAN)
            {
                i=pcl_cloud.points.erase(pcl_cloud.points.begin() + i) - pcl_cloud.points.begin();
                continue;
            }

            pcl_cloud.points[i].ring = rowIdn;
            //先把除以1000,后面再除1000
            double omega = 0.361 * SCAN_RATE;
            double yaw_angle = atan2(pcl_cloud.points[i].y, pcl_cloud.points[i].x) * 57.2957;
            int layer = pcl_cloud.points[i].ring;

            if (is_first[layer])
            {
                yaw_first_point[layer] = yaw_angle;
                is_first[layer] = false;
                relative_time = 0.0;
                i++;
                continue;
            }
            // compute offset time
            if (yaw_angle <= yaw_first_point[layer])
            {
                relative_time = (yaw_first_point[layer] - yaw_angle) / omega;
            }
            else
            {
                relative_time = (yaw_first_point[layer] - yaw_angle + 360.0) / omega;
            }
            if (relative_time / double(1000) >= 0.1 && relative_time / double(1000) < 0.0)
            {
                i=pcl_cloud.points.erase(pcl_cloud.points.begin() + i) - pcl_cloud.points.begin();
                continue;
            }
            pcl_cloud.points[i].time = relative_time / float(1000);
            i++;
        }
    }
### C16 激光雷达代码实现学习教程 #### 初始化 ROS 节并配置发布器 为了使 C16 雷达正常工作,在 Python 编程环境中通常会利用 `rospy` 库完成一系列基础操作,比如启动节、建立消息发布者对象以及设定数据发布的速率。下面是一段用于初始化这些组件的基础代码片段: ```python import rospy from sensor_msgs.msg import PointCloud2, PointField import numpy as np def c16_driver(): # 初始化ROS节名为"c16_lidar_node" rospy.init_node('c16_lidar_node', anonymous=True) # 创建PointCloud2类型的消息发布者,话题名称为"/velodyne_points" pub = rospy.Publisher('/velodyne_points', PointCloud2, queue_size=10) rate = rospy.Rate(10) # 设置循环频率为每秒10次 while not rospy.is_shutdown(): # 此处应加入读取真实C16雷达数据的逻辑 point_cloud_msg = create_pointcloud_message() pub.publish(point_cloud_msg) rate.sleep() if __name__ == '__main__': try: c16_driver() except rospy.ROSInterruptException: pass ``` 这段程序展示了如何通过调用 `rospy.init_node()` 来注册一个新的 ROS 节,并定义了一个 Publisher 对象用来向指定的话题发送云信息[^1]。 #### 构建云消息结构体 当处理来自 C16 的原始扫描数据时,需要构建合适的云消息格式以便于后续算法处理。这里提供了一种方法来创建自定义的 `sensor_msgs/PointCloud2` 类型的数据包: ```python def create_pointcloud_message(points=np.array([])): header = std_msgs.msg.Header() header.stamp = rospy.Time.now() header.frame_id = 'lidar_link' fields = [ PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1), PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1), PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1), PointField(name='intensity', offset=12, datatype=PointField.FLOAT32, count=1), PointField(name='ring', offset=16, datatype=PointField.UINT16, count=1), # 添加环形通道支持 ] pc2 = PointCloud2( header=header, height=1, width=len(points), is_dense=False, is_bigendian=False, fields=fields, point_step=(np.dtype(np.float32).itemsize * 5), # x,y,z,intensity, ring row_step=(np.dtype(np.float32).itemsize * 5 * points.shape[0]), data=np.asarray(points, dtype=np.float32).tostring(), ) return pc2 ``` 此函数负责组装包含三维坐标 (x, y, z),强度 (`intensity`) 环索引 (`ring`) 的云消息实例。特别注意的是增加了对 "ring" 字段的支持,这对于某些特定应用非常重要,例如基于 LOAM 或 Lego-LOAM 算法的地图构建定位任务[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值