11
13

More than 1 year has passed since last update.

ROS講座53 ブラウザでpub subする

Last updated at Posted at 2018-09-06

環境

この記事は以下の環境で動いています。

項目
CPU Core i5-8250U
Ubuntu 20.04
ROS Noetic

インストールについてはROS講座02 インストールを参照してください。
またこの記事のプログラムはgithubにアップロードされています。ROS講座11 gitリポジトリを参照してください。

概要

rosbridgeはROSの通信とwebsocketを相互変換するROSパッケージです。ブラウザはjavascriptでwebsocketの通信を扱えるので、これによってwebページ経由でROSと通信できます。
今回はTalkerとListenerのサンプルを解説します。

インストール

rosbridgeのインストールは以下のコマンドで行えます。

sudo apt install ros-noetic-rosbridge-suite

ソースコード

launch

前回使ったroswwwに加えて、rosbridgeのlaunchを起動させるだけです。

web_lecture/launch/bridge.launch
<launch>
  <include file="$(find roswww)/launch/roswww.launch" />
  <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" />
</launch>

talker(html)

publishを行うwebページ(javascript)の例です。

web_lecture/www/pub.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <style type="text/css">
    <!--
      *{ padding:0px; margin:0px;}
    -->
    </style>
    <title>ROS WEB Publisher</title>
    <script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
    <script src="https://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
  </head>

  <body>
    <script type="text/javascript">

        <!--
if(!Talker){
    var Talker = {
        ros : null,
        name : "",
        init : function(){
            this.ros = new ROSLIB.Ros();
            this.ros.on('error', function(error) {
                document.getElementById('state').innerHTML = "Error";
            });
            this.ros.on('connection', function(error) {
                document.getElementById('state').innerHTML = "Connect";
            });
            this.ros.on('close', function(error) {
                document.getElementById('state').innerHTML = "Close";
            });
            this.ros.connect('ws://' + location.hostname + ':9090');
        },
        send : function(){
            if(document.getElementById("comment").value.length == 0) return;
            var comment = document.getElementById("comment").value;
            var pub = new ROSLIB.Topic({
                ros : this.ros,
                name : '/chatter',
                messageType : 'std_msgs/String'
            });

            var str = new ROSLIB.Message({data : comment});
            pub.publish(str);
        }
    }
    Talker.init();

    window.onload = function(){
    };
    window.onunload = function(){
        Talker.ros.close();
    };
}
        //-->
    </script>
    <p>status: <label id="state">Disconnect</label></p>

    <form action="javascript:Talker.send();" id="ui">
      <label>Comment: </label>
      <input type="text" id="comment" size="20" />
      <input type="submit" value="send" id="btn" /><br/>
    </form>
  </body>
</html>

詳しく解説していきます。
以下のような部分でTalkerの宣言を行っています。

Talkerの宣言
var Talker = {
...
}

以下の部分で初期化動作の宣言をしています。function以下の最初の行ではROSLIBを設定しています。その下の9行はrosbridgeのコネクションの状態が変わった時の処理です。下から2行目のthis.ros.connect('ws://' + location.hostname + ':9090');ではwebsocket通信を開始します。rosbridgeは標準では9090ポートで通信を行います。

Talkerの初期化の宣言
init : function(){
  this.ros = new ROSLIB.Ros();
  this.ros.on('error', function(error) {
    document.getElementById('state').innerHTML = "Error";
  });
  this.ros.on('connection', function(error) {
    document.getElementById('state').innerHTML = "Connect";
  });
  this.ros.on('close', function(error) {
    document.getElementById('state').innerHTML = "Close";
  });
  this.ros.connect('ws://' + location.hostname + ':9090');
}

以下がpublisherのコードです。今回のスクリプトでは「send」ボタンを押すと毎回publisherを生成してpublishします。
1行目は送る文字列(id:commentのテキストボックスから持ってくる)が0文字なら飛ばす処理です。
4~8行目がpublisherの生成です。トピック名とメッセージTypeを記述します。
var str = new ROSLIB.Message({data : comment});でメッセージを作っています。括弧の中でフィールド名を持つ構造体として生成します。

publishのコード
send : function(){
  if(document.getElementById("comment").value.length == 0) return;
  var comment = document.getElementById("comment").value;
  var pub = new ROSLIB.Topic({
    ros : this.ros,
    name : '/chatter',
    messageType : 'std_msgs/String'
  });

  var str = new ROSLIB.Message({data : comment});
  pub.publish(str);
}

listener(html)

web_lecture/www/sub.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
        <style type="text/css">
        <!--
            *{ padding:0px; margin:0px;}
        -->
        </style>
        <title>ROS WEB Subscriber</title>
        <script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
        <script src="https://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
      </head>
    <body>
    <script type="text/javascript">
    <!--
if(!Listener){
    var Listener = {
        ros : null,
        name : "",
        init : function(){
            this.ros = new ROSLIB.Ros();
            this.ros.on('error', function(error) {
                document.getElementById('state').innerHTML = "Error";
            });
            this.ros.on('connection', function(error) {
                document.getElementById('state').innerHTML = "Connect";
            });
            this.ros.on('close', function(error) {
                document.getElementById('state').innerHTML = "Close";
            });
            this.ros.connect('ws://' + location.hostname + ':9090');

            var sub = new ROSLIB.Topic({
                ros : this.ros,
                name : '/chatter',
                messageType : 'std_msgs/String'
            });
            sub.subscribe(function(message) {
                var res = message.data;
                var el = document.createElement("p");
                el.innerHTML = res
                document.getElementById("talk").appendChild(el);
            });
        }
    }
    Listener.init();

    window.onload = function(){
    };
    window.onunload = function(){
        Listener.ros.close();
    };
}
        //-->
    </script>
    <p>status: <label id="state">Disconnect</label></p>
    <div id="talk"><p></p></div>
  </body>
</html>

以下の部分でSubscriberを設定します。publisherと同じようにTopic名とメッセージTypeを宣言します。その下で、callback関数の設定をします。今回のスクリプトではやってきた文字列を<p>要素(id:talk)に追記していきます。

Subscriberの設定
var sub = new ROSLIB.Topic({
  ros : this.ros,
  name : '/chatter',
  messageType : 'std_msgs/String'
});
sub.subscribe(function(message) {
  var res = message.data;
  var el = document.createElement("p");
  el.innerHTML = res
  document.getElementById("talk").appendChild(el);
});

実行

launchを実行します。

roslaunch web_lecture bridge.launch

この後にブラウザを2つ開いてlocalhost:8085/web_lecture/pub.htmllocalhost:8085/web_lecture/sub.htmlのページにアクセスします。以下のようにpub.htmlのページでテキストボックスに文字を入れて「send」を押すと、sub.htmのページに表示されます。

web_pubsub.gif

参考

ROSのWebインタフェースを作る

目次ページへのリンク

ROS講座の目次へのリンク

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13