CodeZine(コードジン)

特集ページ一覧

ラズパイで動くロボット「GoPiGo」をつかって遠隔見守りロボットを作ろう(3)スマホ連携編

ROSとRaspberry Piで遠隔みまもりロボットを作ろう 第3回(「Tech-Sketch」出張所/番外編)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/04/13 14:00
目次

スマホでGoPiGoの操作をしよう

 ではいよいよカメラ映像を見ながらGoPiGo実機の操作ができるようにしてみましょう。ここまで来れば遠隔操作まであと一歩です。

 最終的に、下図のような構成を作ります(Webサーバは省略)。つまり、「1. カメラ映像をブラウザで見てみる」「2. スマホからGoPiGoを操作できるようにする」の構成をそのまま利用します。唯一変わったのは、/cmd_velの受け手がrostopic echoコマンドで表示するのではなく、GoPiGo台車ノードに変えたところです(図の右下)。

 このノードは、第1、2回でも紹介したようにGoPiGoの制御ノードで、速度トピック/cmd_velを受けとると、その速度で移動・回転します。

Webサーバを除いた遠隔操作システムの全体像
Webサーバを除いた遠隔操作システムの全体像

 では、遠隔操作を実行してみましょう。ここまでのコマンドをまとめると、下記のように5つのコマンドになります。

ここまで起動中のコマンド
$ roscore
$ rosrun libuvc_camera camera_node
$ rosrun web_video_server web_video_server
$ roslaunch rosbridge_server rosbridge_websocket.launch
$ roslaunch roswww roswww.launch

 これらがすでに起動できていることを確認したあと、GoPiGoの台車のノード(図の右下)を起動しましょう。

GoPiGoの台車ノードの起動
$ roslaunch ropigo ropigo.launch

 起動後、スマホで下記にアクセスして操作しましょう。

GoPiGoの台車ノードの起動
http://GoPiGoのIPアドレス:8085/webjoy_example/index.html

 上の動画のように、ジョイスティックを動かした方向にあわせて、ロボットが移動・回転しましたか? 部屋の中を自由に走らせたり、別の部屋に探索しに行ったりと、自由に楽しんでください!

 ここからはオプションですが、以上の計6つのコマンドを1発にまとめたlaunchファイルをwebjoy_exampleパッケージ内に用意しました。実行するには、今までに入力したすべてのコマンドをCtrl-Cで停止し、次のコマンドを入力してください。

一発で起動するコマンド
$ roslaunch webjoy_example webjoy_example.launch

 先ほどと同じように操作できれば成功です!

 余裕のある方は、このファイルの中身を見てみてください。roscoreを除く5つのコマンドが記述されていることが分かります。roscoreはlaunchファイル実行時は自動で起動します。

コードを理解しよう

 上記「パッケージの作成」の項で解説したように、webjoy_exampleという名前のパッケージを新規に作りました。これは、遠隔操作を行うことができる画面を生成し、ジョイスティックの操作コマンドをROSに送る役割を果たします。

 このパッケージ(のwwwディレクトリ)はroswww(Webサーバ)の起動時に読み込まれ、スマホなどでクライアントから接続されると自動で画面生成、ROSとの通信が開始されます。

 では、その動作の詳細をコードを読んで理解しましょう。

 webjoy_exampleパッケージのwwwディレクトリには、2つのファイルがあります。

www
    ├── index.html
    └── webjoy.js

 まず、index.htmlの中身をみてみましょう。

index.htmlの解説

 9~16行目はbodyで、bodyのロード時にROSの初期化処理を行います。

 また、表示のためdivのidにカメラ映像(video)や速度(joy_vel)、ジョイスティック(joystick)を割り当てています。

9    <body onload="init_ros();">
10    <h2>GoPiGo Joystick Example</h2>
11     <div id="video"></div>
12        <div id="joy_vel">
13          <h3>Linear: 0.0, Angular: 0.0</h3>
14        </div>
15    <div id="joystick"></div>
16   </body>

 18行目~22行目ではJavaScriptの読み込みを行っています。

18  <script type="text/javascript" src="http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.js"></script>
19  <script type="text/javascript" src="http://cdn.robotwebtools.org/roslibjs/current/roslib.js"></script>
20  <script type="text/javascript" src="http://cdn.robotwebtools.org/mjpegcanvasjs/current/mjpegcanvas.min.js"></script>
21  <script type="text/javascript" src="https://rawgit.com/yoannmoinet/nipplejs/master/dist/nipplejs.js"></script>
22  <script type="text/javascript" src="webjoy.js"></script>

 19行目はROSとの通信を行うためのroslibjsの読み込みを行い、20行目はストリーミングサーバと接続して映像を表示するためのmjpegcanvasの読み込みを行なっています。

 また、21行目はnippleJSというバーチャルジョイスティックのライブラリを読み込んでいます。

 22行目はwebjoy.jsという今回のアプリ向けに作成したJavaScriptファイルです。こちらのファイルについて詳しく解説します。

webjoy.jsの解説

 webjoy.jsは主に3つのことを行っています。

  1. ROSのrosbridge_server(WebSocketサーバ)との接続
  2. ジョイスティックイベントに応じて、速度トピックを配信
  3. カメラ映像の取り込み

