Turtlebot3の実機を使ったSLAMとNavigationをAWS RoboMaker上でやってみた

f:id:aptpod_tech-writer:20200702163024j:plain

研究開発グループの酒井 (@neko_suki)です。

今回は、「Turtlebot3の実機を使ったSLAMとNavigationをAWS RoboMaker上でやってみた」という取り組みについて紹介します。

SLAMは、Simultaneous Localization and Mappingの略で、ロボットによる自己位置推定と地図作成を同時に行うことです。Navigationは、指定した目的地までロボットを移動させることです。

まずは、動画をご覧ください。

www.youtube.com

動画ではAWS RoboMakerのシミュレーションジョブ上で、Turtlebot3のNavigationを行うためのノードを起動します。 そして、シミュレーション上のrvizで目的地を設定します。 そうすると、Turtlebot3が自律走行していることが確認できます。

今回の記事では、この動作をどのように実現したのかをお伝えします。

なお、本内容は、ROS Japan UG #37 オンラインROS勉強会 で発表した内容をベースに執筆しております。 資料は SlideShare にアップロードしてあります。

取り組みのモチベーション

過去に弊社製品のintdash Edge と AWS RoboMaker を用いた遠隔制御の取り組みについてご紹介しました。

参考

tech.aptpod.co.jp

tech.aptpod.co.jp

現在でも研究開発グループでは、AWS RoboMakerとの連携による弊社製品のユースケースの拡充を検討しています。

今回の取り組みではその一環として、SLAMやNavigationのような負荷の高い処理をAWS RoboMaker上で実行するための検証を行いました。

従来は、SLAMやNavigationなどの処理はローカルネットワーク上で、Turtlebot3の実機と接続したPC上で実行していました。

f:id:aptpod_tech-writer:20200630132822p:plain
従来の構成

今回の取り組みでは、このPC上で行っていた処理をAWS RoboMaker上で行えるようにします。

弊社製品のintdash Edge は ROSトピックをインターネット経由で流すことが出来ます。なので、SLAMやNavigationに必要なROSトピックをTurtlebot3の実機からAWS RoboMaker上に流したり、逆にAWS RoboMaker上で発行されたNavigation用のROSトピックをTurtlebot3の実機に流すことも可能になります。

AWS RoboMakerのシミュレーションジョブではrvizをサポートしています。AWS RoboMakerのシミュレーションジョブは、Gazeboを用いた物理シミュレーションやROS bagの再生などのシミュレーションに用いるものですが、今回は(ハック的に)シミュレーションジョブを活用することで、rvizを用いたSLAMの可視化やrvizを用いたNavigationを実現しています。

最終的には以下の構成で検証を行いました。

f:id:aptpod_tech-writer:20200630132836p:plain
最終的な構成

技術的に検討をしたポイント

今回の取り組みを実現するために、技術的に以下の2点について検証をしました。

①インターネット経由でSLAM/Navigationを動かすために必要なROSトピックを調べる

②AWS RoboMaker上でSLAM/Navigationを動かす。

それぞれについて説明します。

①インターネット経由でSLAM/Navigationを動かすために必要なROSトピックを調べる

まず、SLAMやNavigationを動かすためにどのようなROSトピックが使われているかを確認します。

SLAM に必要なROSトピックの確認

SLAMはturtlebot3_manipulation_slam を使用しました。デフォルトでは、turtelbot3_slam_gmapping が起動されます。

以下のコマンドで起動します。

TURTLEBOT3_MODEL=waffle_pi roslaunch turtlebot3_manipulation_slam slam.launch

起動に成功すると下のような画面が表示されます。

f:id:aptpod_tech-writer:20200630132858p:plain
SLAM

turtlebot3_slam_gmapping がpublish/subscribeしているROSトピックの一覧

rosnode info で、turtlebot3_slam_gmapping が使用している=subscribeしているROSトピックを調べます。

$ rosnode info /turtlebot3_slam_gmapping
--------------------------------------------------------------------------------
Node [/turtlebot3_slam_gmapping]
Publications:                                                
 * /map [nav_msgs/OccupancyGrid]
 * /map_metadata [nav_msgs/MapMetaData]
 * /rosout [rosgraph_msgs/Log]
 * /tf [tf2_msgs/TFMessage]                         
 * /turtlebot3_slam_gmapping/entropy [std_msgs/Float64]
                       
Subscriptions:
 * /scan [sensor_msgs/LaserScan]                          
 * /tf [tf2_msgs/TFMessage]                            
 * /tf_static [tf2_msgs/TFMessage]
(以下略)

