PythonでROSを動かす!rospyでメッセージのやり取りをする方法

Python

本記事の内容

・ROSを通じて,pythonで書いたコードからコードへデータ(値)を送る(rospy使用).

・ROSのワークスペース,パッケージの作り方からコーディングまでを丁寧に解説.

・基本的にはこちらの記事を参考にさせて頂きましたが,実行(rosrun)時にエラーがあったので,その解決方法を追加してこの記事を書きました.

ROS用語の確認

※ROS初心者でよく分からないよ!という人は,とりあえず飛ばしてROSを使いながら慣れれば大丈夫だと思います.

・ワークスペース

ファイルを入れていく一番大本のファイルのことです.つまり,一番上のディレクトリです.ワークスペースに,必要なファイルを入れていきます.

・パッケージ

任意の機能をつめたソフトウェアの集合です.

・ノード

一つの実行ファイルのことです.例えば,「Hello world! と出力するファイル」や「ロボットを前方に動かすファイル」です.1つのノードはROSを使用して他のノードとやりとりします.

・トピック

ノードはメッセージをトピックへ向けてPublish(配信)し,同様にSubscribe(購読)することでトピックからメッセージを受け取ることができます.

・メッセージ

トピックへ配信したり購読したりするときの ROS のデータ型です.とりあえず何かのデータだと思えばOKです.

・roscore

ROSを立ち上げるときに必要なコマンドです.

・rosrun

ノードを実行するときに使用するコマンドです.

・catkin_make

ワークスペース内のパッケージを一括ビルドするコマンドです.

ROSをインストール

ROSのインストールは省略します.検索すればインストール方法の記事はたくさん出てくるので,そちらをご覧ください(ROSはUbuntu OS上で動くソフトです).

また,Pythonをインストールしていない方は,こちらなどを参考にインストールしておいてください.

ワークスペースを作る

ノードやそのほかのファイルを入れていくワークスペースを作ります.Ubuntuのターミナルで,以下のコマンドを入力して実行.

mkdir -p ros_ws/src
cd ros_ws
source /opt/ros/indigo/setup.bash
catkin_make

コマンドの説明

・mkdirでros_wsというワークスペースと,その中にsrcというファイルを作っています.

・cd ros_wsでros_wsの中に移動しています.

source /opt/ros/indigo/setup.bashの「indigo」の部分は,ROSのバージョンに合わせて書き換えてください.例えば,Kineticを使っている場合はsource /opt/ros/kinetic/setup.bashです.Melodicに関しても同様です.

・catkin_makeで,ワークスペースのプロジェクトをビルドしています.これをすることで,ros_wsの中に必要なファイル(build, devel, src)が生成されます.catkin_makeをした後のファイル構造は以下のようになっていると思います.確認してみてください.

ファイル構造

ros_ws
|--build
|--devel
|--src

・build … ビルドに関する設定やmakeのlogのファイルが入っています。

・devel … 実行ファイルやmakeによって生成されたものが入っています。

・src … ユーザがソースコードを保存する場所です。ほとんどの場合,我々はここしか編集しません.

(ワークスペース作成完了)

パッケージを作る

専用のパッケージをsrcの中に作ります.

まず,

cd src

でsrcの中に入り,以下のコマンドを実行してください.

catkin_create_pkg ros_adder roscpp rospy std_msgs

これで,ros_adderというパッケージが作られました.

roscpp、std_msgs,sensor_msgsはros_adderと依存関係を持たせるパッケージです.

もう一度,catkin_makeします.

cd ~/ros_ws/
catkin_make

(パッケージ(の基礎)作成完了)

メッセージファイルを作る

ROSでは処理に必要なデータは基本的にメッセージとして通信を行ないます。

簡単なメッセージファイルを作ります.ターミナルで以下のコマンドを実行.

cd ~/ros_ws/src/ros_adder
mkdir msg; cd msg
touch Adder.msg

コマンドの説明

・cd ~/ros_ws/src/ros_adderでros_wsの中のsrcの中のros_adderに入ります.ros_adderは先ほど作ったパッケージファイルです.

・mkdir msg でmsgというファイル(ディレクトリ)をros_adderの中に作り,cd msgでそのmsgファイルに入ります.

・touch Adder.msgでmsgの中に空のファイルを作成します.

メッセージファイルの編集

メッセージファイルAdder.msgを編集します.直接ファイルからたどってAdder.msgを開いてもいいですし,

gedit Adder.msg

emacs Adder.msg

で開いても大丈夫です.できるやり方で開いてください.メモ帳でも構いません.

メッセージファイルAdder.msgの中には以下の記述をしてください。 このmsgファイルではint型の変数を2個保有していることになります。

Adder.msg

int32 arg_x
int32 arg_y

変数の型は他にもあるので,他の型が必要な場合は調べてみてください.

CMakeLists.txtの編集

メッセージファイルAdder.msgを元にメッセージ型を定義するヘッダファイルが生成されます。

cd ~/ros_ws/src/ros_adder

にあるCMakeLists.txtを開き,ヘッダファイル生成の設定を行うため以下のファイルを編集してください。

CMakeLists.txt

#該当部分をコメントアウト.また,必要なものを追加
#7行目あたり
find_package(catkin REQUIRED COMPONENTS
    roscpp
    rospy
    std_msgs
    message_generation
)

#45行目あたり
## Generate messages in the 'msg' folder
add_message_files(
    FILES
#   Message1.msg
#   Message2.msg
    Adder.msg
 )

#66行目あたり
generate_messages(
     DEPENDENCIES
     std_msgs
)

#104行目あたり
catkin_package(
#   INCLUDE_DIRS include
     LIBRARIES ros_adder
     CATKIN_DEPENDS roscpp rospy std_msgs
     DEPENDS system_lib
)

