##はじめに
ROSの初歩的なコードをまとめる。
自分のメモ代わり。
(公式チュートリアルの方がわかりやすいと思います。)
関連記事は以下のとおり。
記事タイトル | 内容 |
---|---|
ROSでHello World | ROSに慣れるために簡単な処理を行う |
ROSで簡単な通信を行う | ROSの基本である通信の処理をテストする |
ROSを使って画像情報でロボットを動かす | 少し実践的に複数のシステムを動かす |
##準備
###本当にROSを初めて触る人用の準備
catkin_ws
という作業ディレクトリを作る。
この名前は慣例的に(?)決まっているものなのでROSを始める際につくりましょう。
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace
$ cd ~/catkin_ws
$ catkin_make
catkin_init_workspace
は最初に一回やるだけで大丈夫。
ってか必要なのか、これ。
catkin_make
でdevel
等のディレクトリが立ち上がる。
その後、gedit ~/.bashrc
でdevel/setup.bash
を見ているか確認する。
source ~/catkin_ws/devel/setup.bash
があれば先へ。
なければ一番下とかに記述しておく。
###パッケージの作成
ROSには「パッケージ」という概念がある。
とりあえず、なにか新しいプログラムをROSで動かしたいならパッケージを作成していくものだと思えば良い。
google検索する際も「ROS パッケージ 追加」とかで調べれば良い。
(ここらへんも正直、最新の公式チュートリアルを見た方がいい。)
$ cd ~/catkin_ws/src
$ catkin_create_pkg easy_comu rospy roscpp std_msgs
catkin_create_pkg
でパッケージを新規に作成できる。
次の引数、ここではeasy_comu
がパッケージ名。好きな名前をつけましょう。
そのあとの引数が使用する依存パッケージ。とりあえず黙って書く。
その後、以下のようにcatkin_makeで変更を反映。
$ cd ~/catkin_ws
$ catkin_make
$ source ~/catkin_ws/devel/setup.bash
パッケージがちゃんと生成されたか確認する方法としてroscd
がある。
これは、どのディレクトリにいてもrosのパッケージに飛べるコマンド。
$ cd
$ roscd easy_comu
これで正しくeasy_comu
ディレクトリに入れれば成功。
##簡単な通信システムの作成
###前提知識
ROSの主な機能は通信。
この通信は他の言語同士のファイルでも行うことができるから便利。
そしていろんな人がインターネット上にROSで動かせるモジュールを公開しているため便利。
ここでは基本的な通信をpythonによって行う。
以下の3つはROSをするなら覚えておく言葉。
- Publisher: 通信で何かを送る側。
- Subscriber: 通信で何かを受け取る側。
- Topic: 通信によって送られる何かそのもの。
関数の名前になっていたりするので、プログラムを検索するときなどに使いましょう。
###コーディング
まず、以下のようにディレクトリを準備する。
$ roscd easy_comu
$ mkdir scripts
$ cd scripts
その後、好きなエディタでtalker.py
とlistener.py
を以下のように記述する。
#!/usr/bin/env python
## coding: UTF-8
import rospy
from std_msgs.msg import String # ROS通信で文字列を取得できるようにstd_msgsというパッケージからStringという型を取得
from datetime import datetime
rospy.init_node('talker') # ノードの生成
pub = rospy.Publisher('chatter', String, queue_size=10) # chatterという名前のTopicを生成し型やらを定義
rate = rospy.Rate(10) # 10Hzで動かすrateというクラスを生成
print("Conection started...")
while not rospy.is_shutdown():
hello_str = String() # Stringというクラスで送信するメッセージ、"hello_str"を生成
timestamp = rospy.get_time()
time = datetime.fromtimestamp(timestamp) # ここらへんはROSと関係ないです
hello_str.data = "hello world(%s)" % time # 内容の書き込み
pub.publish(hello_str) # hello_strを送信!
rate.sleep() # 先程定義したrateをここで動かす
#!/usr/bin/env python
## coding: UTF-8
import rospy
from std_msgs.msg import String
def callback(message):
rospy.loginfo("get message! [%s]", message.data) # ターミナルへの表示
rospy.init_node('listener')
sub = rospy.Subscriber('chatter', String, callback) # chatterというTopicを受信!受信したら上で定義したcallback関数を呼ぶ
rospy.spin()
###実行
以下chmod
のコマンドでpythonファイルを実行ファイルとして扱う。
$ cd ~/catkin_ws/src/easy_comu/scripts
$ chmod 755 talker.py listener.py
ターミナルを3つ開き、以下の順番で実行する。
$ roscore
$ rosrun easy_comu talker.py
$ rosrun easy_comu listener.py
rosrun
のルールとして先にパッケージ名、その後実行ファイルを引数として書く。
rosrun
を使えば、どのディレクトリからでも実行することができる。
実行結果は以下のとおり。メッセージの送信が10Hzで行われているため、0.1秒に一回メッセージを取得できるはず…。
$ rosrun ros_start listener.py
[INFO] [1561534794.212049]: get message! [hello world(2019-06-26 16:39:54.211102)]
[INFO] [1561534794.312196]: get message! [hello world(2019-06-26 16:39:54.311231)]
[INFO] [1561534794.412188]: get message! [hello world(2019-06-26 16:39:54.411242)]
[INFO] [1561534794.512196]: get message! [hello world(2019-06-26 16:39:54.511235)]
[INFO] [1561534794.612122]: get message! [hello world(2019-06-26 16:39:54.611119)]
[INFO] [1561534794.712045]: get message! [hello world(2019-06-26 16:39:54.711120)]
[INFO] [1561534794.812181]: get message! [hello world(2019-06-26 16:39:54.811233)]
[INFO] [1561534794.912186]: get message! [hello world(2019-06-26 16:39:54.911233)]
[INFO] [1561534795.012254]: get message! [hello world(2019-06-26 16:39:55.011237)]
[INFO] [1561534795.112203]: get message! [hello world(2019-06-26 16:39:55.111249)]
[INFO] [1561534795.212027]: get message! [hello world(2019-06-26 16:39:55.211132)]
[INFO] [1561534795.312287]: get message! [hello world(2019-06-26 16:39:55.311287)]
[INFO] [1561534795.412052]: get message! [hello world(2019-06-26 16:39:55.411121)]
###補足
talker.py
の中の、
hello_str.data = "hello world(%s)" % time # 内容の書き込み
この記述におけるdata
ってなんやねんと思った人へ。
data
はその数行前で定義しているROSのStringクラスのメンバ変数です。
プログラミングに疎い方は、ROSが用意してくれている文字列の形式"String"にあらかじめdata
っていう名前の変数が定義されていたと思ってください。
メンバ変数の調べ方は以下のコマンドで行えます。
$ rosmsg show std_msgs/String
string data
string型でdataって名前で定義されていることがわかります。
まあ、公式サイトで調べるのが一番!