ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

You will need both port forwarding and robotwebtools if you plan to make the interface a web browser. You don't say in your question how you are doing it today but I'll assume you're using the standard route of having ROS on multiple machines and using standard pub/sub.

If you plan to have the remote machine running ROS and controlling same as now, I think you'll find a VPN in your future but I have zero understanding of how that will work so will not comment further.

If you do not plan to have ROS running on remote machine, then rosbridge, robotwebtools and portforwarding will be required.

As you note, robotwebtools is how to interface using browser. The robotwebtools site example codes includes a telop example so much of the work has been for you, but the last time I looked at that site the code had some dead links (URL to libraries that no longer work). You'll also find that getting telop to run on an iPhone will be very difficult as iOS will not present a keyboard unless there is a textbox open. When I started the same thing you're trying I gave up on the keyboard based telop and instead created a click-a-button based code for "telop"ing. If you're planning on remote machine being a PC with keyboard, then you're probably OK. But if control via a phone is required, you should not plan on a keyboard input method.

You'll need to use and understand rosbridge, robotwebtools, apache, HTML, and at least a little about how networks work.

I cannot help you with your portforwarding issue. You haven't provided any info on your network (school, work, home, port 80 blocked, intermediate firewalls, etc).

If you tell me you're not working on a homework assignment I can provide the HTML code for my page that allows for driving robot around clicking on buttons on webpage with camera streaming video.

You will need both port forwarding and robotwebtools if you plan to make the interface a web browser. You don't say in your question how you are doing it today but I'll assume you're using the standard route of having ROS on multiple machines and using standard pub/sub.

If you plan to have the remote machine running ROS and controlling same as now, I think you'll find a VPN in your future but I have zero understanding of how that will work so will not comment further.

If you do not plan to have ROS running on remote machine, then rosbridge, robotwebtools and portforwarding will be required.

As you note, robotwebtools is how to interface using browser. The robotwebtools site example codes includes a telop example so much of the work has been for you, but the last time I looked at that site the code had some dead links (URL to libraries that no longer work). You'll also find that getting telop to run on an iPhone will be very difficult as iOS will not present a keyboard unless there is a textbox open. When I started the same thing you're trying I gave up on the keyboard based telop and instead created a click-a-button based code for "telop"ing. If you're planning on remote machine being a PC with keyboard, then you're probably OK. But if control via a phone is required, you should not plan on a keyboard input method.

You'll need to use and understand rosbridge, robotwebtools, apache, HTML, and at least a little about how networks work.

I cannot help you with your portforwarding issue. You haven't provided any info on your network (school, work, home, port 80 blocked, intermediate firewalls, etc).

If you tell me you're not working on a homework assignment I can provide the HTML code for my page that allows for driving robot around clicking on buttons on webpage with camera streaming video.

EDIT after follow on questions:

1 - see below for HTML code that worked on my set up. This code resides on the robot computer and is accessed through the page being served by Apache that is also running on the robot computer.

2 - Google tells me that port forwarding can be setup on those air cards. You'll need to port 80 and 8080 and 9090 I think(can't remember for sure) to run the code below. The air card that needs the port forwarding is the one that supports the robot, not the one being used by remote. You need to know the ip address for the aircard supporting the robot and route ports specially to the IP address of the robot on the wifi network.

3 - As I noted in the original answer, if you plan to run ROS on remote machine I cannot help you. I think you need VPN for that. I don't know anything about VPN(never tried). My information here is only dealing with controlling robot through a web browser from internet connected device. If this is not what you want, then disregard everything I have provided.

If you're going to try the HTML route (proven) I suggest you get it running via HTML on a local network. Once it's running then you can work out the internet access and port forwarding issues. To do this the aircard needs to be configured to allow communication between machines on the network. Not sure they allow that.

Follow the ROS tutorials for rosbridge and spend time on robotwebtools.org. Install apache and get a simple page running within the local network. Then get familiar with debug page on your favorite browser.

Have fun with it but don't expect it to go smoothly. It took me a few weeks to get the page below running from a remote (internet connected) machine.

You can review a couple other questions I've answered that give additional info on how it is set up:

https://answers.ros.org/question/315015/what-is-the-best-way-to-monitor-and-remote-control-the-robot-from-tablet/

https://answers.ros.org/question/319626/real-time-map-generate-on-web-like-a-rviz/#319636

And finally: No comments about messy code - I'm not a SW guy.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1">

<script type="text/javascript" src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<script type="text/javascript">
  var pi_img = new Image(); 
  var ip = location.host;
