自动驾驶建图


前言

本节主要描述基于lio-sam实现自动驾驶3D建图与高精地图创建。

环境配置(Ros2)

# 依赖
sudo apt install ros-<ros2-version>-perception-pcl \
  	   ros-<ros2-version>-pcl-msgs \
  	   ros-<ros2-version>-vision-opencv \
  	   ros-<ros2-version>-xacro
# Add GTSAM-PPA, 如果apt安装的gtsam有问题,可以下载对应版本(readme中指定)的源码编译安装
sudo add-apt-repository ppa:borglab/gtsam-release-4.1
sudo apt install libgtsam-dev libgtsam-unstable-dev

# lio_sam
cd ~/ros2_ws/src
git clone https://github.com/TixiaoShan/LIO-SAM.git
cd LIO-SAM
git checkout ros2
cd ..
colcon build

数据发布

IMU

通过串口或者CAN获取imu数据,完成ros话题发布;

imu 标定内参:录制静止imu数据bag,2小时以上,通过 allan_ros2 完成内参标定;

lidar2imu 外参标定:lidar_IMU_caliblidar2imu

Point Cloud

通过雷达驱动获取点云数据,转换为 Velodyne 格式发布;

GPS

通过串口或者CAN获取差分后的 GPS 数据,每次建图时要先获取起始点的 GPS 信息,因为自动驾驶用的 ENU( 局部坐标系 ) 偏移量,后续建图时的 GPS 是基于起始点的偏移量,所以要固定起始坐标;所以每次建图时应该更新起始点的 GPS 坐标;

建图

根据自己的程序修改 config.yaml 配置文件参数,启动 run.launch.py 文件,实现建图;

若场景过于空旷,报警告 Leaf size is too small... Integer indices would overflow. 时,修改配置文件中的 lidarMaxRange: 70.0 参数,强制丢弃所有超过 70 米的点! 具体多少米根据雷达决定;

如果没有接入 GPS,报警告 Large velocity, reset IMU-preintegration! 这个一般是标定的问题,需要确定精准标定,或者接入 GPS;其实最好还是接入GPS,否则长时间建图+IMU标定不准确,会导致Z轴偏移(降低或升高);

建图后处理

清理“幽灵”与去噪

  • 用 CloudCompare 打开 PCD 文件,使用“剪刀”工具,把明显的噪点、路人、行驶的车辆手工框选并删除(比如在建图时,旁边刚好有一辆公交车开过去,或者有行人走过,它们的点云也会被记录进地图里,形成一道道长长的“残影”,称为 Ghosting)。
  • 使用 SOR(统计离群点移除)算法,把悬浮在空中的离散噪点(比如雨雪引起的噪点)过滤掉。

地面点裁剪

  • 对于 NDT 或 ICP 这类基于几何形状匹配的重定位算法来说,平坦的地面点属于“无效特征”(它无法提供横向和纵向的约束,到处都是平的)。保留过多地面点反而会导致 Z 轴(高度)漂移,且白白浪费算力。使用直通滤波器(PassThrough Filter)。以当前测量的 sensor_kit 为原点,将 Z 轴坐标低于某个阈值(例如低于路面 0.2 米)的点云全部切除,只保留树干、墙壁、路灯杆、建筑物立面等具有高度特征的点云。具体操作程序:
import open3d as o3d
import numpy as np

# 1. 加载第一步清理好的点云
print("正在加载点云...")
pcd = o3d.io.read_point_cloud("cleaned_map.pcd")

# 2. 直通滤波 (裁剪地面)
# 假设雷达高度是 0.95m,地面大概在 Z = -0.95 的位置。
# 我们将 Z 轴小于 -0.5 米的点全部切除(保留高于地面 0.45 米以上的特征)
print("正在执行 Z 轴直通滤波...")
points = np.asarray(pcd.points)
# 筛选条件:保留 Z > -0.5 的点
mask = points[:, 2] > -0.5 
filtered_pcd = pcd.select_by_index(np.where(mask)[0])

# 3. 体素降采样 (0.4米分辨率)
print("正在执行体素降采样...")
downsampled_pcd = filtered_pcd.voxel_down_sample(voxel_size=0.4)

# 4. 保存最终结果
o3d.io.write_point_cloud("ready_for_autoware_map.pcd", downsampled_pcd)
print("处理完成!")

二次降采样(Downsampling)

虽然在保存地图时可能设置了 resolution: 0.2,但对于一个覆盖几公里的园区来说,整个地图的体积依然可能高达数百兆甚至几个 G。

为了确保域控在加载地图时不会因为内存溢出(OOM)而崩溃。通常还需要继续减小文件体积。具体做法:

使用 PCL 库的体素滤波器(Voxel Grid Filter)将地图进一步降采样到 0.4m 或 0.5m 分辨率。这个密度对于 Autoware 的定位通常足够了。

地图分块

autoware 采用“动态加载(Dynamic Map Loading)”机制——车辆开到哪里,只加载车辆周围(比如半径 100 米内)的地图块。具体做法:

需要使用脚本(Autoware 官方提供了一些 PCL 工具,或者网上开源的 pointcloud_divider 脚本),将完整的大地图,切分成一个个例如 50m x 50m 尺寸的小正方形网格地图块。

绘制矢量高精地图

将清理好的 3D 点云地图导入到矢量地图编辑工具中(如 Tier IV 的 Vector Map Builder Web 端工具),在点云上“描图”。画出车道中心线、边界线、停止线,最后导出一个 .osm 格式的 Lanelet2 地图文件。Autoware 只有同时吃进 .pcd 和 .osm,才能真正跑起来。


文章作者: LSJune
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LSJune !
评论
  目录