Raspberry Pi 4 を使ったROS入門　第2回　ROSの概要とチュートリアル　turtlesm

# はじめに
この記事は研究室の学生の教育用に作成してゆきます．
現在はROS2がメジャーとなってきておりますが，まずは自習が出来るよう文献が豊富なROS1でROSの扱いに慣れてみます．
ROSは既に多くの文献があり，それだけでも自習可能ですが解説されているバージョンや環境が違い，初心者には躓きやすい内容だと思ったため，改めてまとめてみます．

前回はこちら
[Raspberry Pi 4 を使ったROS入門　第1.5回　環境構築②　VNCとVSCodeの導入](https://qiita.com/H-Ando-robo/items/bf0b0410a5f9da07514c)
次回はこちら
[Raspberry Pi 4 を使ったROS入門　第3回　Hello world](https://qiita.com/H-Ando-robo/items/b069818816a76f80b86c)

# 動作環境
Raspberry Piを使用します．(用意できるならUbuntu入りのPCが◎)
ROSはUbuntu上で動くソフトなのですが，設定の違いによってトラブルが起きやすいので，クリーンインストールしてから始めることをお勧めします．
ROSのバージョンはUbuntuのバージョンとリンクしてます．

本記事で使用する機器とバージョン
| 使用機器 | Ubuntuバージョン | ROSバージョン |
|:------------:|:------------:|:------------:|
|Raspberry Pi 4 Model B / 8GB|20.04|Noetic Ninjemys|

※RAMが2GB，4GBだとビルドが途中で落ちることが多々ありました．
出来れば8GBが良いかもしれません．

# 1.ROSとは
　ROSはWindowsやLinuxのようなOSとは違い，そのOS上で動作するミドルウェアやソフトウェアフレームワークの一種です．ROSの情報がまとめられた「ROS Wiki」では，ROSのことをメタオペレーティングシステムと呼んでいます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/35907150-8b86-8ff2-f86f-e09fb5f20395.png)

ROSとは何かという問いに，ROSプロジェクトに参画するBrian Gerkey氏は、次のように述べています．
ROS＝Plumbing（通信）＋Tools（ツール群）＋Capabilities（機能群）＋Ecosystem（エコシステム）

#### ・ROS通信ライブラリ
　複数のプログラムを結合させる通信ライブラリがROSの中心です．ROSの実行プログラムはNodeという単位で扱い，Publisher/Subscriberモデルで通信します．またServiceという同期的な通信も用意されています．
　下の図のように，情報を送信するNodeはTopicにデータを書き込み(Publish)，受信する側はTopicを購読(Subscribe)します．(送信側は常にメモに書置きし，受信側はそのメモを拾いに行くイメージです)　これにより，通信相手が誰なのか特に意識せず通信することが出来ます．この際，Topicは型が決まっており，相手のIPアドレスやポート番号などの情報なしに通信を行うことが出来ます．(メモ書きのルールだけ決めておけば送信者が後から入れ替わっても通信できるので便利です)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/1aedebe3-1b84-b52b-4d72-b34e083b40b9.png)

#### ・ツールライブラリ群
 ROSには非常に強力なツールやライブラリ群が付属しています．ロボット製作の上ではデバッグや可視化が重要ですが，これらを簡単に導入できます．またロボットを制御する上で中核となる移動・マニピュレーション・知覚といった機能をロボットに実装する多様なライブラリが用意されており，これらの機能はオープンソースなので世界中の人々が使い改良していくうちにどんどん良くなっていきます．

#### ・ROSエコシステム
 ROSは現在，ロボットミドルウェアのデファクトスタンダードになっていますが，この一因として第3者のライブラリの配布，導入が容易である事が挙げられます．
　例えば誰かが作ったライブラリが「apt-get」といコマンドで簡単にインストールできます．(Pythonのpinの様なもの)　これにより誰でも簡単に登録して依存関係を満たしながらインストールすることで高度なロボット設計を可能としています．
　ROSは第3者のライブラリ配布に関してもかなりコストをかけており，これによって形成されるエコシステム(依存関係や協調関係)こそがROSの強みであると言えます．

