ロボットシステム開発のためのフレームワーク Robot Operating System (ROS) の環境構築および簡単な使い方について記載します。ここでは Debian9 を利用することにします。ROS は現行バージョン1 の Melodic Morenia ディストリビューションを扱います。
インストール
contrib
と non-free
をソースリストに追加します。
sudo vi /etc/apt/sources.list
deb http://deb.debian.org/debian stretch main contrib non-free
deb-src http://deb.debian.org/debian stretch main contrib non-free
deb http://deb.debian.org/debian-security/ stretch/updates main contrib non-free
deb-src http://deb.debian.org/debian-security/ stretch/updates main contrib non-free
deb http://deb.debian.org/debian stretch-updates main contrib non-free
deb-src http://deb.debian.org/debian stretch-updates main contrib non-free
ros-melodic
をソースリストに追加します。
sudo apt update
sudo apt install dirmngr
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
# ↑初回実行時は失敗することがあります。
sudo apt update
ros-melodic
をインストールして初期化します。
sudo apt install ros-melodic-desktop-full
sudo rosdep init
rosdep update
環境変数等を bash 起動時に自動で読み込むようにします。
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
その他必要になりそうなパッケージをインストールしておきます。
sudo apt install python-rosinstall python-rosinstall-generator python-wstool build-essential
以下のような ROS コマンドが利用できることを確認します。roscd
は ROS の作業用ディレクトリに移動するためのコマンドです。/opt/ros/melodic/share/rosbash/rosbash
内で定義されています。
roscd
用語
- Node 何らかの機能を持ったプロセスです。
- Master Node 情報を管理します。
- Parameter Server Node 間でパラメータ情報等を共有するための保管場所です。Master が提供します。
- Services ある Node で提供することで別の Node から同期的に RPC を受け付けます。
- Topics 多対多で非同期に Node 間通信するための Pub-Sub のトピックです。
- Messages Node 間で情報をやり取りするためのデータ単位です。
- Bags メッセージをファイルに保存するためのフォーマットです。
ワークスペースとパッケージ
ワークスペースの初期化
mkdir -p mydir/src
cd mydir/src/
catkin_init_workspace
cd ../
catkin_make
echo "source `pwd`/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
env | grep ROS_PACKAGE_PATH
パッケージの追加
ROS ではパッケージとよばれる単位でプログラムを管理します。
echo $ROS_PACKAGE_PATH
ROS をインストールすると以下のようなパッケージがインストールされます。
rospack find rospy
rospack find roscpp
ワークスペースからは複数のパッケージを利用します。新規にパッケージを作る場合は以下のようにします。rospy
と roscpp
に依存した mypkg
が作成されます。
cd mydir/src/
catkin_create_pkg mypkg rospy roscpp
ワークスペースにパッケージを追加したら必要となるソフトウェアをシステムにインストールします。
rosdep update
rosdep install mypkg
ワークスペースに追加したパッケージは以下のようにビルドできます。内部的に cmake と make が実行されます。
cd ../
catkin_make
基本的なコマンド
パッケージの情報を取得 (rospack)
名前だけ一覧、パス情報込み
rospack list-names
rospack list
パス情報
rospack find mypkg
直接依存するパッケージ、間接的にでも依存するパッケージ
rospack depends1 mypkg
rospack depends mypkg
指定したパッケージに直接依存するパッケージ、指定したパッケージに間接的にでも依存するパッケージ
rospack depends-on1 mypkg
rospack depends-on mypkg
ディレクトリ移動 (roscd)
パッケージ名を指定してディレクトリ移動できます。
roscd rospy
roscd roscpp
roscd mypkg
roscd mypkg/src
ROS プログラムのログは $HOME/.ros/log
に保存されています。以下のコマンドで移動できます。
roscd log
パッケージ内のファイルを確認して編集、コピー、実行 (rosls,rosed,roscp,rosrun)
rosls mypkg
rosed mypkg package.xml
roscp mypkg package.xml .
rosrun mypkg talker.py
Master、Parameter Server (roscore)
前述の Master プロセスを起動します。既定では $ROS_MASTER_URI
でサービスを開始します。-p
オプションでポート番号を変更できます。
roscore
roscore -p 1234
Parameter Server 操作 (rosparam)
一覧取得、すべての値を取得
rosparam list
rosparam get /
特定の値を設定、取得、削除
rosparam set /myparam 123
rosparam get /myparam
rosparam delete /myparam
すべての値をファイルに保存、ファイルから読み出し
rosparam dump params.yaml
rosparam load params.yaml
起動したプロセスの情報を取得 (rosnode)
rosnode list -a
rosnode info /talker
rosnode ping /talker
rosnode kill /talker
rosnode machine
rosnode machine HOSTNAME
トピック情報を取得 (rostopic)
rostopic list
rostopic type /chatter
rostopic info /chatter
rostopic hz /chatter
rostopic echo /chatter
rostopic pub -r 1 /chatter2 std_msgs/String hello
サービス情報を取得 (rosservice)
rosservice list -n
rosservice info /add_two_ints
rosservice type /add_two_ints
rosservice uri /add_two_ints
rosservice call /add_two_ints 1 2
メッセージとサービスの型情報を取得 (rosmsg,rossrv)
rosmsg list
rosmsg show std_msgs/String
rossrv list
rossrv show mypkg/AddTwoInts
Pub-Sub 非同期通信
こちらのチュートリアルに記載されている、Pub-Sub Python パッケージのサンプルをもとにしています。rospy
に依存したパッケージを作成します。
catkin_create_pkg mypkg rospy
roscd mypkg
パッケージ内の実行ファイル置き場として scripts
ディレクトリを作成します。
mkdir scripts
chmod +x scripts/talker.py
chmod +x scripts/listener.py
talker.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from rospy import Publisher
from rospy import Rate
from rospy import init_node
from rospy import is_shutdown
from rospy import loginfo
from rospy import get_name
from std_msgs import msg
def Main():
# トピック名、メッセージの型、キューの最大長
pub = Publisher('chatter', msg.String, queue_size=10)
# ノードの初期化
init_node('talker', anonymous=False)
# 一秒間に何回トピックに情報をパブリッシュするか
rate = Rate(2) # Hz
# Ctrl-C 等が押されていないことを確認しつつループ
while not is_shutdown():
msgStr = msg.String(data='ok')
loginfo('%s publish %s' % (get_name(), msgStr.data))
pub.publish(msgStr)
rate.sleep()
if __name__ == '__main__':
Main()
listener.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from rospy import init_node
from rospy import Subscriber
from rospy import spin
from rospy import get_name
from rospy import loginfo
from std_msgs import msg
def Callback(msgStr):
loginfo(get_name() + ', received %s', msgStr.data)
def Main():
init_node('listener', anonymous=False)
Subscriber('chatter', msg.String, Callback)
# 何もしない別スレッドを新規に生成してプロセスの終了を防ぎます。
spin()
if __name__ == '__main__':
Main()
実行例
roscore
rosrun mypkg talker.py
rosrun mypkg listener.py
RPC Service 通信
こちらのチュートリアルに記載されている、Service の Python パッケージのサンプルをもとにしています。rospy に依存したパッケージを作成します。
catkin_create_pkg mypkg rospy
roscd mypkg
パッケージ内の実行ファイル置き場として scripts
ディレクトリを作成します。
mkdir scripts
chmod +x scripts/server.py
chmod +x scripts/client.py
server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from mypkg.srv import AddTwoInts
from mypkg.srv import AddTwoIntsResponse
from rospy import init_node
from rospy import Service
from rospy import spin
from rospy import get_time
from rospy import get_caller_id
def Main():
init_node('add_two_ints_server')
s = Service('add_two_ints', AddTwoInts, HandleAddTwoInts)
print 'Ready to add two ints.'
spin()
def HandleAddTwoInts(req):
print '%s, %s' % (get_time(), get_caller_id())
print 'Returning [%s + %s = %s]' % (req.a, req.b, (req.a + req.b))
return AddTwoIntsResponse(req.a + req.b)
if __name__ == '__main__':
Main()
client.py (Master に登録する必要がないため init_node は不要です)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from mypkg.srv import AddTwoInts
from rospy import wait_for_service
from rospy import ServiceProxy
from rospy import ServiceException
def Main():
# サービスが利用できるようになるまで待ちます。
wait_for_service('add_two_ints')
try:
addTwoInts = ServiceProxy('add_two_ints', AddTwoInts)
res = addTwoInts(1, 2)
print res.sum
except ServiceException, e:
print 'Service call failed: %s' % e
if __name__ == '__main__':
Main()
Service でやり取りするメッセージの型の情報は、こちらのチュートリアルと同様に以下のようにして設定します。
roscd mypkg
mkdir srv
vi srv/AddTwoInts.srv
vi package.xml
vi CMakeLists.txt
cd ../..
catkin_make install
source ~/.bashrc
srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
CMakeLists.txt (追記)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_service_files(
FILES
AddTwoInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
実行例
roscore
rosrun mypkg server.py
rosrun mypkg client.py
複数の ROS ノードをまとめて起動 (roslaunch)
rosrun によって個別の Node を起動する方法以外に、設定ファイルをもとに roslaunch によってまとめて複数の Node を起動する方法があります。関連チュートリアルはこちらです。XML の書き方についてはこちらに記載があります。
roscd mypkg
talker.launch
<launch>
<param name="myparam" value="ok" />
<node name="talker"
pkg="mypkg"
type="talker.py">
<param name="myparam2" value="ok2" />
</node>
</launch>
listener.launch
<launch>
<node name="listener"
pkg="mypkg"
type="listener.py">
</node>
</launch>
main.launch
<launch>
<include file="$(find mypkg)/talker.launch" />
<include file="$(find mypkg)/listener.launch" />
<group ns="mynamespace">
<include file="$(find mypkg)/talker.launch" />
<include file="$(find mypkg)/listener.launch" />
</group>
</launch>
実行
roslaunch mypkg main.launch
動作確認
rosnode list
rostopic list
roscd log
tail -f talker-*.log
tail -f listener-*.log
tail -f mynamespace-talker-*.log
tail -f mynamespace-listener-*.log
rosparam get /myparam
rosparam get /talker/myparam2
rosparam get /mynamespace/myparam
rosparam get /mynamespace/talker/myparam2
デバッグツール
ROS で開発を行うときによく利用されるツールには以下のようなものがあります。rqt は Qt をもとにした ROS における GUI 開発フレームワークです。
rosbag
トピックからパブリッシュされた情報を一定期間分だけファイルに保存して、後から再生することができます。-l
は保存した情報をループして再生するためのオプションです。GUI ツールとして rqt_bag があります。
rosbag record /chatter
rosbag play 2019-03-19-00-33-56.bag -l
rostopic list
rqt_plot
トピックにパブリッシュされたメッセージをグラフ化することができます。geometry_msgs/Twist は速度情報を格納するための型です。
rostopic pub -r 1 /mypub geometry_msgs/Twist '{linear: {x: 0.1, y: 0.5, z: 1.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}'
rqt_plot /mypub/linear
rqt_graph
Node 等の状態を可視化できます。
rqt_graph
その他のツール
関連記事
- ROS/tf による座標変換ロボットを制御する際に複数の座標系を扱う必要があります。これら複数の座標系間の変換等を行うためのライブラリに tf2 (transform2) があります。C++ と Python がサポートされていますが、ここでは Python を用いて簡単な使い方を把握します。 tf2 チュートリアルと同様に動作検証のためのパッケージを用意します。ROS ノードのスクリプトを格納
- ロボットシミュレータ Gazebo の簡単な使い方 (ROS)ロボットシミュレータ Gazebo を ROS開発で利用するための簡単な手順を記載します。ここでは Debian9 を利用します。個別にインストールすることもできますが、ROS を ros-melodic-desktop-full でインストールすれば gazebo もインストールされます。 [URDF モデルの作成](http://wiki.ro
- STL ファイルに Blender でテクスチャを適用して COLLADA を作成ROS による開発で必要となる 3D モデルは STL や COLLADA データとして作成できます。FreeCAD と Blender を用いて直方体のデータを作成してみます。いずれの場合も、ROS 等で扱うために単位はメートルで出力します。 FreeCAD による直方体 STL の作成 STL はフェイスに三角形を利用した 3D モデルを表現するためのファイルフォーマットの一つです。多くのソフ...
- 輪郭に関連した画像処理 (OpenCV3 C++)cv::Canny などで検出したエッジをもとに cv::findContours で輪郭を計算できます。輪郭に関連した処理の例を記載します。 輪郭の描画 #include <opencv2/opencv.hpp> #in
- Qt for Python (PySide2) の基本的な使い方QT を Python から利用するためのライブラリには PyQt や PySide 等が存在します。PySide は元々 QT4 向けのライブラリでしたが、QT5 に対応するために新たに PySide2 が開発されました。PySide2 は Qt for Python ともよばれています。 Q: PySide? Qt for Python? what is the name?A: The nam...