ロボットシステム学2016第13回

Mon Jan 16 19:24:06 JST 2017 (modified: Fri Nov 29 17:15:49 JST 2019)
views: 601, keywords:

  このエントリーをはてなブックマークに追加 
   

ロボットシステム学

第13回

上田 隆一

2017年1月18日@千葉工業大学

本日の内容

  • ROS
    • ROSのインストールが終わった状態からスタート
    • 講義で扱うのはとりあえず触ってみる程度
      • 講義を通じて得たLinuxの知識があれば十分独学が可能

動作確認

  • $ roscore
    • ROSのバックにいるプログラムが立ち上がる
    • Ctrl+cで出る
$ roscore
   (略)
   started roslaunch server http://localhost:39310/
   ros_comm version 1.12.6

   SUMMARY
   ========

   PARAMETERS
   * /rosdistro: kinetic
   * /rosversion: 1.12.6

   NODES

   auto-starting new master
   process[master]: started with pid [1439]
   ROS_MASTER_URI=http://localhost:11311/

   setting /run_id to b749a100-d0dc-11e5-a506-b827eb17cb96
   process[rosout-1]: started with pid [1452]
   started core service [/rosout]

ROSのノード

  • プログラムのプロセス一つ一つが「ノード」と呼ばれる
  • ノードの例
    • cv_cameraとmjpeg_serverを立ち上げる(roscoreは立ち上げておく)
    • $ rosrun cv_camera cv_camera_node 
         $ rosrun mjpeg_server mjpeg_server 
    • ノードの確認
      $ rosnode list
         /cv_camera
         /mjpeg_server
         /rosout
    • ディレクトリのように管理されている

トピック・メッセージ

  • 今度はrostopic listと打ってみる
  • データをやり取りする口(トピック)が表示される
  • $ rostopic list
       /cv_camera/camera_info
       /cv_camera/image_raw
       /rosout
       /rosout_agg
  • トピックからデータを取り出す(先週もやりました)
  • $ rostopic echo /cv_camera/image_raw
    • このデータは「メッセージ」と呼ばれる

パブリッシャ・ サブスクライバ

  • 各ノードがトピックを通じてメッセージを融通することで全体として仕事を行う
  • mjpeg_serverは/cv_camera/image_rawからカメラ画像を取得して、ブラウザに画像を配信
  • データを出す側がパブリッシャ
  • データを受け取る側がサブスクライバ
  • この構造でサブスクライバ側の柔軟な組み換えが可能に
    • ブラウザに配信するノード、顔検出をするノード、mp4に変換するノード・・・

ROSプログラミングの準備

  • パブリッシャ、サブスクライバを作ってみましょう
  • その前に・・・
  • 「ワークスペース」(作業場)を作る
  • $ cd
       $ mkdir -p catkin_ws/src
       $ cd ~/catkin_ws/src
       $ catkin_init_workspace 
       Creating symlink "/home/ubuntu/catkin_ws/src/CMakeLists.txt" pointing to "/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake"
       $ ls
       CMakeLists.txt

  • .bashrcの末尾に以下を記述
source /opt/ros/kinetic/setup.bash #これは元からある
   source ~/catkin_ws/devel/setup.bash #ここから3行追加
   export ROS_MASTER_URI=http://localhost:11311
   export ROS_HOSTNAME=localhost
   
  • 環境のビルド
$ cd ~/catkin_ws
   $ catkin_make
   $ source ~/.bashrc
   
  • 確認
    • ROS_PACKAGE_PATHにcatkin_ws/srcがセットされているはず
$ echo $ROS_PACKAGE_PATH
   /home/ubuntu/catkin_ws/src:/opt/ros/kinetic/share

パッケージを作る

  • パッケージ: いくつかのノードを含んだ一単位
  • パッケージの生成
    • catkin_create_pkg <作るパッケージの名前> [使用するライブラリ...]
    • rospy: Pythonでノードを作るときに使用
    • パッケージを作ったら下にscriptsというディレクトリを作成
      • ここにノードとなるプログラムを置く
