第四章:激光雷达驱动与配置
好,咱们进入正题。光流搞定了,接下来就是激光雷达。说实话,这部分我踩过的坑比光流还多。尤其是串口配置那一步,稍不留神就收不到数据。
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_ROT和SENS_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会更「宽容」,不会因为一个异常值就震荡。
- 确认雷达数据能正常发布(用
listener distance_sensor查看) - 确认
SENS_LIDAR_ROT和实际安装方向一致 - 确认
EKF2_HGT_MODE设成了激光雷达模式 - 试飞时先悬停,看高度数据是否稳定
好了,激光雷达这块的核心配置就这些。说白了就是三步:连好串口、设对参数、让EKF用起来。但每一步都有坑,尤其是参数匹配那一步。我建议你配完后,用listener distance_sensor先看看数据对不对,再起飞。
用手在雷达前面晃一晃,看
listener distance_sensor输出的距离值是否跟着变。如果不动,八成是串口配置错了。
这张图把整个流程串起来了。从硬件连接开始,到串口配置、参数设置、数据解析、uORB发布、EKF融合,最后验证和试飞。每一步都环环相扣,缺一不可。
我个人觉得,最容易出问题的是第3步和第6步的参数匹配。你设了SENS_LIDAR_ROT=90,但EKF那边没改EKF2_RNG_AID,那雷达数据就白发了。嗯,这种低级错误我犯过不止一次。