ここから、turtlebot3_slam_gmapping を動かすためには、実機側で発行されている/scan/tf/tf_static が必要ということがわかります。 ただし、試してみた限りでは/tf_static は必要ありませんでした。

Navigationには、turtlebot3_manipulation_navigation を使用しました。

以下のコマンドで起動します。

$ TURTLEBOT3_MODEL=waffle_pi roslaunch turtlebot3_manipulation_navigation navigation.launch map_file:=/tmp/my_map.yaml open_rviz:=false    

起動に成功すると下のような画面が表示されます。

f:id:aptpod_tech-writer:20200630132915p:plain
Navigation

ここでは、amclmove_base という2つのノードについて調べました。

$ rosnode info amcl
--------------------------------------------------------------------------------
Node [/amcl]           
Publications:
 * /amcl_pose [geometry_msgs/PoseWithCovarianceStamped]
 * /diagnostics [diagnostic_msgs/DiagnosticArray]
 * /particlecloud [geometry_msgs/PoseArray]
 * /rosout [rosgraph_msgs/Log]
 * /tf [tf2_msgs/TFMessage]                         
                                                       
Subscriptions:         
 * /initialpose [unknown type]
 * /scan [sensor_msgs/LaserScan]                             
 * /tf [tf2_msgs/TFMessage]                            
 * /tf_static [tf2_msgs/TFMessage]
(以下略)                                
$ rosnode info move_base
--------------------------------------------------------------------------------
Node [/move_base]
Publications: 
 * /cmd_vel [geometry_msgs/Twist]
 * /move_base/DWAPlannerROS/cost_cloud [sensor_msgs/PointCloud2]
 * /move_base/DWAPlannerROS/global_plan [nav_msgs/Path]
 * /move_base/DWAPlannerROS/local_plan [nav_msgs/Path]
 * /move_base/DWAPlannerROS/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/DWAPlannerROS/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/DWAPlannerROS/trajectory_cloud [sensor_msgs/PointCloud2]
 * /move_base/NavfnROS/plan [nav_msgs/Path]
 * /move_base/current_goal [geometry_msgs/PoseStamped]
 * /move_base/feedback [move_base_msgs/MoveBaseActionFeedback]
 * /move_base/global_costmap/costmap [nav_msgs/OccupancyGrid]
 * /move_base/global_costmap/costmap_updates [map_msgs/OccupancyGridUpdate]
 * /move_base/global_costmap/footprint [geometry_msgs/PolygonStamped]
 * /move_base/global_costmap/inflation_layer/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/global_costmap/inflation_layer/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/global_costmap/obstacle_layer/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/global_costmap/obstacle_layer/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/global_costmap/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/global_costmap/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/global_costmap/static_layer/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/global_costmap/static_layer/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/goal [move_base_msgs/MoveBaseActionGoal]
 * /move_base/local_costmap/costmap [nav_msgs/OccupancyGrid]
 * /move_base/local_costmap/costmap_updates [map_msgs/OccupancyGridUpdate]
 * /move_base/local_costmap/footprint [geometry_msgs/PolygonStamped]
 * /move_base/local_costmap/inflation_layer/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/local_costmap/inflation_layer/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/local_costmap/obstacle_layer/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/local_costmap/obstacle_layer/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/local_costmap/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/local_costmap/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/parameter_descriptions [dynamic_reconfigure/ConfigDescription]
 * /move_base/parameter_updates [dynamic_reconfigure/Config]
 * /move_base/result [move_base_msgs/MoveBaseActionResult]
 * /move_base/status [actionlib_msgs/GoalStatusArray]
 * /rosout [rosgraph_msgs/Log]

Subscriptions: 
 * /clock [rosgraph_msgs/Clock]
 * /map [nav_msgs/OccupancyGrid]
 * /move_base/cancel [unknown type]
 * /move_base/global_costmap/footprint [geometry_msgs/PolygonStamped]
 * /move_base/goal [move_base_msgs/MoveBaseActionGoal]
 * /move_base/local_costmap/footprint [geometry_msgs/PolygonStamped]
 * /move_base_simple/goal [geometry_msgs/PoseStamped]
 * /odom [nav_msgs/Odometry]
 * /scan [sensor_msgs/LaserScan]
 * /tf [tf2_msgs/TFMessage]
 * /tf_static [tf2_msgs/TFMessage]
 (以下略)

これらの情報を精査した結果、SLAMで使用していたROSトピックに加えて、/odom が必要ということがわかりました。 また、インターネット経由でTurtlebot3の実機を制御するためには、move_base ノードがpublishした/cmd_vel を実機に届ける必要があることがわかります。

