ROSのCvBridgeをPython3で使う

はじめに

ROSで画像をMessageとしてPub/Subしたい場合は,CvBridgeを使うのが一般的だと思います.
しかし,Python3からCvBridgeを使おうとするとエラーになります.
前回,ROSノードをPython3で動かす方法を紹介しました)

CvBridge自体はPython2用にインストールされていて,Python3でROSノードを動かすとPython3でCvBridgeを動かすことになるので,エラーになります.
そこでCvBridgeをPython3用にビルドするのですが,ネットの記事だとエラーになったので,解決策を備忘録的に残します.

環境構築

Pythonはビルドイン・仮想環境どちらでも問題ないです.
(どちらかというと仮想環境向けです)

$ mkdir -p ~/cvbridge_build_ws/src
$ cd ~/cvbridge_build_ws/src
$ git clone -b melodic https://github.com/ros-perception/vision_opencv.git
$ cd vision_opencv
$ git checkout 578af4d6c7846876b3fc64512b1cc92a54894483
$ cd ../..
$ source /opt/ros/melodic/setup.bash
$ catkin config \
    -DCMAKE_BUILD_TYPE=Release \
    -DSETUPTOOLS_DEB_LAYOUT=OFF\
    -DPYTHON_EXECUTABLE={Pythonのパス} \
    -DPYTHON_LIBRARY={Pythonのlibパス} \
    -DPYTHON_INCLUDE_DIR={Pythonのincludeパス}
$ catkin config --install
$ catkin build cv_bridge
$ source install/setup.bash --extend

ex)
$ catkin config \
    -DCMAKE_BUILD_TYPE=Release \
    -DSETUPTOOLS_DEB_LAYOUT=OFF\
    -DPYTHON_EXECUTABLE=~/.anyenv/envs/pyenv/versions/3.9.1/bin/python \
    -DPYTHON_LIBRARY=~/.anyenv/envs/pyenv/versions/3.9.1/lib/libpython.3.9.so \
    -DPYTHON_INCLUDE_DIR=~/.anyenv/envs/pyenv/versions/3.9.1/include/python3.9

Checkoutしてバージョンを戻していますが,最新でも問題ないと思います.

開発の際の注意点

元々入っているPython2のCvBridgeを削除しない場合,
PYTHONPATHの順番に注意しないとビルドしたCvBridgeが使われません.

ROS本体の順番が先だとPython2のCvBrdigeが使われます.

この順番だとダメ(root直下にワークスペースを作ってるので以下のようになっているので,順番だけ見てください)
$ echo $PYTHONPATH
/opt/ros/melodic/lib/python2.7/dist-packages:/cvbridge_build_ws/install/lib/python3.9/site-packages

解決策としては,以下.

  1. PYTHONPATHの先頭に明示的に追加する
  2. sourceの順番を変える

1.PYTHONPATHの先頭に明示的に追加する

こちらは2回記述されてすっきりしないのと,site-packagesまで記載しないといけないので面倒です.

$ export PYTHONPATH=~/cvbridge_build_ws/install/lib/python3.9/site-packages/$PYTHONPATH

2.sourceの順番を変える

ROS(関連)のsetup.shの中を見ると,自身のPYTHONPATHをPYTHONPATHの先頭に追加しています.
なので,ROS本体のsetup.bash(sh)より後にCvBridgeのsetup.bash(sh)を実行すれば解決します.

Dockerfileで環境を作っている場合は,
bashrcに記載するかentrypointで順番をコントロールすれば面倒はないかと思います.

まとめ

CvBridgeをPython3から使う方法を紹介しました.
ご参考になれば幸いです.

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

ROSノードをPython3で動かす

はじめに

最近ROS Melodicを触っています.
ROS1ではPython2が標準になっていて,普段Python3を使っている身からするとやりにくいです.
(サポートも切れていて時流に沿ってないですしね)

しかし,ROS1でしかサポートされていないノードも多々あると思うので,
ROS1が避けられないこともあるかと思います.
(OpenVSLAMなど ← develop版ではROS2をサポートとしているようですが)

そこで,ROS本体はPython2で動かしつつ,ROSノードはPython3で動かす方法を取りました.
備忘録的に残しておきます.

ROSをPython3用にビルドする方法も探すと出てきますが,
時間がかかったりうまくいかなかったりするのでこの方法が簡単です.

環境構築

ROSインストール

以下を実行してROSをインストールします.
ROS Wikiの通りです)

ROSのインストール準備
$ apt-get update
$ apt-get install -y dirmngr gnupg2
$ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
$ echo "deb http://packages.ros.org/ros/ubuntu bionic main" > /etc/apt/sources.list.d/ros1-latest.list

ROSのインストール(Desktop Fullをインストールしています)
$ apt-get install -y ros-melodic-desktop-full
$ apt-get install -y -essential python-rosdep python-rosinstall python-vcstools

rosdep初期化&更新
$ rosdep init
$ rosdep update --rosdistro melodic

Python×ROS

Python自体の環境構築は省きますが,ビルドインのPythonでも問題ありませんし,pyenvなどの仮想環境でもOKです.
PythonにROSのコマンドをインストールします.
catkin_toolsはpipでインストールすると使うに際エラーが出るので,gitから直接インストールします.

$ pip install trollius rosdep rospkg rosinstall_generator rosinstall wstool vcstools catkin_pkg
$ pip install git+https://github.com/catkin/catkin_tools

Catkinワークスペースの作成

Catkinワークスペースを作る際に使用したいPythonを指定します.

$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws
$ catkin_make -DPYTHON_EXECUTABLE={Pythonのパス}
$ source devel/setup.sh

ex)
$ catkin_make -DPYTHON_EXECUTABLE=~/.anyenv/envs/pyenv/versions/3.9.1/bin/python

Dockerfileの場合は,ここはentrypointにしておくと良いです.
(sourceの部分はbashrcに書くようにするなど工夫する)

開発

rosrunで実行すると,Python3で実行したいノードはPython2から起動されますが,
#!(シバン)を書いておくことでPython3でノードを実行することができます.

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def talker():
    rospy.init_node('talker')
    word = rospy.get_param("~content", "default")
    pub = rospy.Publisher('chatter', String, queue_size=10)

    r = rospy.Rate(1) # 10hz
    while not rospy.is_shutdown():
        str = "send: %s" % word
        rospy.loginfo(str)
        pub.publish(str)
        r.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

まとめ

ROSノードをPython3で実行するための環境構築に関して書きました.
特にしがらみがないのであればROS2を選択するのがベターな気がします.

シェアする

  • このエントリーをはてなブックマークに追加

フォローする