React Studio + ROSでちょっとカッコいいフロントエンドアプリを作る

# ROS向けのフロントエンドアプリのプロトタイプ制作

ROSでちょっとパラメータの調整とか試したりするのであれば、rqtとかを使って変更したり、そもそも操作するアプリを専用でQTを使用して作ったりしている人も多いと思います。（かくいう私もQTでアプリを作っていました）ただ、最近のWebサイトで見られるようなちょっとカッコイイ表現とかするには、いろいろ苦労したり、あまりに硬派なGUIだとウケが悪いという悩みを持っている人は多いと思います。
最近ちょっとカッコいいサイトとかフロントエンドアプリとかが出ていますが、ReactとかのWebベースで制作されたアプリが多いです。Webをベースにしたフロントエンドはかなり進んでいて、Native動作できるアプリ開発も最近はWebベースで作成するものが増えてきている印象です。おそらくAndroidとかiPhoneとかのクロスプラットフォームでの対応が容易であるというのもあるかもしれません。ということで、今回はReactを使用したWebベースのアプリを作って、ROSと通信させることで、ちょっとカッコいいWebアプリを作成しようという話です。

## プロトタイプ制作ソフト

Nativeアプリの開発環境であれば、古くはMFCやXCode+Objective-Cといった環境で、GUIをデザインする環境がありました。Webの世界はどうなっているのかと調べたところ、大体はデザイナーがデザインするものとあってか、デザインツールとしてFigmaとかAdobe XDなどが使われているようです。今回は実際に動くことや、機能を拡張したい、あと最も重要なところでReactのコードが出力できるということを前提に調べた結果、以下の２個に候補を絞りました。

 - BuilderX
 - React Studio

ただ、BuilderXはWebベースで動作して、機能を拡張するなどはどうやら難しそうであったため、今回はReact Studioを用いて、Webアプリを作成していきたいと思います。

## React Studioの基本

まず最初にとても重要なことを書いておきます。

_このソフトはMac専用ソフトです！_

WindowsやUbuntuのPCしか持っていない諸君は回れ右でお願いします。

_価格はなんと無料です！_

素晴らしい！課金だけしてろくに使えないとなりがちなロボット開発勢にはうれしいところです。

_素晴らしいツールに見えるのに、更新されていなさそうで、しかもなぜか情報が少なすぎる！_

それを乗り切ってこそロボット開発者というものです。

とはいえ、全く情報がないと何ができるのかもよくわからないとなりますが、以下のYouTubeとMediumのサイトに記事がいろいろ出ているので、参考にしてください。

https://youtu.be/GBBLj2gn6J8

https://reactstudio.medium.com

## とにもかくにもインストール

Mac用なので、特にいろいろ書く必要はないですね。Homepageからダウンロードしてきて解凍するだけです。しかも、なんとこのツールは内部にnode.jsを取り込んでいたりするので、基本的に他に何も追加でインストールする必要がないです。これは非常に楽。

## ということで起動します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/de3bb26a-3b19-d646-7c62-e05ca2079e2f.png)

せっかくなので、モバイル用のアプリを作成してみましょう。
Create new projectをクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/9abae176-70b9-aa21-31fa-13f6e15a2edc.png)

なんか上のバーの部分にExportやらモバイル用の表示とかまであって、期待が持てますね！

## とりあえずGUIをデザインしてみる

自分を含めセンスがないロボット開発者の方が多いと思いますが（おい）、とりあえずGUIを作っていきます。
まずは、ScreenのStartのブロックをダブルクリックしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/204b77ba-8239-456c-389f-d2f8871be4ca.png)

もうボタンを配置してくれと言わんばかりのWindowが出てきましたね。では、そのままテキストボックスとボタンを一個ずつ配置してみましょう。

続いて、ボタンをクリックした際の動作を割り当てていきます。
Interactの項目からTapをクリックして、クリックの動作にScriptを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d86b91a0-e28a-3c2e-3850-38d4bd13c17c.png)

Edit Scriptをクリックすると、ボタンをクリックした時の動作を書くことができます。

