cv_bridgeをpython3(virtualenv)で使いたい時の解決法


経緯

ROSを使って色々イジイジしていたときのことです。カメラの入力ノードからRGBデータが送られてくるので、それを別のノードで受け取りたいと思い、cv_bridgeを使おうとしていました。下のような感じです。

from cv_bridge import CvBridge

def prediction(msg):
    bridge = CvBridge()
    img = bridge.imgmsg_to_cv2(msg, "bgr8")

しかし、ビルドして実行してみたところ、以下のようなエラーが発生しました。

File "/opt/ros/melodic/lib/python2.7/dist-packages/cv_bridge/core.py", line 91, in encoding_to_cvtype2
    from cv_bridge.boost.cv_bridge_boost import getCvType
ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)

調べてみると、cv_bridgeがpython2でビルドされていることが原因のようでした。自分は実行環境がpython3(virtualenv)だったので、cv_bridgeをソースコードからビルドする必要がありました。

環境

  • ROS melodic
  • python3.6(virtualenv)
  • ubuntu18.04
  • Jetson AGX Xavier

最初にやった方法

最初はこちらの方法を参考にしてやってみました。ローカルのpython3が実行環境の場合は、上手く行くのかもしれませんが、virtualenvを使っていた自分の環境ではうまく行きませんでした。一応共有しておきます。

$ cd catkin_ws
$ catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.5m -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.5m.so
$ catkin config --install
$ git clone https://github.com/ros-perception/vision_opencv.git src/vision_opencv
$ apt-cache show ros-melodic-cv-bridge | grep Version
$ cd src/vision_opencv/
# たぶんの下のバージョンだった気がします。apt-cache showで出てきたものです。
$ git checkout 1.13.0
$ cd ../../
$ catkin build cv_bridge
$ source install/setup.bash --extend

virtualenvを使っていた自分の環境では、cv_bridgeは無事にビルドされるのですが、ビルド後に自前の他のノードを一緒のcatkin_wsでビルド実行すると下のようなエラーが発生してしまいました。

RLException: [sample.launch] is neither a launch file in package [sample_proc] nor is [sample_proc] a launch file name

ここから結構沼にハマってしまいました。犠牲者を減らすために、自分が解決した方法を共有します。

最終的な解決法

こちらのリポジトリの環境が、自分と同じようにvirtualenv上のpython3でcv_bridgeを使っていたので、そこからヒントを得ました。
大事なことは、2つあります。1つは、cv_bridgeのビルドを自前のワークスペースとは別のワークスペースで行うことです。もう1つは、自分のスクリプトのcv_bridgeをimportしている行の前で、python2.7のパスを削除することです。具体的な手順は以下の通りです。

$ sudo apt install python-catkin-tools python3-dev python3-catkin-pkg-modules python3-numpy python3-yaml ros-melodic-cv-bridge
$ mkdir -p cv_bridge_ws/src && cd cv_bridge_ws
$ git clone https://github.com/ros-perception/vision_opencv.git src/vision_opencv
$ apt-cache show ros-melodic-cv-bridge | grep Version
$ cd src/vision_opencv/
# apt-cache showの結果のversionの値に切り替えてください
$ git checkout 1.13.0
$ cd ../../
# 環境により、DPYTHON_LIBRARYのaarch64-linux-gnuの部分は変わります
$ catkin config -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.6m.so
$ catkin build
$ source devel/setup.bash --extend
$ cd ../catkin_ws
# 自前のノードをビルド
$ catkin build
$ source devel/setup.bash

さらに自分のスクリプトも変更します。sys.path.removeの文の下にはcv_bridgeのimportの文だけにしてあげてください。

import sys
sys.path.remove('/opt/ros/melodic/lib/python2.7/dist-packages')
from cv_bridge import CvBridge

def prediction(msg):
    bridge = CvBridge()
    img = bridge.imgmsg_to_cv2(msg, "bgr8")

これにより、python2のcv_bridgeではなく、python3のcv_bridgeが実行時に呼び出されるようになります。

まとめ

もうmelodicはいやだ(笑)。noeticかROS2使いたい。

間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。