1. rosbridge_serverとの接続

 rosbridge_serverと接続するために、まずROSのオブジェクトを生成します。また、次の行で接続先のサーバのホスト名とポート番号(9090)を指定しています。

1  var ros = new ROSLIB.Ros();
2
3  var serverURL = "ws://" + location.hostname + ":9090";

 次に、先ほど指定したサーバの宛先URLを指定してrosbridge_serverと接続します。

28  function init_ros() {
29        try {
30                ros.connect(serverURL);
31                console.log("Connected to ROS.");
32        } catch (error) {
33                console.error(error);
34        }
35 }

 また、ROSとの接続時や接続エラー時などのイベントに対してコールバックを登録できます。

37  ros.on('connection', function() {
38        console.log('Rosbridge connected.');
39  });
40 
41  ros.on('error', function(error) {
42        console.log("Rosbridge Error: " + error);
43        disconnectServer();
44  });
45
46  ros.on('close', function(error) {
47        console.log("Rosbridge Close: " + error);
48  });

2. ジョイスティック操作に応じて、速度トピックを配信

 まず、55~61行目でジョイスティックを使うためのnippleJSのジョイスティックオブジェクトを生成しています。

55  var joystick = nipplejs.create({
56            zone: document.getElementById('joystick'),
57            mode: 'static',
58            position: { left: '50%', top: '85%' },
59            color: 'blue',
60            size: 150
61        });

 これはパラメータを細かく指定することによって、zone(どのdivにジョイスティックを表示するか)やmode(ジョイスティックの表示位置モード)などを細かく指定できます。ここでは、joystickという名前のdivにジョイスティックを割り当て、staticモード(表示位置固定)で表示しています。

 次に、nippleJSによるジョイスティックのイベントコールバックを見てみましょう。3種類あります。

  • start end:ジョイスティックに触れたタイミング、離したタイミングで呼ばれます
  • dir:ジョイスティックの押されている方向が確定した段階で呼ばれ、4方向(上下右左)どれかの値を返します
  • move:ジョイスティックが移動されている最中に呼ばれ、ジョイスティック中心からの距離などを返します

 これらを踏まえ、コード量の多いmoveのコールバックを見てみましょう(73~108行目)。

73  joystick.on('move', function (evt, data) {
74          var distance = data.distance;
75          var vel_x = vel_theta = 0.0;
76         
77          var x = LINEAR_VEL * distance / 75.0;
78          var theta = ANGULAR_VEL * distance / 75.0;
79 
80          if(joyDirection === "up"){
81            vel_x = x;
82          }
83          else if(joyDirection === "down"){
84             vel_x = -x;
85          }
86          else if(joyDirection === "right"){
87             vel_theta = -theta;
88          }
89          else if(joyDirection === "left"){
90             vel_theta = theta;
91          }
92
93          twist = new ROSLIB.Message({
94              linear : {
95              x : vel_x,
96              y : 0.0,
97              z : 0.0
98            },
99              angular : {
100              x : 0.0,
101              y : 0.0,
102             z : vel_theta
103            }
104         });
105         cmdVel.publish(twist);
106         
107         document.getElementById("joy_vel").innerHTML = "<h3>Linear: "+vel_x.toFixed(1)+", Angular: "+vel_theta.toFixed(1)+"</h3>";         
108 });

 ここでは、ジョイスティック中心からの距離や方向に合わせ、そのGoPiGoに与えるスピードを決定しています(73~91行目)。

 そして、決定した速度を/cmd_velという名前のトピックとしてWebからROSに配信(publish)しています(93~105行目)。

3. カメラ映像の取り込み

 最後に、カメラ映像の取り込みを行なっている部分です(5~13行目)。

5  var mjpegViewer = new MJPEGCANVAS.Viewer({
6                                     divID : 'video',
7                                     host : document.location.hostname,
8                                     port : 8080,
9                                     width : Math.round(window.innerWidth),
10                                   height : Math.round(window.innerWidth* 480/640),
11                                   quality : 50,
12                                   topic : "/image_raw"
13  });

 mjpegcanvas.jsが提供するビューアを生成し、その引数に、映像の表示divの指定やストリーミングサーバのホスト名やポート番号(8080)、縦横の大きさ、画質、読み込むトピック名を指定することでカメラ映像が取り込まれ、HTMLでブラウザに表示されます。

おわりに

 少し長くなりましたが、今回の記事ではGoPiGoをスマホで遠隔操作する方法を解説しました。次回はいよいよローカル環境を飛び出し、クラウドの世界に入っていく予定です。次回もお楽しみに!



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:ROSとRaspberryPiで遠隔みまもりロボットを作ろう(「Tech-Sketch」出張所/番外編)

著者プロフィール

  • 古賀 勇多(TIS株式会社)(コガ ユウタ)

    TIS株式会社 AIサービス事業部AIサービス企画開発部所属。2015年入社後、自律移動ロボットの研究開発に従事。ロボット・クラウド・機械学習を活用した、人と共生できるロボットシステムの開発を目標にしている。最近興味がある技術は電子工作や3D CAD、DIY。

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5