## ROSを使えるようにする

GUIの作り方はYouTubeのチュートリアルを参照していただければと思いますので、続いてはROSを使えるようにしていきたいと思います。

とはいえ、ROSをWebアプリで使うにはどうするかとなるのですが、roslibjsというROSの機能をJavaScriptで扱えるようにするライブラリを使用していきます。ただ、このroslibjsは直接rosmasterと通信することはできないので、ROSが入ったUbuntu上で、rosbridge_websocketを使用する必要があるため、HostとなるUbuntuマシンに以下のパッケージをインストールしておきます。

```console 
sudo apt install ros-noetic-rosbridge-server
```

続いて、React Studio上でroslibjsを使えるようにします。React Studioは先ほど内部にnode.jsが内包していると書きましたが、自由にプラグインを自作して追加することで、npmのパッケージを導入することができます。ここでは、プラグインを作成してroslibjsを使えるようにしていきます。

メニューバーのPluginsからCreate New Pluginを選択します。
名前は適当にROSとして、TypeはWrapping NPM Packageを選んでおきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/dfdbeddd-4362-3103-f1bd-6c5d133c4394.png)


続いての画面で、npmでインストールするパッケージを指定します。npmでインストールする場合は、roslibという名前で最新バージョンは1.3.0なので、そのように入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/4865585a-11a4-3220-1366-4a0067f16910.png)

PreviewイメージとIconは好みでROSのアイコンとかを設定すると分かりやすいですが、、、なぜかドラッグ&ドロップできないので、手動で後でPNGファイルを書き換えるなりします（各自やってください）。

続いて、このままではプラグインとしてroslibを使用することはできません。ですので、使えるように書き換えていきます。まず、PluginsのEdit PluginでROSプラグインを編集してきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/bb59af3b-e810-1c9d-c8ee-6caf6486931c.png)

Plugin EditorのMain.jsを編集していきます。
まずdefaultNameForNewInstanceの表記がrOSになっていてカッコ悪いのでROSにしておきましょう。（いらん

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/8e0bfa1b-354e-00e9-d998-45b2caa0ec95.png)


続いて104行目の以下の箇所を変更します。これはroslibはJSXのコードに追加する必要がないですので、消している処理となります。

```console 
this.getReactWebJSXCode = function(exporter) {
  //return `<Roslib />`;
  return ``;
}
```

これでとりあえずroslibをReact Studioを使えるようになりました！

## ROSLIBをReact Studioで使う。

無事にプラグインが作成できていると、コンポーネントのリストにROSが現れます。
これをドラッグ&ドロップをして配置します。実際にはこのコンポーネントは見えないので、どこにおいても問題ないです。とりあえずこれで正しく動作するかまずは確認してきましょう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/5e5acdd7-11f8-5a2c-3cb1-af0d69a24e28.png)

続いて、この状態でエラーが出ないかどうか確認するためにプロジェクトを保存して、右上のOpen in Web Browserをクリックして、今回作成したUIがエラーでないかを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/43660d3a-5d49-ab8e-a07c-fd1c755fc0f0.png)

このようにエラーせずにWindowが出てこればOKです。

### ROS Publisherを作る

続いて、ROSのPublisherを作っていきます。先ほどのボタンにPublishの機能を持たせますが、まずはこのプロジェクトでROSのサーバー側と接続するなどのコードを記載してきます。
まずは、上のScript Editorをクリックして、Editor画面を出します。

StartのTempleteの箇所の最後に以下の行を追加していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/3ded0838-9ceb-3352-7462-2a9e4fa8442e.png)

``` 
var ROSLIB = require('roslib');

var ros = new ROSLIB.Ros({
  url : 'ws://10.211.55.15:9090'
});

ros.on('connection', function() {
  alert("Connected");
  console.log("Connected.");
});

ros.on('error', function(error) {
  alert("ERROR");
});

ros.on('close', function() {
  alert("CLOSED Connection");
});
```

これはROS Bridgeに接続するコードとなっています。alertとすることで、ポップアップで接続動作ができたかを表示することができます。

