diego1# 突破局域网限制,实现互联网范围内控制你的ROS机器人

34 篇文章 11 订阅

更多创客作品,请关注笔者网站园丁鸟,搜集全球极具创意,且有价值的创客作品


1.概述

ROS机器人系统有一个局限就是,所有Robot都必须在一个局域网内,虽然有robot web tools工具集可以实现通过web浏览器控制ROS机器人,但仍然是要求Robot和浏览器必须在同一个局域网内。有许多的应用是需要跨地域,跨网络进行监控机器人的,本文介绍一种突破局域网限制,可以实现互联网范围内通过Web对机器人进行控制。

2.原理

实现的原理还是使用robot web tools工具集,增加一个中转的服务器,本文中此服务器命名为diegoserver。

2.1robot web tools基本原理

robot web tools工具集中实现通过web控制机器人的是通过rosbridge,和roslibjs两个包,通过websocket实现(具体如何安装,请搜索网络,这里不做介绍),先来看一下实现的架构

在这里插入图片描述

robot web tools 提供了一个rosbridge的包,通过topic/service与robot机器人通信,并将相应的topic/service封装成json格式的消息。
roslibjs,是一个java script实现的rosbridge客户端,通过websocket与rosbridge通信,roslibjs负责在web端实现发布消息,订阅消息的基本功能,更上层的js包,有ros2djs,ros3djs,keyboardteleopjs等上层包,可以实现地图,导航,3d,键盘控制等功能,具体功能可以参考官网http://robotwebtools.org/ 网上大部分文章都是翻译官网文章。

2.2 diegoserver 原理

在这里插入图片描述
diegoserver实现的原理简单的来说,就是增加了一个中继服务器,服务器部署在互联网上,实现跨局域网的远程控制

diegobridge是一个部署在和robot,rosbridge同一局域网的一段pyton程序,实现rosbridge和diegoserver通讯。

3. cmd_vel的web发布

下面实现一个最基本的cmd_vel消息的web发布过程

3.1 web端实现

web端实现完全按照roslibjs的规范就可以,只要将ros的连接到diegoserver(也可以是你自己的服务器)即可,具体实现网上有很多参考代码。本文用的是官网的示例代码。如下是js的代码,用到了keyboardteleopjs,可以通过键盘的实现cmd_vel topic的发布

<script type="text/javascript" type="text/javascript">
    /**
     * Setup all visualization elements when the page is loaded.
     */
    function init() {
        // Connect to ROS.
        var ros = new ROSLIB.Ros({
            url: 'ws://diegoserver:5556/rosbridge'
        });

        // Initialize the teleop.
        var teleop = new KEYBOARDTELEOP.Teleop({
            ros: ros,
            topic: '/cmd_vel'
        });

        // Create a UI slider using JQuery UI.
        $('#speed-slider').slider({
            range: 'min',
            min: 0,
            max: 100,
            value: 90,
            slide: function (event, ui) {
                // Change the speed label.
                $('#speed-label').html('Speed: ' + ui.value + '%');
                // Scale the speed.
                teleop.scale = (ui.value / 100.0);
            }
        });

        // Set the initial speed .
        $('#speed-label').html('Speed: ' + ($('#speed-slider').slider('value')) + '%');
        teleop.scale = ($('#speed-slider').slider('value') / 100.0);
    }
</script>

html代码

</div>
                    <div id="speed-label"></div>
                    <div id="speed-slider"></div>
                </div>

3.2服务器端实现

服务器端采用Flask开发,使用flask-socketio包实现websocket通信,服务器本质上就是对rosbridge包的转发,非常简单,如下是转发代码:

from flask_socketio import send, emit, Namespace
import random
import json

class RosBridgeNamespace(Namespace):

    def __init__(self, socketio, namespace=None):
        super().__init__(namespace=namespace)
        self.socketio=socketio
    
    def on_connect(self):
        print('############## some ros connect')
        
    def on_disconnect(self):
        print('disconnect')

    def send_to_front(self,data):
        self.socketio.emit('data',
                      json.dumps(data),
                      namespace='/rosbridge',broadcast=True)
    
    def send_to_rosbridge(self,data):
        self.socketio.emit('diegoserver',
                      data,
                      namespace='/rosbridge',broadcast=True)
        
    def on_rosbridge(self, data):#response for rosbridge
        self.send_to_front(data)


    def on_operation(self,data):# response for web client
        print('**************** receive operation message from web roblibjs client')
        self.send_to_rosbridge(data)

3.3 diegobridge的实现

rosbridge实现使用robot web tools中roslibpy包实现与rosbridge包的通信,通过socketio实现与diegoserver的通信,代码如下:

from __future__ import print_function
import roslibpy
import socketio
import time
import json

sio = socketio.Client()
sio.connect('wt://diegoserver:5556', namespaces=['/rosbridge'])

client = roslibpy.Ros(host='localhost', port=9090)
client.run()

print('my sid is', sio.sid)

host = 'localhost'
port = 9090


class DiegoTalker():
    def __init__(self, topic, topic_type):
        self.topic=topic
        self.topic_type=topic_type

    def talk(self,data):
        talker = roslibpy.Topic(client, self.topic, self.topic_type)
        talker.publish(roslibpy.Message(data))
        talker.unadvertise()

class RosbridgeNamespace(socketio.ClientNamespace):
    def on_connect(self):
        pass

    def on_disconnect(self):
        pass

    def on_diegoserver(self, data):
        print('I received a message from the diego server')    
        if json.loads(data)['topic'] =='/cmd_vel' and json.loads(data)['op']=='publish':
            talker=DiegoTalker('/cmd_vel', 'geometry_msgs/Twist')
            talker.talk(json.loads(data)['msg'])

sio.register_namespace(RosbridgeNamespace('/rosbridge'))

实现的原理也很简单,收到diegoserver发布的cmd_vel消息后转发给rosbridge

4.运行

首先运行rosbridge
roslaunch rosbridge_server rosbridge_websocket.launch
接着运行diegobridge
python3 diegobridge.py
运行后,即可以看到rosbridge输出信息显示已经有一个client连接

在这里插入图片描述

这时候打开diegoserver的控制界面,通过键盘就可以控制

在这里插入图片描述

这是我们用rostopic echo /cmd_vel就可以看到从远程web客户端发布的cmd_vel 消息

在这里插入图片描述

当然可以发布,也可以订阅,原理相同,下图就是通过这样的方法远程订阅/map,并在web显示的效果

在这里插入图片描述

考虑的网络的稳定性,远程控制可能会有实时性的问题,当然这个要看实际的应用场景,要实现一个产品化的应用,应该考虑如下问题:

  • 实时性
  • ROS的topic是高频率,实时发布的,服务器端应该增加高速缓存机制,
  • 安全性,基于互联网的应用,应该充分考虑安全性,如通信过程加密等,这个非常重要,机器人一旦被网络劫持,将有不可预想的后果。
  • 带宽问题,如涉及视频,导航的数据带宽需求是非常大的
  • 其他…
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DiegoRobot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值