目的导向
我们的目的是让哨兵知道自己处于赛场的哪个位置,为此,我们使用SLAM,SLAM的全称是同时定位与建图构建,这意味着随着传感器持续地扫描,SLAM项目可以算出机器人相对于程序开始那一刻机器人所处的平移量和旋转量,同时还可以获得周遭的二维或者三维地图。
这里便引出一个问题,SLAM程序求出的是相对于起始点的位姿,那么我们怎么获得机器人在比赛场地的绝对位姿呢,答案有两个:
一个是在比赛开始时将哨兵准确无误地放置在一个固定位置,这样我们便可以用这个固定位姿换算出绝对位姿;
另一个是提前把比赛场地的地图建好(比赛前会单独提供一个时间段给哨兵建图),然后手动指定地图的原点,哨兵比赛时只需要讲它扫描到的信息和地图做对比(严格学名叫做点云配准),就能得到一个相对于地图的绝对位姿。
运行方案
大范围的点云配准是极其耗性能的,我们不可能以一个能够满足控制观测的帧率去运行重定位,于是一个常用的方案是,在比赛开始前进行一次重定位,随后进行SLAM进行里程积累,在误差过大导致丢失位姿时进行SLAM的重启,再次进行重定位,这便是哨兵定位的大致方案了。
抛却重定位,只运行SLAM,当然也可以,只是定位的稳定性无法保证,加上每次比赛前摆放哨兵都需要小心翼翼的。
我们所采用的是激光雷达SLAM,而非视觉SLAM,或者视觉激光雷达融合SLAM,这是需要注意的(这篇指南便是基于激光雷达SLAM的),激光雷达会返回它扫描到的每一个点的三维坐标,直接获得点云,融合陀螺仪来做SLAM,而视觉则是利用双目视差或者单目前后帧对比计算出三维点云,更多的信息就自己google一下吧,这里不过多赘述。
开源节流
那么,我们需要使用到的SLAM算法是一个怎样的形态呢?
绝大部分SLAM算法都是使用Cpp写的,使用cmake管理项目,其中,这些项目又大部分依赖ROS或者ROS2(ROS更多),我在这里列举一些比较知名的项目:
fast-lio,使用广泛的SLAM算法,消耗小,但是代码极其不规范,也不知道怎么跑起来的,想做一点修改困难重重,不过不用担心,我已经改好了一份ROS2的版本在我们仓库里,顺便规范了一下代码,后来受不了其糟糕的代码,新建了一个仓库稍微重构了这个项目:rmcs-slam
lio-livox,大疆开发的SLAM项目,最新的提交是2023年5月,代码还算规范,只提供了ROS1的版本,我也改好了一份ROS2的版本放在了我们算法组的团队仓库里,感觉不太好使,有兴趣可以测测:livox-lio
point-lio,fast-lio的升级版,但是在高速旋转的情况下容易寄,消耗也大,不是很好使,我又双叒叕改了一份ROS2的版本在我们仓库里,有兴趣clone下载试试:point-lio
fast-gicp,不是SLAM,是一个支持多线程加速的点云配准库,可以用来重定位,代码很规范,提供了python的绑定,也有none-ros的使用途径
kiss-icp,挺规范的激光雷达里程计,有ROS1和ROS2的适配,最近还在维护,有python绑定,可以使用pip下载,适配了livox的雷达
fast-lio-localization,基于fast-lio的持续重定位SLAM项目,ROS1,其实就是fast-lio粘了点python,使用体验并不好,坐标会小范围突变,消耗还大了,也可能是我打开方式不对,感兴趣的自己试试
cartographer,谷歌开源,必属精品,企业级别的工程规范,无与伦比的拓展性与兼容性,极少的依赖,它不需要ros,依赖库很少,同时支持2D和3D激光雷达,跨平台,适配多传感器配置融合,适用范围极其广泛,社区也提供了ROS的版本,怎么使用,都顺手!(虽然我就没使用过这个)
还有诸如 gmapping等优秀的开源SLAM项目,其中的每一个项目都可以满足哨兵的定位需求,任君挑选
不过先别急着去部署,在使用这些算法之前,我们还需要一些前置知识和环境配置。