これらの情報から、AWS RoboMakerから弊社intdashサーバー経由でSLAM/Navigationを行うには、Turtlebot3実機とシミュレーションジョブで以下のように設定すればよいことがわかりました。

  • Turtlebot3は、/scan/tf/odomをintdashサーバーにアップロードし、 /cmd_vel をダウンロードする。
  • AWS RoboMaker側のシミュレーションジョブは、/scan/tf/odomをintdashサーバーからダウンロードし、/cmd_velをアップロードする。
帯域の計測

インターネットを経由する場合、どのくらいの帯域が必要になるか気になると思います。

弊社の製品には流れているデータの流量を計測できるものがあるので、それを用いてROSトピックの帯域を計測しました。

結果は以下のようになります。

/scan: 約40Kbps

f:id:aptpod_tech-writer:20200630133141p:plain
/scan

/tf: 約74Kbps

f:id:aptpod_tech-writer:20200630133154p:plain
/tf

/odom: 約23Kbps

f:id:aptpod_tech-writer:20200630133206p:plain
/odom

/cmd_vel : 約1kbps

f:id:aptpod_tech-writer:20200630133218p:plain
/cmd_vel

ここから、Turtlebot3の実機からROSトピックを流すために必要な帯域は、約140kbps、実機を制御するのに必要なROSトピックを流すために必要な帯域は約1kbps であることがわかりました。

上り・下りの帯域としては、現実的に利用可能な値ではないかと思います。

ただし、これらの帯域の値はTurtlebot3を使用した時の値であり、必要となる帯域は実際に使用するロボットの設定・構成に依存するので注意が必要です。

②AWS RoboMaker上でSLAM/Navigationを動かす。

AWS RoboMakerでは、Gazeboを使ったシミュレーションだけではなく、ROS bag 再生によるシミュレーションを行うことが可能です。

今回の取り組みでは実機を使うので、Gazeboは不要です。ROS bag再生用のシミュレーションアプリケーションを作成し、利用します。

具体的なやり方について説明します。

ROS bag再生に対応したシミュレーションアプリケーションを作る

AWS RoboMakerのコンソールから、「シミュレーションアプリケーション」→「シミュレーションアプリケーションの作成」を選択します。

f:id:aptpod_tech-writer:20200630133533p:plain

シミュレーションソフトウェアスイートは「RosbagPlay」を選択します。このように設定することで、ROS bag再生用のシミュレーションアプリケーションを作ることが出来ます。

f:id:aptpod_tech-writer:20200630133546p:plain

後ほどシミュレーションジョブを作成するときに使うので、アプリケーションに名前を付けます。ここでは「aptpod」という名前を付けました。

ROS bag再生用のシミュレーションジョブの作成

AWS RoboMakerのコンソールから、「シミュレーションジョブ」→「シミュレーションジョブの作成」を選択します。

f:id:aptpod_tech-writer:20200630154310p:plain

今回は、ステップ2の「ロボットアプリケーションの指定」では「なし」を選択します。

f:id:aptpod_tech-writer:20200630133606p:plain

ステップ3の「シミュレーションアプリケーションの指定」では、まず先ほど作成した既存のアプリケーションを選びます。

f:id:aptpod_tech-writer:20200630133622p:plain

次に「データソースの設定」を行います。

コンソールから設定するときは、シミュレーションジョブを起動するために少なくとも一つのROS bagファイルを設定する必要があります。 ROS bagファイルはS3上にあるものを指定します。

AWS RoboMakerではlaunchファイルにROS bagを再生する設定を書くか、ターミナル上でROS bagファイルを再生しない限りは再生されないため、ここで設定したROS bagファイルは実際には再生されません。

f:id:aptpod_tech-writer:20200630154532p:plain

これらの設定を終えたらシミュレーションジョブの作成を完了し、シミュレーションジョブが起動するのを待ちます。

シミュレーションジョブが起動すると、以下のような画面になります。

ここで、Terminalを選択するとターミナルが開かれます。あとは冒頭の動画で紹介したようにSLAMやNavigationなどのROSノードを起動するとrvizが使えるようになります。

f:id:aptpod_tech-writer:20200630161733p:plain

まとめ

今回は「Turtlebot3の実機を使ったSLAMとNavigationをAWS RoboMaker上でやってみた」 について紹介しました。

研究開発グループではROSやAWS RoboMakerに関連した取り組みに限らず、プロトコルや機械学習に関連したテーマなど、様々な技術テーマの調査・検証を進めています。 今後も継続的に調査・検証の結果を記事として投稿できれば良いと思います。

最後までご覧いただきありがとうございました。