masato-ka's diary

日々思ったこととか、やったことの備忘録。

Jetbot+ROS+Python3環境構築

この記事について

この記事ではJetbotのOSイメージにROSをインストールしPython3でROSのスクリプトを記述する方法について説明する。Jetbotのイメージで提供されているPythonのライブラリはPython3で記載されている。しかし、公式ではROSはPython2系対応のみだ。そのためJetbotのライブラリを利用してJetbot向けのROSのパッケージを作ることができない。 そこでROSのパッケージ開発(rospyなどを使った開発)のみPython3で行えるようにした。今回はROSのシステムはPython2.7で動作する。実際は以下のように ROS全てをPython3で動くようソースからビルドするのが望ましいだろう。

ros.youtalk.jp

手順

1. ROSのインストール

ROSのインストールは公式ページに従って進める。今回ROSのバージョンはMelodicをインストールした。またros-melodic-desktopを利用した。Jetson nano及びJetbotの場合、OSはUbuntu 18.04 がインストールされている。

roscore, rosrunが実行できる状態まで持っていく。またpython2系でimport rospyができるところまで確認する。

2. Python3向け準備

ROSコマンドやPYTHONPATHはROSインストール時にインストールされるPython2.7をさしている。ROSのPythonライブラリであるrospyやsensor_msgsなどはPython3系でそのまま動くようになっている。そこで、Python3からPython2.7のdist-packageにインストールされているROSライブラリを参照できるようにする。

2. Python3からrospyを使えるようにする。

基本的にはPyhotn3のパスにPyhton2.7のdist-packageのパスが追加できればいい(と信じている)rospkgというパッケージをインストールするとこれが実現できる。何らかの副作用だと思うが深くは追っていない。

sudo pip3 install rospkg catkin_pkg

パッケージのインストール後、Python3でrospy, sensor_megsがインポートできるようになる。

3. vision_opencvのインストール

この状態でOpenCVとROSのブリッジライブラリcv_bridgeライブラリを利用するとエラーが発生する。cv_bridgeで利用しているネイティブライブラリがPython2系向けにコンパイルされているためだ。そこで、cv_bridge自体をPython3系向けにコンパイルし直す必要がある。手順は以下のページを参考にした。一部パスがx86向けなので、ARM向けに修正した。

How to setup ROS with Python 3 - Omri Ben-Bassat - Medium

  • python3系向けにビルドするための準備
mkdir ~/catkin_build_ws && cd ~/catkin_build_ws
catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.6m.so
catkin config --install
mkdir src
cd src
git clone -b melodic https://github.com/ros-perception/vision_opencv.git
cd ~/catkin_build_ws
catkin build cv_bridge
source install/setup.bash --extend

これで、Python3でROSパッケージを書く準備が整った。

4. スクリプトの書き方と実行方法

rosのワークスペースで新しいパッケージを作成する。ワークスペースはパスさえ通っていれば先ほどのワークスペースと違うものでも大丈夫。 パッケージ内にscriptsフォルダを作成し、次のファイルを作成する。

  • camera.py
#!/usr/bin/env python3

import yaml
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
from jetbot import Camera
from sensor_msgs.msg import CameraInfo

NODE_NAME = 'jetbot_camera_node'
IMAGE_TOPIC = 'jetbot/image_raw'

class JetbotCamera:

    def __init__(self, width=640, height=480, calib_file=''):
        self.calib_file = calib_file
        self.camera = Camera(width=width,height=height)
        self.publisher = rospy.Publisher(IMAGE_TOPIC, Image, queue_size=1)
        self.bridge = CvBridge()

    def start(self):
        rospy.init_node(NODE_NAME)
        self.camera.observe(self.image_proc, names='value')
        self.camera.start()
        rospy.spin()

    def image_proc(self, change):
        image_value = change['new']
        cv2_image = self.bridge.cv2_to_imgmsg(image_value, 'bgr8')
        self.publisher.publish(cv2_image)

if __name__ == '__main__':
    jetbot_camera = JetbotCamera()
    jetbot_camera.start()
    pass

ファイル先頭に#!/usr/bin/env python3を記載する。またファイルのパーミッションを755に設定し、実行ファイルにする。その後以下のコマンドで実行する。

roscore
#別ターミナルに切り替え
rosrun ros_package-name camera.py

そうするとjetbot/image_rawというトピックが設定される。rosのimage_viewで画像を表示させてみる。

rosrun image_view image_veiw image:=jetbot/image_raw

まとめ

jetbot用に車輪のコントロールと画像を受信するrosパッケージを作ってみた。広角カメラのカメラパラメータも一緒に入ってる。 時間があるときにちょくちょくメンテする予定。

github.com