ros kinetic 自帶opencv3 與 opencv 2 的兼容問題

問題分析

自己寫的系統必須基於opencv 2.x,而ros kinetic自帶了opencv3的版本。於是在編譯時報錯:

/usr/bin/ld: CMakeFiles/xxxx.cpp.o: undefined reference to symbol '_ZN2cv6String10deallocateEv'
/opt/ros/kinetic/lib/x86_64-linux-gnu/libopencv_core3.so.3.3.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
CMakeFiles/xxxx/build.make:192: recipe for target '../xxxx' failed

而自己的系統裏 Pangolin 等一堆庫都基於2.x版本opencv了,不好再做調整,於是只好強行調整ros的opencv依賴來使其適應我的系統了。

ros中用到opencv的地方是從話題中讀取圖像,如 /camera/image_raw話題中抓取 rgb或depth圖像保存爲cv::Mat,所需用到的ros包是cv_bridge。

因此核心問題是: ros的包cv_bridge使用默認opencv3編譯,而自身系統使用opencv 2.x編譯,opencv的混合編譯帶來了錯誤。

 

問題解決方法

方法一共有兩種:

1) 淺依賴可以直接調整cv_bridge的cmake文件,詳細可參考:https://www.mobibrw.com/2017/8718

這個方法可以幫助我通過編譯,然而實際運行時會報內存錯誤。因此放棄選擇第二個方式,各位如果想省時間也可以試試這個方式,只需要改文件的幾行路徑。

注意: 改完cv_bridge的cmake文件後,一定要 rm -rf build 文件然後重新 cmake .. & make 纔會生效。

 

2)重度依賴,一勞永逸

直接將cv_bridge卸載掉,然後從源代碼重新編譯,詳細參考:https://blog.csdn.net/xiat5/article/details/79354573

下面是我的執行過程。
 

步驟

使用opencv 2.x版本重新編譯  cv_bridge。

1、 卸載 cv_bridge

使用指令卸載cv_bridge,

$ sudo apt-get remove --purge ros-kinetic-cv-bridge

這裏會出現提示說下列包會被一併卸載,不用慌,直接y卸載,實測不影響ros 通信等基本功能的使用 [ 這裏有一點提一下,可見文章最後 ]:

ros-kinetic-camera-calibration ros-kinetic-compressed-depth-image-transport
  ros-kinetic-compressed-image-transport ros-kinetic-cv-bridge ros-kinetic-depth-image-proc ros-kinetic-desktop
  ros-kinetic-desktop-full ros-kinetic-gazebo-plugins ros-kinetic-gazebo-ros-pkgs ros-kinetic-image-pipeline
  ros-kinetic-image-proc ros-kinetic-image-publisher ros-kinetic-image-rotate ros-kinetic-image-transport-plugins
  ros-kinetic-image-view ros-kinetic-perception ros-kinetic-rgbd-launch ros-kinetic-rqt-common-plugins
  ros-kinetic-rqt-image-view ros-kinetic-simulators ros-kinetic-stereo-image-proc
  ros-kinetic-theora-image-transport ros-kinetic-vision-opencv ros-kinetic-viz

 

2、 到github上clone 下來cv_bridge

gihub地址爲:  https://github.com/ros-perception/vision_opencv

切換kinetic版本: 

$ git checkout kinetic

 

3、 修改CMakeLists.txt文件指定爲你自己的opencv版本.

拿我的爲例子,我的opencv 2.4.11的build路徑爲:  ~/opencv_2.4.11/build

於是我在 find_package(OpenCV)前加入一行::

set( OpenCV_DIR "~/opencv_2.4.11/build" )

建議可以使用message輸出一下opencv version或 opencv_include 目錄來確保cmake加載的自己版本的opencv.

 

3、最後

$ cmake ..  && make

$ sudo make install

出現下列情況表示安裝成功

...

-- Set runtime path of "/usr/local/lib/libcv_bridge.so" to ""
-- Installing: /usr/local/lib/python2.7/dist-packages/cv_bridge/boost/cv_bridge_boost.so
-- Set runtime path of "/usr/local/lib/python2.7/dist-packages/cv_bridge/boost/cv_bridge_boost.so" to ""

 

4、回到自己最初需要用ros的代碼裏,對CMakeLists.txt中做一些調整:

set(cv_bridge_DIR /usr/local/share/cv_bridge/cmake)

find_package(cv_bridge)

include_directories(${cv_bridge_DIR})

target_link_libraries中將cv_bridge的庫文件鏈接上

   ${cv_bridge_LIBRARIES}

然後按順序編譯,大功告成!!!!

 

其他

1、so文件來源

一開始我檢查自己的CMakeLists.txt中,所有 target_link_libraries 的地方都沒找到opencv 3.x的引用,後來梳理了ros的性質,

rosbuild_add_executable() 指令會從 manifest.xml 中讀取包,而我的manifest.xml中包含了 cv_bridge

而cv_bridge自帶的 cmake文件中加載了 3.x的so文件.

2、 關於ros自帶包在CMakeLists.txt中的結構

這個過程其實是把 cv_bridge 當成了一個普通的庫來使用的。

而ros有一套體系來讓這些很簡便, 如 catkin components中直接加入 cv_bridge,其實底層和這個過程是一樣的。

所以這裏弄明白了,ros的底層依賴關係也差不多可以自己diy了。

4、關於刪除 cv_bridge 後的影響

這裏卸載cv_bridge後發生了ros gazebo不發佈話題的問題,其實仔細一想自帶的cv_bridge可以留着,然後通過在CMakeLists.txt中指定 cv_bridge_DIR的方式來選擇性調用cv_bridge版本。

5、 兩個版本的安裝路徑

opencv 2.4.11 檢查安裝路徑爲:  /usr/local

ros-kinetic安裝了opencv3, 檢查安裝路徑爲:

lib: /opt/ros/kinetic/lib/x86_64-linux-gnu

include: /opt/ros/kinetic/include/opencv-3.3.1-dev

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章