ROS 環境構築および簡単な使い方 (Debian9)
[History] [Last Modified] (2019/05/09 15:19:11)
Recent posts
What is this site?
A platform for makers to share their knowledge.

Share your robots/products with others.
New robots/products

概要

ロボットシステム開発のためのフレームワーク Robot Operating System (ROS) の環境構築および簡単な使い方について記載します。ここでは Debian9 を利用することにします。ROS は現行バージョン1 の Melodic Morenia ディストリビューションを扱います。

インストール

contribnon-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

ワークスペースからは複数のパッケージを利用します。新規にパッケージを作る場合は以下のようにします。rospyroscpp に依存した 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

直接依存するパッケージ、間接的にでも依存するパッケージ (関連: jhbuild list, rdepends)

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

package.xml (追記)

<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 の書き方についてはこちらに記載があります。関連ツール: supervisord

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 で開発を行うときによく利用されるツールには以下のようなものがありますrqtQt をもとにした 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

Uploaded Image

rqt_graph

Node 等の状態を可視化できます。

rqt_graph

Uploaded Image

その他のツール

  • roswtf インストールおよびシステムの状態に異常がないか検証するためのツールです。
  • rviz 三次元モデル等の可視化ツールです。
Related pages
    概要 ROS による開発で必要となる 3D モデルは STL や COLLADA データとして作成できます。FreeCAD と Blender を用いて直方体のデータを作成してみます。いずれの場合も、ROS 等で扱うために単位はメートルで出力します。 FreeCAD による直方体 STL の作成 STL はフェイスに三角形を利用した 3D モデル
    概要 ロボットシミュレータ Gazebo を ROS 開発で利用するための簡単な手順を記載します。ここでは Debian9 を利用します。個別にインストールすることもできますが、ROS を ros-melodic-desktop-full でインストールすれば gazebo もインストールされます。 URDF モデルの作成
    概要 ロボットを制御する際に複数の座標系を扱う必要があります。これら複数の座標系間の変換等を行うためのライブラリに tf2 (transform2) があります。C++ と Python がサポートされていますが、ここでは Python を用いて簡単な使い方を把握します。 tf2 チュートリアルと同様に動作検証のための