</script>
<script type="text/javascript" type="text/javascript">
  var ip = String(location.host);
  var x = 0;
  var z = 0;
  var scale = 0;
  var scale_max = 0.2;
  var out_message = "";

  // Connecting to ROS
  // -----------------
  var newURL = "ws://" + ip + ":9090";
  var ros = new ROSLIB.Ros({
    url : newURL
  });

  ros.on('connection', function() {
    console.log('Connected to websocket server.');
  });

  ros.on('error', function(error) {
    console.log('Error connecting to websocket server: ', error);
  });

  ros.on('close', function() {
    console.log('Connection to websocket server closed.');
  });

    function sendTelop(){

        var cmdVel = new ROSLIB.Topic({
            ros : ros,
            name : '/cmd_vel',
            messageType : 'geometry_msgs/Twist'
        });

        var outputTopic = new ROSLIB.Topic({
            ros : ros,
            name : '/webpage',
            messageType : 'std_msgs/String'
        });

        var out_string = new ROSLIB.Message({
        });

        out_string.data = out_message;

        var twist = new ROSLIB.Message({
          linear : {
            x : x,
            y : 0,
            z : 0
          },
          angular : {
            x : 0,
            y : 0,
            z : z
          }
        });
        cmdVel.publish(twist);
    outputTopic.publish(out_string);
    console.log('output publisher: ' + out_string.data);
    }
  // Subscribing to a Topic
  // ----------------------

  var listener = new ROSLIB.Topic({
    ros : ros,
    name : '/webpage',
    messageType : 'std_msgs/String'
  });

  listener.subscribe(function(message) {
    console.log('Received message on ' + listener.name + ': ' + message.data);
        document.getElementById('statusbar').innerHTML = message.data + '<br>' + document.getElementById('statusbar').innerHTML;
//    listener.unsubscribe();
  });

    function forward(){
        x = 0.5 * scale_max;
        z = 0;
        out_message = "go forward";
        sendTelop();
    }
    function left(){
        x = 0;
        z = scale_max;
        out_message = "rotate left";
        sendTelop();
    }
    function right(){
        x = 0;
        z = -scale_max;
        out_message = "rotate right";
        sendTelop();
    }
    function backward(){
        x = -0.5 * scale_max;
        z = 0;
        out_message = "go backward";
        sendTelop();
    }
    function stop(){
        x = 0;
        z = 0;
        out_message = "stop";
        sendTelop();
    }


//init();

</script>
<style>
  #buttonup{
    width: 200px;
    height: 40px;}

  #buttondown{
    width: 200px;
    height: 40px;}

  #buttonleft, #buttonright{
    display:inline-block;
    width: 98px;
    height: 40px;}

</style>

</head>

<body>

  <h1>Robot Web Interface</h1>
  <h2>Allows remote access to the family robot.</h2>
  <h2>Press-and-hold (for at least 1 sec) a button to move robot.</h2>
  <p>*Reload page if needed as cached pages don't work. </p>

    <input type="button" id="buttonup" 
    onmousedown="inter=setInterval(forward, 500);"
    onmouseup="clearInterval(inter);stop();" 
    ontouchstart= "inter=setInterval(forward, 500);" 
    ontouchend ="clearInterval(inter);stop();" 
    value="Go forward" />

<br>
    <input type="button" id="buttonleft" 
    onmousedown="inter=setInterval(left, 500);"
    onmouseup="clearInterval(inter);stop();" 
    ontouchstart= "inter=setInterval(left, 500);" 
    ontouchend ="clearInterval(inter);stop();" 
    value="Rotate left" />

    <input type="button" id="buttonright" 
    onmousedown="inter=setInterval(right, 500);"
    onmouseup="clearInterval(inter);stop();"
    ontouchstart= "inter=setInterval(right, 500);" 
    ontouchend ="clearInterval(inter);stop();"  
    value="Rotate right" />

<br>
    <input type="button" id="buttondown" 
    onmousedown="inter=setInterval(backward, 500);"
    onmouseup="clearInterval(inter);stop();" 
    ontouchstart= "inter=setInterval(backward, 500);" 
    ontouchend ="clearInterval(inter);stop();" 
    value="Go backward" />

  <p></p>
    <iframe src= '' id= 'target_frame' name='target_frame' width="410" Height="310"></iframe>
  <p></p>
<script>
  document.getElementById('target_frame').src = "http://" + ip + ":8080/stream?topic=/convertedimage";
</script>


  <p>Commands being sent to robot:</p>
    <div class="messages" id="statusbar" style = "width:200px; height:500px; overflow:hidden; background-color:grey"></div>

</body>

</html>