ロボットシステム開発のためのフレームワーク 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
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 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 rospy
roscd roscpp
roscd mypkg
roscd mypkg/src
ROS プログラムのログは $HOME/.ros/log
に保存されています。以下のコマンドで移動できます。
roscd log
rosls mypkg
rosed mypkg package.xml
roscp mypkg package.xml .
rosrun mypkg talker.py
前述の Master プロセスを起動します。既定では $ROS_MASTER_URI
でサービスを開始します。-p
オプションでポート番号を変更できます。
roscore
roscore -p 1234
一覧取得、すべての値を取得
rosparam list
rosparam get /
特定の値を設定、取得、削除
rosparam set /myparam 123
rosparam get /myparam
rosparam delete /myparam
すべての値をファイルに保存、ファイルから読み出し
rosparam dump params.yaml
rosparam load params.yaml
rosnode list -a
rosnode info /talker
rosnode ping /talker
rosnode kill /talker
rosnode machine
rosnode machine HOSTNAME
rostopic list
rostopic type /chatter
rostopic info /chatter
rostopic hz /chatter
rostopic echo /chatter
rostopic pub -r 1 /chatter2 std_msgs/String hello
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 list
rosmsg show std_msgs/String
rossrv list
rossrv show mypkg/AddTwoInts
こちらのチュートリアルに記載されている、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
こちらのチュートリアルに記載されている、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>
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