# 2. ROSの用語説明
#### ・Node
ROSでは1つのプロセスをNodeと呼びます．Nodeは ROS クライアント ライブラリを使用して他のNodeとやりとりします．NodeはTopicへ配信したり購読したりできます．NodeはServiceを提供したり，使用したりすることができます．
#### ・Message
　ROSで通信する為には，あらかじめ決められた型が必要です．C/C++で言うと構造体やクラスのようなものです．Messageは型を持った通信で受け渡しされるデータの事です．
#### ・Master
　ROSのNode同士が通信するための名前の解決をする特別なプロセスです．roscoreというコマンドで起動します．
#### ・Topic
　ROSのNodeが送受信するデータです．ROSはPublisher Subscriberモデルで通信します．送信側のNodeがTopicにデータをPublishします．受信側のNodeはTopicにSubscribeする事でデータを受け取ります．
#### ・Service
　Topicは相手を仮定せずにデータの受け渡しをする非同期通信でした．一方で相手に何かしてもらう際にその成否を呼び出し側で知りたい時があります．そのようなときにServiceを使う事が出来ます．
#### ・Parameter
　ROSを使うと同じプログラムで様々なロボットを制御できるようになります．大きさや速度などのパラメータはロボットによって違いますので，プログラム実行時にファイルやネットワークからパラメータを読み出すことが出来ます．

# 3. チュートリアル
ROSにはデフォルトでturtlesmという簡単なシミュレータが付属しています．こちらを使用して，ROSの基本的な動きを体験してみましょう．

#### ・roscoreの起動(Masterの起動)
ROSのNodeを実行する際には必ず1つ立ち上げる必要があります．ターミナルを立ち上げ，下記のコマンドを実行してください．
```
roscore
```
続いて，ターミナルをもう一つ立ち上げてturtlesmを起動します．

*ターミナルを新たに立ち上げる際にはアイコンを中クリックすると起動できます．
**ターミナルではコマンド入力を行う際にある程度入力を行いTabキーを押すと予測入力が出来ますので活用してください．

```
rosrun turtlesim turtlesim_node
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/34f61413-538d-64b7-3d79-ad4f5d115fdc.png)

続いてキーボード入力を使ってこの亀を動かしてみます．以下のコマンドを新たなターミナルで実行し，プログラムを実行します．

```
rosrun turtlesim turtle_teleop_key
```
無事起動できた場合，亀のウィンドウ上でなく上記コマンドを実行したウィンドウにカーソルを合わせて矢印キー(↑↓←→)で入力すると亀が移動します．

#### ・rqt_graphでの可視化
今回立ち上げたturtlesimとturtle_teleop_keyはROSのTopicで通信しています．turtle_teleop_keyがキーボード入力を速度に変換してPublishし，turtlesimが速度をsubscribeしています．rqt_graphというソフトを起動するとこの関係を図示することが出来ます．新たなターミナルで下記コマンドを実行してみてください．

```
rqt_graph
```
左のteleop_turtle Nodeとturtlesim Nodeが/turtle1/cmd_velというtopicによって結ばれていることが分かります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/e58a4b6b-6920-7a51-6861-aa0771fc3751.png)

#### ・rostopicの使用
　次にrostopicというコマンドを使って/turtle1/cmd_velのtopicの中身を見てみます．
新しいターミナルを立ち上げて，下記コマンドを実行してください．

```
rostopic echo /turtle1/cmd_vel
```
このままでは何も起きませんが，turtle_teleop_keyを起動したターミナル内で矢印キーを押して亀を動かしてみてください．以下の通り，表示されたはずです．

```
linear: 
  x: 2.0
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 0.0
```
このデータが亀に与えられた速度を表しています．Linear:のx:部分が前進速度を表しており，angularが回転速度を表しています．

次にrqt_graph内の更新ボタン<img width="30" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/bc7a73f4-3686-1460-c429-972d8dafbc8d.png">を押してみてください．このrostopic自体も1つのNodeで，Topicを介して通信していることが分かります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/5079264e-5144-ab53-cbd5-ab33f2e030bb.png)

#### ・rostopicでTopicに直接値を書き込んでみる(Publish)
まずはTopicの型を調べる必要が有りますが，この際もrostopicを使用します．rostopicを使う際に使用したターミナル上で，Ctrl＋Cを押し，プログラムを終了させて以下のコマンドを入力してください．
```
rostopic type /turtle1/cmd_vel
```
すると以下のように表示されます
```
geometry_msgs/Twist
```
この"geometry_msgs/Twist"が"turtle1/cmd_vel"のTopicの型になります．
一度turtlesm_nodeを立ち上げ直してください．(Ctrl＋Cで終了し，上矢印キーを押すと，過去に入力したコマンドを再入力できます)
空いているターミナルで以下のコマンドを入力します．
```
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -- '[1,0,0]' '[0,0,1.5]'
```
うまくコマンドを入力できると亀が少し動きます．
1.0が前進速度(m/s)を示し，1.5が左方向の回転速度(rad/s)を表しています．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/e1ca004a-80a9-3abb-cec2-7bddf8c46890.png)

次は先ほどのコマンドを少し変えて以下のコマンドを入力してみてください．
```
rostopic pub -r 1 /turtle1/cmd_vel geometry_msgs/Twist -- '[1,0,0]' '[0,0,1.5]'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/89b8e473-8919-086a-f66e-91206106064e.png)
今度は亀が回転し続けたと思います．
-r 1　というオプションにより亀が回転し続けます．これは1Hzつまり1秒に1回繰り返しデータを送信するという意味になります．

