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を選択するのがベターな気がします.