$ cd ~/catkin_ws/src
   $ catkin_create_pkg mypkg rospy
    Created file mypkg/package.xml
    Created file mypkg/CMakeLists.txt
    Created folder mypkg/src
    Successfully created files in /home/ubuntu/catkin_ws/src/mypkg. Please adjust the values in package.xml.
   $ cd mypkg/
   $ mkdir scripts
   $ cd scripts/

パブリッシャを作る

  • 次のようなプログラム(count.py)を書いてみましょう
  • ノード名が「count」、パブリッシャが「count_up」
  • rospy.Publisherを作って定期的にデータを投げる
    • count_upというトピックに、型はInt32で(バッファとなるキューのサイズは1)
#!/usr/bin/env python
   import rospy
   from std_msgs.msg import Int32

   if __name__ == '__main__': 
       rospy.init_node('count')
       pub = rospy.Publisher('count_up', Int32, queue_size=1)
       rate = rospy.Rate(10)
       n = 0
       while not rospy.is_shutdown():
           n += 1
           pub.publish(n)
           rate.sleep()

ノードの実行

$ rosrun mypkg count.py
  • rosnode listとrostopic listでノードとトピックの確認を
  • 次にrostopic echoでcount_upからデータを取り出してみましょう
$ rostopic echo /count_up 
   data: 1430
   ---
   data: 1431
   ---
   data: 1432
   ---
   data: 1433
   ...

サブスクライバを作る

  • 次のようなtwice.pyを作る
  • rospy.Subscriberを使う
    • count_upという名前のトピックを購読する
    • 型はInt32
    • データを受け取ったときにcbという関数で処理
      • コールバック関数
#!/usr/bin/env python
   import rospy
   from std_msgs.msg import Int32

   def cb(message):
       rospy.loginfo(message.data*2)

   if __name__ == '__main__': 
       rospy.init_node('twice')
       sub = rospy.Subscriber('count_up', Int32, cb) 
       rospy.spin()

twice.pyの実行

  • roscore、rosrun mypkg count.pyを事前に実行しておく
  • 二倍になった数字が端末上に表示される
    • 非同期なので欠ける可能性があることに注意
    • 途中で切ってまた立ち上げても再開
$ rosrun mypkg twice.py 
   [INFO] [1484659840.762425]: 4
   [INFO] [1484659840.862150]: 6
   [INFO] [1484659840.961791]: 8
   [INFO] [1484659841.062162]: 10
   ...
   

パブリッシャと サブスクライバの同居

  • twice.pyにパブリッシャを追加
#!/usr/bin/env python
   import rospy
   from std_msgs.msg import Int32

   n = 0

   def cb(message):
       global n
       n = message.data*2

   if __name__ == '__main__': 
       rospy.init_node('twice')
       sub = rospy.Subscriber('count_up', Int32, cb) 
       pub = rospy.Publisher('twice', Int32, queue_size=1) 
       rate = rospy.Rate(10)
       while not rospy.is_shutdown():
           pub.publish(n)
           rate.sleep()

実行

  • ノードを立ち上げてrostopic echo /twiceでトピックとしてデータを得る
$ rostopic echo /twice
   data: 1050
   ---
   data: 1052
   ---
   data: 1054
   ---
   data: 1056
   ...

 

その他

  • package.xml
    • パッケージの情報が書かれる
    • メンテナの名前、ライセンス、他のパッケージの依存関係等、配布に必要な情報
  • CMakeLists.txt
    • ビルド情報
    • 自分で型を作る、C++でノードを作る等、講義の内容より複雑なことをするときには手を入れる必要がある
  • 参考: 小倉: ROSではじめるロボットプログラミング, 工学社, 2015. 

課題

  • ROSで何か作る
  • あとは課題1と同じ提出方法で
    • GitHubにパッケージを置く
    • YouTube等に実行例
    • メールで連絡(件名: 課題2 <学籍番号> <氏名>)
  • 締め切り2/8
  • 満点20点+α
    • 体裁を整えて今日の内容を置いてくれたら15点。一捻りあれば満点に近づくということで