第四章:激光雷达驱动与配置

好,咱们进入正题。光流搞定了,接下来就是激光雷达。说实话,这部分我踩过的坑比光流还多。尤其是串口配置那一步,稍不留神就收不到数据。

4.1 串口(UART)配置

激光雷达和飞控通信,最常用的就是UART。我个人习惯用TELEM2或者GPS2端口,因为这两个口默认没被占用,而且支持DMA。

先看硬件连接:

  • 激光雷达的TX → 飞控的RX
  • 激光雷达的RX → 飞控的TX
  • GND → GND
  • VCC → 5V(注意:有些雷达是3.3V,别烧了)

然后在default.cmake里使能串口驱动:

# 在 boards/px4/fmu-v5/default.cmake 中添加
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_LASER_UART=y
CONFIG_DRIVERS_DISTANCE_SENSOR_TFMINI_UART=y

嗯,这里要注意。不同雷达的驱动名不一样。比如TFmini用tfmini,TeraRanger用teraranger。我建议你直接看src/drivers/distance_sensor/目录下的文件夹名。

⚠️ 串口波特率陷阱
大部分激光雷达默认是115200,但有些奇葩厂家用57600甚至9600。我曾经被一个国产雷达坑过,手册写115200,实际是115200但校验位是奇校验。折腾了两天才发现。

配置串口参数,在startup.sh里写:

# 启动激光雷达驱动
tfmini start -d /dev/ttyS2 -b 115200

-d指定设备,-b指定波特率。如果你用别的雷达,比如Lightware,命令是:

lightware_laser_uart start -d /dev/ttyS2 -b 115200

4.2 激光雷达参数配置

参数这块,有两个最关键:SENS_LIDAR_ROTSENS_LIDAR_MAXHGT

SENS_LIDAR_ROT:安装角度

这个参数告诉飞控:激光雷达朝哪个方向装。默认是0度(朝前)。但实际中,很多人把雷达装在机头下方,或者侧面。

举个例子:

  • 朝前安装:SENS_LIDAR_ROT = 0
  • 朝下安装:SENS_LIDAR_ROT = 90(或者-90,看坐标系定义)
  • 朝后安装:SENS_LIDAR_ROT = 180

怎么设?用QGroundControl的参数列表,搜索SENS_LIDAR_ROT,直接改。或者用命令行:

param set SENS_LIDAR_ROT 90
param save
💡 我的经验
如果你把雷达朝下装,记得把旋转值设为90。我曾经设成-90,结果EKF把地面数据当成前方障碍物,无人机直接往地上撞。嗯,那次炸机让我记住了这个教训。

SENS_LIDAR_MAXHGT:最大测量高度

这个参数限制了雷达的有效测量范围。比如你的雷达标称能测12米,但实际超过8米数据就不稳定。那就设成8米。

为什么要设这个?因为EKF融合时,如果雷达报一个20米的异常值,飞控会以为前方突然空了,然后加速往前冲。你想想看,这多危险。

设置方法:

param set SENS_LIDAR_MAXHGT 8.0
param save
参数名 默认值 推荐值 说明
SENS_LIDAR_ROT 0 0/90/180 雷达安装角度(度)
SENS_LIDAR_MAXHGT 100.0 8.0~12.0 最大有效测量距离(米)

4.3 数据解析与发布

雷达数据怎么到飞控里?说白了就是驱动把串口收到的二进制数据,解析成distance_sensor_s结构体,然后发布到uORB总线上。

以TFmini为例,它的数据帧格式是:

0x59 0x59 [距离低字节] [距离高字节] [强度低字节] [强度高字节] [校验和]

驱动里解析的代码大概长这样:

// 伪代码,实际在 src/drivers/distance_sensor/tfmini/tfmini.cpp 中
if (buf[0] == 0x59 && buf[1] == 0x59) {
    uint16_t dist = buf[2] | (buf[3] << 8);
    uint16_t strength = buf[4] | (buf[5] << 8);
    // 校验和检查
    if (checksum_ok) {
        // 发布到uORB
        distance_sensor_s report = {};
        report.current_distance = dist / 100.0f; // 单位:米
        report.max_distance = SENS_LIDAR_MAXHGT;
        report.orientation = SENS_LIDAR_ROT;
        _distance_sensor_pub.publish(report);
    }
}

发布之后,EKF模块就能通过uORB订阅到这些数据。说白了,驱动就是个翻译官,把雷达的「方言」翻译成飞控能懂的「普通话」。

🔑 关键点
数据发布时,orientation字段必须和SENS_LIDAR_ROT一致。否则EKF会以为数据来自另一个方向,融合结果全乱套。

4.4 EKF融合配置

最后一步,让EKF用上激光雷达数据。默认情况下,EKF只融合气压计和GPS的高度。要加入激光雷达,得改几个参数。

核心参数是EKF2_HGT_MODE

  • 0:气压计高度(默认)
  • 1:GPS高度
  • 2:激光雷达高度(推荐)
  • 3:视觉高度

我建议设成2,让EKF用激光雷达作为主要高度源。但要注意,激光雷达在强光下或者低反射率地面(比如黑色沥青)会失效。所以最好同时保留气压计作为备份。

怎么配?

param set EKF2_HGT_MODE 2
param set EKF2_RNG_AID 1   # 启用激光雷达辅助
param set EKF2_RNG_USE_HGT 1  # 用激光雷达做高度
param save

还有一个容易被忽略的参数:EKF2_RNG_GATE。它控制EKF对雷达数据的信任程度。默认是3.0,意思是如果雷达测量值和预测值偏差超过3个标准差,就丢弃这个数据。

我个人习惯设成5.0,因为室内环境反射多,偶尔会有跳变。设大一点,EKF会更「宽容」,不会因为一个异常值就震荡。

⚠️ 融合前的检查清单
  1. 确认雷达数据能正常发布(用listener distance_sensor查看)
  2. 确认SENS_LIDAR_ROT和实际安装方向一致
  3. 确认EKF2_HGT_MODE设成了激光雷达模式
  4. 试飞时先悬停,看高度数据是否稳定

好了,激光雷达这块的核心配置就这些。说白了就是三步:连好串口、设对参数、让EKF用起来。但每一步都有坑,尤其是参数匹配那一步。我建议你配完后,用listener distance_sensor先看看数据对不对,再起飞。

📌 快速验证方法
用手在雷达前面晃一晃,看listener distance_sensor输出的距离值是否跟着变。如果不动,八成是串口配置错了。
激光雷达驱动与配置流程 1. 硬件连接 TX/RX/GND/VCC 2. 串口配置 波特率/设备名 3. 参数设置 ROT / MAXHGT 4. 数据解析 校验/单位转换 5. uORB发布 distance_sensor 6. EKF融合 HGT_MODE配置 7. 验证 listener检查 8. 试飞验证 悬停/高度稳定

这张图把整个流程串起来了。从硬件连接开始,到串口配置、参数设置、数据解析、uORB发布、EKF融合,最后验证和试飞。每一步都环环相扣,缺一不可。

我个人觉得,最容易出问题的是第3步和第6步的参数匹配。你设了SENS_LIDAR_ROT=90,但EKF那边没改EKF2_RNG_AID,那雷达数据就白发了。嗯,这种低级错误我犯过不止一次。

专注资料整理