rostopicの便利な機能としてlistがあります．以下の通りコマンドを実行してみてください．
```
rostopic list
```

現在登録されているtopicとが表示されます．このlistは実行後に自動終了するのでCtrl+Cは不要です．

```
/rosout
/rosout_agg
/statistics
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
```

#### ・rosserviceを使ってServiceを理解する
rostopic list と同じように，以下のコマンドで現在利用可能なServiceが一覧で見れます．
```
rosservice list
```
以下のように表示されます．
```
/clear
/kill
/reset
/rosout/get_loggers
/rosout/set_logger_level
/rqt_gui_py_node_45689/get_loggers
/rqt_gui_py_node_45689/set_logger_level
/spawn
/teleop_turtle/get_loggers
/teleop_turtle/set_logger_level
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/get_loggers
/turtlesim/set_logger_level
```
では以下のコマンドでどんな引数と戻り値を受け取るのか調べてみます．
```
rosservice type /spawn | rossrv show
```
以下のように表示されます．
```
float32 x
float32 y
float32 theta
string name
---
string name
```
---の上が関数で言うところの引数(入力)で下が戻り値(出力)となっています．
spawn　は　x,y,thetaの座標にnameという名前の亀を生成するServiceです．
rosservice call でserviceを読みだすことが出来ます．
```
rosservice call /spawn 2 3 1 ""
```
以下の文字が表示されます．今回は4つ目の引数を空欄にしましたので自動でturtle2という名前が付けられました．
```
name: "turtle2"
```
x=2，Y＝3，theta1の位置に亀が出てきました．Serviceは実行結果を返してもらうまで待つのが特徴です．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/ddd52284-0b9b-21a1-8de9-b8be0f4a273b.png)

#### ・rosparamを使ったParameterの理解
 ROSの重要な機能の一つにParameterがあります．これは同じプログラムでも様々なロボットに適応する為の細かい制御パラメータを変更するための機能です．下記コマンドを実行してください．
```
rosparam list
```
下記のように現在セットされているParameterの一覧が取得できます．
```
/rosdistro
/roslaunch/uris/host_hando_ubuntu__37203
/rosversion
/run_id
/turtlesim/background_b
/turtlesim/background_g
/turtlesim/background_r
```
下記コマンドを実行してみてください．

```
rosparam get /turtlesim/background_r
```
以下の様な値が返ってきたと思います．
```
69
```
この値は背景色のうち赤の成分が表示されています．下記の通り入力すると赤の成分を変更できます．
```
rosparam set /turtlesim/background_r 200
```
もう一度下記コマンドで確認してみましょう．
```
rosparam get /turtlesim/background_r
200
```
背景色が変わるはずですが，まだ変化がないはずです．
Parameterは起動時に1度読み込まれるだけなので，Turtlesimを再起動します．
```
rosservice call /clear
```
下図の通り，背景がピンク色に変われば成功です．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438020/6ef85ead-3448-604b-e241-2da7d43288f8.png)

# おわりに
今回はROSに付属しているturtlesmというプログラムを使い，Topic，Service，ParameterというROSのすべての通信手段とコマンドラインツールについて触れてみました．現時点では完全に理解できていなくても大丈夫です．触っていくうちに慣れていくと思います．

参考　ROS公式 チュートリアル
http://wiki.ros.org/ja/ROS/Tutorials

# 更新履歴
2022年11月7日　公開