尝试在一个嵌入式环境上开发基于视觉的定位算法,也就是视觉里程计。嵌入式的软硬件环境计算能力有限,架构不同,所以部署很多主流算法有点困难,如ORB-SLAM系列,DSO系列,VINS-Fusion系列。
板子是旭日x3,大概500块钱,操作系统Ubuntu20。接入摄像头跑了一下官方目标检测sample,实时性勉强,算是个入门级的板子。
我首先尝试的是VINS和DSO两个框架,发现编译VINS的时候直接CPU占满卡死,无论cmake指令加-j并行编译还是创建交换内存,仍然卡死,于是尝试部署DSO,DSO通过交换内存艰难地编译成功了,但是运行官方数据集时处理速度极慢,大约2-3秒一帧,CPU还是满载,感觉优化空间太大,遂放弃。
本来想要么自己拼装一个轻量的框架,但是时间紧迫不想造轮子了,就继续调研更轻量的框架,然后发现了LVT。
论文:Lightweight Visual Odometry for Autonomous Mobile Robots
github:https://github.com/SAR-Research-Lab/lvt
项目相对冷门,但也有少量的引用和改进。支持双目和RGBD相机输入。
最主要的是该工作能在树莓派3上运行,单帧处理时间不到200ms,体量和内存都极小,而且精度尚可,官方数据集验证超过了LIBVISO2,接近主流VSLAM系统。项目在Ubuntu和Windows上成功构建,我觉得这可能是非常适合我的需求的框架,下面打算在它的基础上开发。
我想在自己的win11上做开发,借助vcpkg可以极大简化依赖的安装,值得努力一下。
使用vcpkg安装依赖
我想用最新的opencv4和CUDA,所以我先对照自己显卡,安装了CUDA11。此处不赘述。
然后下载vcpkg,稍微学习一下使用,参考:https://blog.csdn.net/cjmqas/article/details/79282847
为了防止vcpkg下载依赖时网络引起的乱七八糟问题,把梯子挂上。
然后通过vcpkg一键安装opencv4(contrib,带CUDA),g2o和pangolin。安装g2o时会自动安装eigen3。vcpkg会自动下载这些依赖,编译,完成安装。速度比较慢,要耐心等待。
完成后使用.\vcpkg.exe integrate install
集成到全局,让任何VS工程里能找到这些依赖。
最后,把vcpkg安装的位置全部加到环境变量里去,让cmake能够从这里找包,省得配置来配置去。
用.\vcpkg.exe list
查看已安装的依赖,发现我的环境具体是:
- opencv v4.7
- eigen3
- g2o (2020)
- pangolin v0.8
cmake生成解决方案+VS2019生成
clone下来lvt的代码,建一个build文件夹,进去后cmake..
生成VS的解决方案。
可以看到需要的依赖都找到了,不过我使用的opencv和g2o都是新版本的,所以还要修改一下源码。
打开build里生成的lvt.sln。直接生成的话,肯定会有opencv相关的报错,因为我用的是opencv4,所以要去源码里把找不到定义的变量名修改一下,不多。
另外还有g2o新版本里的求解器的用法变了,要使用unique_ptr。参考该同学的博客:https://blog.csdn.net/robinhjwy/article/details/78084210 对照着修改了一下。
右击ALL_BUILD -> 生成,把可执行项目全部生成。
如果要可视化展示,确保CMakeLists.txt里把pangolin编译的选项置为“ON”,然后生成。我尝试了开启,但是Pangolin报了一堆gl.h未声明符号的错,我查了半天不明白原因,有的说没有引入opengl32.lib,有的直接用旧版本v0.5,我这里就先关闭pangolin的编译。
生成成功。
目标视图如下。lvt生成库,三个example生成对应数据集的测试程序。经VS生成后,会发现在三个example目录下/debug中生成了可执行程序。
KITTI数据集测试
下载KITTI odometry数据集,使用sequences/00测试。
报错1:
缺少opencv xfeatures2d4d.dll终止运行。
- 解决:打开可执行程序所在的文件夹发现确实没有该动态库,原因不明。我在VS里由debug模式改成release模式重新生成,发现xfeatures2d4d.dll等加载到可执行程序所在目录了,该报错解决。
报错2:
Can't open file: 'calib/00.yml' in read mode
- 解决:观察一下就会发现,因为我在VS里生成项目,可执行程序会被输出到/debug或/release文件夹里,而kitti_example.cpp的main函数是从当前路径下读取标定文件,所以把读取路径的代码修改一下就好。
将kitti example设为启动项目,根据main函数里的定义,在项目属性页填写参数。我写的是绝对路径,同时注意其它文件的读取路径是否正确,可能需要修改一下。
开始运行。因为没有开启可视化,所以终端只打印了处理的帧数。lvt内有获取当前位置的接口,我调用了一下在终端里打印出当前位置。
执行结果:
在我的PC上,平均一帧处理时间0.015s,也就是约66FPS,速度还是非常快的。
用evo绘制轨迹,只展示俯视角
evo_traj kitti 00.txt -p --plot_mode=xz
结果:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。