ここでサーバーとなるPCでROS Brdigeを立ち上げておきます。

```console
roslaunch rosbridge_server rosbridge_websocket.launch
```

これで準備は完了です。また右上のOpen in Web Browserをクリックして動作を確認してきましょう。

正しく接続できると以下のようにConnected.と表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/6fa35225-0185-4452-77ce-66bcf4ea3fb9.png)

これで正しくrosbridge_serverと通信できました。続いて先ほど配置したPUBLISHボタンを押すことで、Topicが送信されるようにしてみます。

まず先ほどPUBLISHボタンのInteractの箇所でボタンをTapするとScriptを実行するようにしましたが、そこのEdit ScriptからScriptを編集していきます。
以下の通り、ボタンをTapした時にPublishするようにコードを記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d8692d5a-a381-d21e-26aa-18e974cd4452.png)


```
var publisher = new ROSLIB.Topic({
  ros : ros,
  name : '/webapp/topic',
  messageType : 'std_msgs/String'
});
​
var msg = new ROSLIB.Message({
  data : 'Hello ROS!'
});
publisher.publish(msg);
```

ここまでできましたら、Open in Web Browserをクリックして、動作確認します。
Ubuntu側で

```script
rostopic echo /webapp/topic
```

と実行して、Web BrowserでボタンをクリックするとTopicが出力されていることがわかります。
これでボタンをクリックするとTopicを出すことができました！これを応用すれば、いろいろこのWebアプリ経由でTopicを出力することができると思います。

### ROS Subscriberを作る

続いて、ROSの他のノードが出力するTopicをSubscribeして表示するようにしていきます。
まず初めに、JavaScriptのコード内で、このScreenのアイテムの内容を更新できるように、Screnにアクセスできるようにしていきます。とりあえずプロトタイプ用にできるやり方を書いていますが、筆者はReact初心者なので、これで良いかはよくわかっていません。あんまり良い方法ではないかもしれませんが、こちらで試していきたいと思います。

まず、Script Editorで、componentDidMountのが呼ばれる際に、以下の行を追加することで、JavaScript側から、Textなどにアクセスできるようにします。

```
  componentDidMount() {
    {{CLASS_NAME}}.instance = this;
{{COMPONENT_DID_MOUNT_CODE}}
  }
```

続いて、そのままScriptの一番下に、ROS TopicをSubscribeするコードを記載していきます。

まず配置したTextのLocalize. Keyをチェックしておきます。ここではstart_text_860211となっていますので、その値をSubscribeしたStringで上書きすることで表示したいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/e510e6dc-6e8e-d0bd-bd11-df2f35f24ec3.png)

StartScreenのMethodsの下にSubscribeしたデータに表示を更新するUpdateText関数を追加します。

```
{{METHODS}}

  updateText(msg) {
    this.context.locStrings.start_text_860211 = msg;
    this.setState({});
  }
```

そして最終行に以下のコードを追加してSubscribeして表示を更新するようにします。

```
const subscriber = new ROSLIB.Topic({
  ros : ros,
  name : '/server/topic',
  messageType : 'std_msgs/String'
});
subscriber.subscribe(msg => {
  var receive_string = msg.data;
  StartScreen.instance.updateText(receive_string);
});
```

ここまでできましたら、保存してOpen in Web Browserをクリックして実行します。

そして、Ubuntu側で以下のコマンドを実行して、トピックを発行します。

```
rostopic pub /server/topic std_msgs/String "data: 'aaa'" -r 1
```

すると以下の通り、TextBoxにSubscribeしたメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/5a7dfd72-7dda-0f35-8a91-54c0c74abc8d.png)



## まとめ　

ということで、今回はReact StudioというWebAppを制作するためのプロタイピングツールを使用して、ちょっとかっこいいROSと通信できるWebAppを作るということをやってみました。お気づきの人もいるかと思いますが、最後のスクリーンショットにJoyStickが出ていると思いますが、このようにReactで使えるパッケージを使用して、さらにカッコイイWebAppを作ることもできます。みなさんも是非試してみてください！(ただしMacユーザー限定ですが