ROS2 CrystalのGazebo/rqtでTurtlebotを動かしてみる


# はじめに

[ROS Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ros) 17日目の記事です。

[ROS 2 Crystal Clemmys Released!](https://discourse.ros.org/t/ros-2-crystal-clemmys-released/7137)
ちょうど2日前の2018/12/15にROS2の新しいバージョンである「Crystal Clemmys」がリリースされました。Crystalは以下のような特徴があります( https://index.ros.org/doc/ros2/Release-Crystal-Clemmys/ より)。

* Actions in C / C++ ([server](https://github.com/ros2/examples/tree/af08e6f7ac50f7808dbe6165f1adfd8e6cd3a79c/rclcpp/minimal_action_server) / [client](https://github.com/ros2/examples/tree/af08e6f7ac50f7808dbe6165f1adfd8e6cd3a79c/rclcpp/minimal_action_client) examples.)
* [gazebo_ros_pkgs](http://gazebosim.org/tutorials?tut=ros2_overview)
* [image_transport](https://github.com/ros-perception/image_common/wiki/ROS2-Migration)
* [navigation2](https://github.com/ros-planning/navigation2/blob/master/README.md)
* [rosbag2](https://index.ros.org/r/rosbag2/github-ros2-rosbag2/#crystal)
* [rqt](https://index.ros.org/doc/ros2/RQt-Overview-Usage/)
* Improvement in memory management
* Introspection information about nodes
* Launch system improvements
  * Arguments
  * Nested launch files
  * Conditions
  * Pass params to Nodes
* Laid the groundwork for [file-based logging and /rosout publishing](https://github.com/ros2/rcl/pull/327)
* [Time and Duration API in Python](https://github.com/ros2/rclpy/issues/186)
* [Parameters work with Python nodes](https://github.com/ros2/rclpy/issues/202)


ROS2ではまだあまりロボットを動かせるデモが少ないので、今年のアドベントカレンダーは、このうち「Gazebo対応」「rqt対応」の2つの機能を使い、ROS2のGazebo上でTurtlebotをrqtを動かすねたをやってみたのでそれを紹介します。

# 結果

Ubuntu18.04の環境でROS1 bridgeを使うことなく、ROS2のみでTurtlebotがGazebo上で動かせるようになりました。動かせるといっても、とりあえず車輪が動くだけで、バンパ情報やデプスセンサの情報はまだ取れません（Pluginを自分で移植すればできます）。
どこがROS2?という感じですが・・・・

![](https://raw.githubusercontent.com/wiki/otamachan/ros2_turtlebot_gazebo_test/demo.gif)


# 動かし方

https://github.com/otamachan/ros2_turtlebot_gazebo_test#how-to

に記載しました。

2018/12/17現在リリースされている ``gazebo_ros_pkg`` に修正が必要がだっため、gazebo_ros_pkgに少し手をいれたものを使っています（本家にFB中）。

# やったこと

## 1. packageを作ります

ROS1とそれほど違いはありません。[チュートリアル](https://index.ros.org/doc/ros2/Colcon-Tutorial/)を参考にしながら作りました。

* [package.xml](https://github.com/otamachan/ros2_turtlebot_gazebo_test/blob/master/ros2_turtlebot_gazebo_test/package.xml)
* [CMakeLists.txt](https://github.com/otamachan/ros2_turtlebot_gazebo_test/blob/master/ros2_turtlebot_gazebo_test/CMakeLists.txt)

package.xmlの``<export>``タグに``<build_type>``の記載をしないと、パッケージが見つからなくなったりするようなので、忘れないようにします。

## 2. launchファイルを書きます

launchシステムは、ROS1から大きく変更されたところです。以下を参考に作成しました。

* https://github.com/ros2/launch/tree/master/ros2launch/examples
* https://github.com/ros2/launch/tree/master/launch_ros/examples
* https://github.com/ros2/launch/tree/master/launch/examples
* https://github.com/ros2/launch/blob/master/launch/doc/source/architecture.rst

ROS2のlaunchシステムはPythonで記述します。処理を``launch.action.Action``として登録することで色々な処理の実行が可能です（もちろんノードを起動することも）。ROS1では、サービスの起動を待ってそのサービスを呼び出す処理(``gazebo_ros``, ``nodelet``, ``ros_control`` 等)は、spawnスクリプトを書いて別プロセスとしてroslaunchから呼び出す必要がありますが、今回はこのあたりの処理を``launch.action.Action``として記述しlaunchの中から直接SpawnEntityサービスを呼び出してロボットモデルをGazeboにロードするようにしてみました。[empty_world.lauch.py](https://github.com/otamachan/ros2_turtlebot_gazebo_test/blob/master/ros2_turtlebot_gazebo_test/launch/empty_world.launch.py)
非同期な処理も書く事ができます。

## 3. URDFファイルを作ります

``turtlebot_description``, ``create_description`` パッケージが必要なため、まずこれらを[ament対応します](https://github.com/otamachan/ros2_turtlebot_gazebo_test/commit/bca7a62b413ace13455795fc772e6aab0060886e)。
ROS2には、xacroがない＆Gazeboのタグが少し変更されたため、ROS1のxacroで出力したURDFファイルを手で編集して用意しました。[create_circles_kinect.urdf](https://github.com/otamachan/ros2_turtlebot_gazebo_test/blob/master/turtlebot_description/urdf/create_circles_kinect.urdf)

## 4. rqt_robot_steeringをROS2に移植する

rqtのいくつかのPluginは既に移植されていましたが、``rqt_robot_steering``はまだ移植されていなかったため、移植済みの以下のパッケージを参考に、移植してみました。

* https://github.com/ros-visualization/rqt_py_console/tree/crystal-devel
* https://github.com/ros-visualization/rqt_publisher/tree/crystal-devel

基本的には、PubSubや、Parameter周りの[変更](https://github.com/otamachan/rqt_robot_steering/commit/7cad5356f0290ddd2015921b80e4c44eb07506a8)だけで動くようになるイメージです。

* https://github.com/otamachan/rqt_robot_steering/tree/ros2-port

# はまりポイント

* ROS2自体が絶賛開発中です。リリース直前まで不具合修正([#608](https://github.com/ros2/rclcpp/pull/608))されていたりと、何か問題があった場合に本家の情報は常に見ておかないといけないようです。
* rviz2で``robot_description``からロボットモデルの表示ができませんでした。既にQAには[ある](https://answers.ros.org/question/304645/ros2-robot-state-publisher-publishes-empty-robot_description/)ようです。今回はトピックではなく、URDFをファイル指定することで表示させています。
* PythonがSegmentation Faultで落ちます。ROS2からクライアントはPure Pythonではなく、cのラッパとして作成されています。少しおかしなことをすると、Python自体を巻き込んで落ちてしまい、デバッグが少し大変になったイメージです。

# 終わりに

Gazeboが対応されたとはいえ、まだ最小限のPluginしかポーティングされていない＆``ros_control``のポーティングがまだのため、本格的にロボット開発に使えるようになるにはもう少しかかりそうです。
逆にいうと、コントリビューションの余地はまだたくさんありそうです。

Enjoy happy ROS hacking!