LoginSignup
49
39

More than 5 years have passed since last update.

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

Posted at

 ロボットをWebブラウザから色々操作できれば,便利なわけです.
 個人的にも,人の入力を待つみたいな非同期イベントは,ロボット制御のループからは離しておきたいので,そういう意味でも非同期入力が得意なWebブラウザにお任せしておくのは良さそうだと思っています.

Webサーバを立ち上げる

 なんとびっくりなんですが,ROSのパッケージの中に,簡単なWebサーバを実現するものがありました!roswww
 こいつをインストールすれば,最低限の機能は実現できそうです.

apt
sudo apt-get install ros-indigo-roswww

 実際に起動してみましょう.

roswww.launch
roslaunch roswww roswww.launch

 この状態で, http://localhost:8085/ にアクセスすると,インストール済みパッケージのリストを表示するページが開きます.また, http://localhost:8085/roswww/ にアクセスすると,「roswww, sup?」とだけ書かれたテストページが開きます.
 roswwwは, rosインストール先/share/各パッケージ/www/ のフォルダを参照するので,自作のパッケージにも www フォルダを作って, share 下にインストールすれば, http://localhost:8085/自作パッケージ名/ というURLでアクセスできるようになります.

JavaScriptでTopicをPub/Subする

 さて,静的なページだけだと,やはりつまらない.Webページ上からTopicを投げる方法がないかros-jpのメーリングリストで質問したら,roslibjsという,javascriptから直接ROS TopicのPub/SubやActionの発行など,ROSの緒機能にアクセスできるパッケージを紹介してもらいました!このパッケージは,rosbridgeで提供されるROSのwebsocketの口を利用するようです.
 さっそくインストール.

apt
sudo apt-get install ros-indigo-rosbridge-server

(もしかしたら,roswwwの依存関係で,もう入ってるかも)

 んで,roswwwのlaunchフォルダに以下のようなlaunchファイルを書いて,

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

同じくroswwwのwwwフォルダに以下のようなhtmlファイルを入れます.

chat.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>Sample Chat</title>
        <script src="http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.js"></script>
        <script src="http://cdn.robotwebtools.org/roslibjs/current/roslib.js"></script> </head>
    <body>
        <script type="text/javascript">
        <!--
if(!Chat){
    var Chat = {
        ros : null,
        name : "",
        init : function(){
            this.ros = new ROSLIB.Ros();
            this.ros.on('error', function(error) {
                document.getElementById('state').innerHTML = "Error";
                document.getElementById("btn").disabled = true;
            });
            this.ros.on('connection', function(error) {
                document.getElementById('state').innerHTML = "Connect";
                document.getElementById("btn").disabled = false;
            });
            this.ros.on('close', function(error) {
                document.getElementById('state').innerHTML = "Close";
                document.getElementById("btn").disabled = true;
            });
            this.ros.connect('ws://localhost:9090');

            var sub = new ROSLIB.Topic({
                ros : this.ros,
                name : '/chat',
                messageType : 'std_msgs/String'
            });
            sub.subscribe(function(message) {
                var res = message.data;
                var date = res.substring(1, res.indexOf("]"));
                res = res.substring(res.indexOf("]")+1, res.length);
                var name = res.substring(0, res.indexOf(":"));
                res = res.substring(res.indexOf(":")+1, res.length);
                var el = document.createElement("p");
                el.innerHTML = "[" + date + "] <b>" + name + " :</b> " + res;
                //document.getElementById("talk").appendChild(el);
                document.getElementById("talk").insertBefore(el, document.getElementById("talk").childNodes[0]);

                document.getElementById("btn").disabled = false;
                document.getElementById("state").innerHTML = "received";
            });
        },
        send : function(){
            if(document.getElementById("comment").value.length == 0) return;

            document.getElementById("btn").disabled = true;
            document.getElementById("state").innerHTML = "sending";

            var now = new Date();
            var str_date = (now.getMonth()<10?"0":"") + (now.getMonth()+1) + "/";
            str_date += (now.getDate()<10?"0":"") + now.getDate() + "/";
            str_date += now.getFullYear() + " ";
            str_date += (now.getHours()<10?"0":"") + now.getHours() + ":";
            str_date += (now.getMinutes()<10?"0":"") + now.getMinutes() + ":";
            str_date += (now.getSeconds()<10?"0":"") + now.getSeconds(); 

            var comment = document.getElementById("comment").value;
            var pub = new ROSLIB.Topic({
                ros : this.ros,
                name : '/chat',
                messageType : 'std_msgs/String'
            });

            var str = new ROSLIB.Message({data : "[" + str_date + "]" + this.name + ":" + comment});
            pub.publish(str);
            document.getElementById("comment").value = "";
        }
    }
    Chat.init();

    window.onload = function(){
        Chat.name = window.prompt("What's your name?", "Jane Doe");
        document.getElementById("name").innerHTML = Chat.name;
    };
    window.onunload = function(){
        Chat.ros.close();
    };
}
        //-->
        </script>
<p>Connection status: <label id="state">Disconnect</label></p>
<p>Your name: <label id="name"></label></p>
<form action="javascript:Chat.send();" id="ui">
<label>Comment: </label>
<input type="text" id="comment" size="20" />
<input type="submit" value="send" id="btn" /><br/>
</form>
<div id="talk"><p></p></div>

    </body>
</html>

 それでは,いつものようにインストール.私はros_make_isolatedを愛用してます.ros_makeでも,たぶん同じ.

catkin_make
catkin_make_isolated --install --pkg roswww

そして,以下のコマンドで起動します.

launch_roswww
roslaunch roswww chat.launch

 ここまでできたら,ブラウザで http://localhost:8085/roswww/chat.html にアクセスしてください.名前の入力を促すダイアログが現れるので,適当に入力してください.
 次に,さらにもう1つ別のウィンドウで同じページにアクセスしてください.この状態で,片方のウィンドウからコメントを送ると,rostopicを介して,もう片方のウィンドウにも表示されます!

ROSでChat

 プロジェクトの全文はGitHubにも置いてあるので,参考にしてくださいー.

 以上,WebブラウザをROSのインタフェースにするお話しでしたっ!

49
39
2

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
49
39