目录
1、问题描述
开发环境
我的程序配置
2、问题造成的后果
3、解决方案
说明:
4、实例,针对ORB_SLAM3问题
5、其他参考解决方案
6、另一个例程
7、其他:修改系统默认链接的cv_bridge版本号,以及查看当前系统链接的cv_bridge版本号与位置
与本篇问题相关的一个问题,可参考我之前的一篇博客:
cv_bridge与python版本问题导致编译错误error: return-statement with no value, in function returning ‘void*’
以下为我个人的开发环境用到这个问题,当然,换做其他开发环境遇到的问题也是类似的,解决方案也是类似的,因此本文问题及解决方案是通用的。
嵌入式主控:nvidia xavier
os:ubuntu 18.04, ROS melodic
--------------------------------------------
所以,我的xavier上总共有3个版本的opencv:3.2, 4.1.1, 3.4.9
教训:以后不要在同一个主控上安装多个版本opencv,那是自找麻烦,涉及到各种配置,配置不对就导致程序无法运行,调试配置花费大量精力!
在我的ROS节点程序对应的cmakelists.txt中find_package(),我用的是find_package(OpenCV 4 REQUIRED),如果用3就导致程序根本编译不通过,
因此只能选择调用opencv4库,这就是导致用户程序调用的opencv库版本4.1.1与ROS默认安装的cv_bridge调用的opencv库版本3.2不一致问题!
一句话总结:ROS melodic默认安装cv_bridge版本为1.13.0以及opencv版本为3.2,而我的程序中用到了cv_bridge且设置调用的opencv版本为4.1.1
cv_bridge与opencv版本问题会导致用户代码编译成功,但运行报错的问题,是很棘手的一个问题。
例如:
等等
——以下展示了ORB_SLAM3编译其ROS例程结果,只有几个节点编译成功,其他节点报出由于opencv版本冲突问题导致编译失败错误。
由于我的程序或ORB_SLAM2/3都只能使用opencv4才能编译通过,因此解决方案只能是安装使用了opencv4的cv_bridge。
ROS noetic默认安装的cv_bridge1.15.0以及opencv4.2,因此,就要下载1.15.0版本的cv_bridge源码,将其放到用户自建的ROS工作空间中用
catkin_make编译,之后将用户ROS节点程序设置为优先链接用户安装的这个版本cv_bridge(而不是ROS默认安装的那个),在~/.bashrc文件中
将用户ROS工作空间包的setup.bash文件在最后source就能够覆盖ROS系统默认的cv_bridge了,并在ROS包对应的camkelists.txt中更新为find_package(OpenCV 4 REQUIRED)
总结一下,解决步骤:
- 下载1.15.0版本的cv_bridge源码,catkin_make编译
- ~/.bashrc中source上步安装的cv_bridge包路径
- camkelists.txt中更新find_package(OpenCV 4 REQUIRED)
(1)cv_bridge包包含在vision_opencv包中,因此,建议将vision_opencv包一起下载下来整体编译安装
注意,下载源码时选择noetic对应的1.15.0版本的!
http://wiki.ros.org/vision_opencv
(2)在cv_bridge源码目录下CHANGELOG.rst文件中有其版本更新信息,如下图所示:
按照以下修改进行操作,即可保证正常运行
(1)修改~/.bashrc文件
按照官网(https://github.com/UZ-SLAMLab/ORB_SLAM3)将ROS包路径添加到此文件中,添加完成如下:
终端重新source ~/.bashrc
说明:
——由于我自己安装的1.15.0版本的cv_bridge安装在~/bluerov2/src下,而我没有把此包路径在bashrc进行source,因而默认调用cv_bridge版本依然是
ROS默认安装的1.13.0版本,如此这样,也未导致ORB_SLAM3的ROS包编译出错,并且ORB_SLAM3的ROS节点可以正常运行(好神奇,此问题需要
抽时间再好好研究一下,此处既然不需要一定调用1.15.0版本的cv_bridge,那么我们就可以不在bashrc中source其包路径了)。
——但是,如果编译时报错,还是建议在bashrc中将用户自己安装的cv_bridge1.15.0路径进行source一下,从而保证默认调用的是用户自己安装的cv_bridge1.15.0
——用指令pkg-config --modversion cv_bridge查看目前系统中默认的cv_bridge版本号,pkg-config --cflags cv_bridge查看系统默认搜索cv_bridge的路径
——下面分别展示了设置系统没有调用用户自己安装的cv_bridge1.15.0(本例使用),以及默认调用了用户自己安装的cv_bridge1.15.0的截图
(2)修改find_package()默认链接opencv4
将源码顶层cmakelists.txt中的find_package(OpenCV 3)修改为find_package(OpenCV 4),下面左图
将例程ROS包中的cmakelists.txt中的find_package(OpenCV 3)修改为find_package(OpenCV 4),下面右图
(3)将源码中opencv3库API替换成opencv4库API
在ORB_SLAM3整个工程中查找关键字CV_LOAD_IMAGE_UNCHANGED,并替换为cv::IMREAD_UNCHANGED
说明:如果不做此步修改而直接编译的话,会报错未定义的CV_LOAD_IMAGE_UNCHANGED。这是由于CV_LOAD_IMAGE_UNCHANGED是opencv3库中的,
而cv::IMREAD_UNCHANGED是opencv4库中的。
——CV_LOAD_IMAGE_UNCHANGED未定义错误
——IMREAD_UNCHANGED必须加上cv::域名(不要参考博客Ubuntu安装ORB-SLAM常见问题中说的加一个cv声明,在哪些文件加,这是个问题)
(4)重新编译
执行./build.sh和./build_ros.sh分别来编译ORB_SLAM3源码及ROS例程包源码。
以下展示了编译结果OK,虽然有opencv版本冲突问题,但不影响程序正常运行!
(5)运行ORB_SLAM3的ROS包例程
这里以运行Mono节点为例(使用ZED相机及对应的内参),效果如下:
——
将rosrun写成shell脚本,省去每次重新敲代码:我增加了以下文件:(1)单目节点启动shell脚本,rosrun_mono.sh(2)zed相机单目配置文件,zed_mono.yaml
运行其他相机模式的方式类似,不再赘述。
——
由于ORB_SLAM3没有将相机最终位姿以ROS话题形式发布出来,这里我自己实现了将相机位姿以变换矩阵形式发布出来了(稍后会更新成nav_msgs::Odomtry格式发布)。
单目初始化未成功阶段:无有效的相机位姿
——
定位追踪过程:相机位姿以变换矩阵形式被实时发布出来了,便于其他ROS节点订阅以实现ORB_SLAM与其他功能模块的集成
以下为我参考的一些解决方案,都不完整,或不是很好的解决方案,本文结合自己的应用程序汇总整理出一套完整可用的解决方案
Ubuntu安装ORB-SLAM常见问题
(十一)ORBSLAM2在ROS下运行
Opencv 图像读取与保存问题
另外一个遇到本文同样问题的例程是我自己写的基于opencv和点云库多模态模板检测与跟踪程序,
解决方案同上,具体不再赘述,给出更新可用的一些配置截图。以下find_package(OpenCV REQUIRED)链接的是opencv4
(1)如何查看?
——用指令pkg-config --modversion cv_bridge查看目前系统中默认的cv_bridge版本号,pkg-config --cflags cv_bridge查看系统默认搜索cv_bridge的路径
——下面分别展示了设置系统没有调用用户自己安装的cv_bridge1.15.0(本例使用),以及默认调用了用户自己安装的cv_bridge1.15.0的截图
(2)如何修改?
在bashrc中修改:如果不source用户自己安装的cv_bridge包路径(下图中倒数第2行),那么系统默认调用cv_bridge1.13.0;
如果source用户自己安装的cv_bridge包路径(下图中倒数第2行),那么系统默认调用cv_bridge1.15.0