再び,catkin_make.

cd ~/ros_ws
catkin_make

これができたら,

ls ~/ros_ws/devel/lib/python2.7/dist-packages/ros_adder/msg/

のコマンドを実行し,以下がターミナルに表示されることを確認してください.

_Adder.py  __init__.py

これでメッセージファイルおよびCMakeLists.txtの編集は完了です.

ノードを作る

いよいよ,ノード(自分がやりたいコード)を書いていきます.

まず,para_in.pyとadder.pyという,空のノードファイルを作成します.

cd ~/ros_ws/src/ros_adder/
mkdir scripts; cd scripts
touch para_in.py adder.py

para_in.pyは処理に必要なデータをPublishするPublisherで,

adder.pyはpublisherから受け取ったデータを表示するSubscriberです.

Publisherを作成

scriptsに入っているpara_in.pyを開き,以下のように書いてください.

para_in.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
# license removed for brevity

# pythonでROSのソフトウェアを記述するときにimportするモジュール
import rospy

# 自分で定義したmessageファイルから生成されたモジュール
from ros_adder.msg import Adder

def para_in():
    # 初期化宣言 : このソフトウェアは"para_in"という名前
    rospy.init_node('para_in', anonymous=True)

    # nodeの宣言 : publisherのインスタンスを作る
    # input_dataというtopicにAdder型のmessageを送るPublisherをつくった
    pub = rospy.Publisher('input_data', Adder, queue_size=100)

    # 1秒間にpublishする数の設定
    r = rospy.Rate(5)

    para_x = 0
    para_y = 2

    # Adder型のmessageのインスタンスを作る
    msg = Adder()

    # ctl + Cで終了しない限りwhileループでpublishし続ける

    while not rospy.is_shutdown():

        msg.arg_x = para_x
        msg.arg_y = para_y

        # publishする関数
        pub.publish(msg)
        print "published arg_x=%d arg_y=%d"%(msg.arg_x,msg.arg_y)
        para_x += 1
        para_y += 1

        r.sleep()

if __name__ == '__main__':
    try:
            para_in()

    except rospy.ROSInterruptException: pass

Subscriberをつくる

同様に,adder.pyに以下のように書いてください.

adder.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
# license removed for brevity
import rospy
from ros_adder.msg import Adder

# Subscribeする対象のトピックが更新されたら呼び出されるコールバック関数
# 引数にはトピックにPublishされるメッセージの型と同じ型を定義する
def callback(data):
    # 受けとったmessageの中身を足し算して出力
    print data.arg_x + data.arg_y

def adder():
    rospy.init_node('adder', anonymous=True)

    # Subscriberとしてimage_dataというトピックに対してSubscribeし、トピックが更新されたときは
  # callbackという名前のコールバック関数を実行する
    rospy.Subscriber('input_data', Adder, callback)

    # トピック更新の待ちうけを行う関数
    rospy.spin()

if __name__ == '__main__':
    adder()

これら2つのノードが書けたら,ビルドしてください.

cd ~/ros_ws/
catkin_make

これで,ノードの作成も完了です.

ノードを実行

上までの工程に問題がなければ,さっそく実行してみます.

ターミナルは3つ開き,以下のコマンドを上から順番にそれぞれ入力してください。

(別ターミナルは「Ctrl + Shift + T」で開くことができます.ただし,はじめのターミナルは「Ctrl + Alt + T」で開きます.)

1つ目のターミナル(roscore)

ROSではroscoreというコマンドを始めに起動することで,様々なことをスタートする準備が整います.ノード間の通信も,roscoreを起動しなければできません.

以下を実行しましょう.

cd ~/ros_ws
source devel/setup.bash
roscore

roscoreが成功すれば,ターミナルの最後に「stared core service [/rosout]」と出て,止まると思います.

2つ目のターミナル(subscriber)

単体のノードの実行はrosrunというコマンドで行います.まず,subscriberを起動しましょう.

cd ~/ros_ws
source devel/setup.bash
rosrun ros_adder adder.py

筆者の場合は,ここでエラーが出て,subscriberを起動することができませんでした.

エラーは,「Couldn’t find executable named …」というものです.

調べたところ,解決方法として,以下のコマンドを実行すれば無事起動することができました.

sudo chmod +x adder.py

意味はよく分かりませんが,できたので良しとしましょう.

subscriberを起動した段階では,ターミナルには何も出ないと思います.

3つ目のターミナル(publisher)

最後に,publisherを起動します。

cd ~/ros_ws
source devel/setup.bash
rosrun ros_adder para_in.py

こちらも,「Couldn’t find executable named …」というエラーが出たら,

「sudo chmod +x para_in.py」で対応しましょう.

結果

起動に成功したら,以下のような結果がターミナルに表示されるはずです.

2つ目のターミナル:

root@localhost:~/ros_ws$ rosrun ros_adder adder.py
2
4
6
8
10
12
14

3つ目のターミナル:

root@localhost:~/ros_ws$ rosrun ros_adder para_in.py
published arg_x=0 arg_y=2
published arg_x=1 arg_y=3
published arg_x=2 arg_y=4
published arg_x=3 arg_y=5
published arg_x=4 arg_y=6
published arg_x=5 arg_y=7

結果を見て分かるように,publisherであるpara_in.pyから1ずつ増える2つの値(arg_xとarg_y)をメッセージとしてsubscriberであるadder.pyに渡し,adder.pyの中で2つの値を足していることが分かります.

「Ctrl + C」でこのプラグラムを終了することができます.

おわりに

pythonを使ってROSでメッセージのやり取りをすることができたので,将来的には以下の記事のような「Pythonでドローンを操作する」プログラムをROSで書きたいと思っています.

コメント

タイトルとURLをコピーしました