前言
本节主要描述基于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_calib、lidar2imu
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,才能真正跑起来。