• ROS学习(28)Web GUI



    前言

      ROS Web tools社区开发了很多功能强大的web功能包。针对本篇文章,创建新的工作空间catkin_js_ws,并进行初始化等操作。

    一、rosbridge_suite元功能包

      rosbridge_suite功能包用于完成web浏览器和ROS之间的数据交互,是一种中间件,屏蔽了ROS中复杂的算法、接口、消息传递机制等,使用socket序列化协议为机器人应用提供更为简单的接口。
      rosbridge_suite允许使用html5 web sockets或者标准的posix ip sockets进行ros的消息传送。
    安装,命令如下:

    sudo apt-get install ros-kinetic-rosbridge-suite
    
    • 1

    该元功能包包含如下三个功能包:

    1. rosbridge_library:提供ROS消息与JSON消息之间转换的python API
    2. rosbridge_server:提供websocket服务
    3. rosapi:通过服务调用来获取ROS中的Topic和Parameters

    二、roslibjs、ros2djs、ros3djs功能包

    ROS web tools开发了一系列rosbridge的客户端功能包,可以通过web浏览器发送JSON命令,在不同场景中实现ROS丰富的功能。

    1. roslibjs:实现了ROS中的部分功能,例如Topic、Server、actionlib、TF、URDF等。
    2. ros2djs:在roslibjs的基础上提供二维可视化管理工具,例如在web浏览器中可视化显示二维地图。
    3. ros3djs:提供三维可视化工具,可以基于web创建一个rviz实例,三维显示URDF、TF等信息。

    这三个功能包需要通过源码编译的方式进行安装,命令如下:

    git clone https://github.com/RobotWebTools/roslibjs.git
    git clone https://github.com/RobotWebTools/ros2djs.git
    git clone https://github.com/RobotWebTools/ros3djs.git
    
    • 1
    • 2
    • 3

    下载源码到catkin_ws工作空间,即可使用catkin_make命令进行编译。

    三、tf2_web_republisher功能包

    该功能包可以计算TF数据,并且发送到ros3djs客户端,实现机器人的运动。
    需要通过源码编译的方式进行安装,命令如下:

    sudo apt-get install ros-kinetic-tf2-ros
    git clone https://github.com/RobotWebTools/tf2_web_republisher
    
    • 1
    • 2

    工作空间src目录,如图所示:
    在这里插入图片描述
    然后执行编译命令,编译成功,如下:
    请添加图片描述

    四、创建web应用

    功能描述:通过web远程控制机器人运动,并且显示机器人的三维模型。
    实现原理:使用keyboardteleopjs功能包,通过JavaScript实现浏览器中对键盘按键的识别,并且发布Twist消息。Twist消息会由rosbridge的客户端使用JSON命令通过web sockets发送到服务器,然后服务器负责解析消息,通过controller控制机器人移动。而tf2_web_republisher会将机器人的TF数据通过rosbridge发送到客户端,在ros3djs的可视化显示中更新机器人状态。
    创建功能包web_gui,创建keyboardteleop.html文件,代码如下:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-3.5.1.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-3.5.1.min.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-3.5.1.slim.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.12.4.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="http://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
        <script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/blitzer/jquery-ui.css">
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/cupertino/jquery-ui.css">
        <script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
        <script src="https://static.robotwebtools.org/roslibjs/current/roslib.js"></script>
        <script src="/home/zt/catkin_js_ws/src/ros3djs/build/ros3d.js"></script>
        <script src="/home/zt/catkin_js_ws/src/ros3djs/build/ros3d.min.js"></script>
        <script src="/home/zt/catkin_js_ws/src/web_gui/build/keyboardteleop.js"></script>
    
    <script>
      /**
       * Setup all GUI elements when the page is loaded. 
       */
    
      var teleop_topic = '/cmd_vel'
      var base_frame = 'odom';
    
      var init_flag = false
    
    function submit_values(){
      teleop_topic = document.getElementById("tele_topic").value;
      base_frame = document.getElementById("base_frame_name").value;
    
      init_flag = true;
      init();
    }
    
    function init() {
    
    	if(init_flag == true)
    	{
    		// Connecting to ROS.
    		var ros = new ROSLIB.Ros({
    			url : 'ws://localhost:9090'
    		});
    
    
    		// Initialize the teleop.
    		var teleop = new KEYBOARDTELEOP.Teleop({
    			ros : ros,
    			topic : teleop_topic
    		});
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////
    		var viewer = new ROS3D.Viewer({
    			background : 000,
    			divID : 'urdf',
    			width : 1280,
    			height : 600,
    			antialias : true
    
    		});
    
    		// Add a grid.
    		viewer.addObject(new ROS3D.Grid());
    
    		// Setup a client to listen to TFs.
    		var tfClient = new ROSLIB.TFClient({
    			ros : ros,
    			fixedFrame : base_frame,
    			angularThres : 0.01,
    			transThres : 0.01,
    			rate : 10.0
    		});
    
    		// Setup the URDF client.
    
    		var urdfClient = new ROS3D.UrdfClient({
    			ros : ros,
    			tfClient : tfClient,
    			path : 'http://resources.robotwebtools.org/',
    			rootObject : viewer.scene,
    			loader : ROS3D.COLLADA_LOADER
    		});
    
    
    	///////////////////////////////////////////////////////////////////////////////////////////////////
    
    		// 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);
    
    		init_flag = false;
    	}
    }
    
    </script>
    </head>
    
    <body onload="init()">
      <h1>Web-browser keyboard teleoperation</h1>
    
    	<form >
    		Teleop topic:<br>
    		<input type="text" name="Teleop Topic" id='tele_topic' value="/cmd_vel">
    		<br>
    		Base frame:<br>
    		<input type="text" name="Base frame" id='base_frame_name' value="/odom">
    		<br>
    	 <input type="button" onmousedown="submit_values()" value="Submit"> 
    	</form> 
    
      <p>Run the following commands in the terminal then refresh this page. Check the JavaScript
        console for the output.</p>
      <ol>
        <li><tt>roslaunch mrobot_gazebo view_mrobot_with_kinect_gazebo.launch </tt></li>
        <li><tt>rosrun tf2_web_republisher tf2_web_republisher </tt></li>
        <li><tt>roslaunch rosbridge_server rosbridge_websocket.launch</tt></li>
        <li>Use WASD on your keyboard to move the robot (must have this browser window focused).</li>
      </ol>
      <div id="speed-label"></div>
      <div id="speed-slider"></div>
      <div id="urdf"></div>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    关键代码解释如下:

    var ros = new ROSLIB.Ros({
    			url : 'ws://localhost:9090'
    		});
    
    • 1
    • 2
    • 3

    创建一个ROSLIB.Ros对象用于连接rosbridge_server,如果rosbridge_server位于本机,IP使用localhost,否则需要修改为相应的IP地址。

    var teleop = new KEYBOARDTELEOP.Teleop({
    			ros : ros,
    			topic : teleop_topic
    		});
    
    • 1
    • 2
    • 3
    • 4

    创建一个KEYBOARDTELEOP.Teleop对象,用来识别键盘按键并且发布消息,发布的话题通过变量teleop_topic设置,也就是”/cmd_vel“,设置了ROS的节点对象ros。

    var viewer = new ROS3D.Viewer({
    			background : 000,
    			divID : 'urdf',
    			width : 1280,
    			height : 600,
    			antialias : true
    
    		});
    viewer.addObject(new ROS3D.Grid());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    创建一个ROS3D.Viewer的可视化对象,用于显示机器人的URDF模型,同时设置了可视化区域的分辨率尺寸,还通过addObject方法在可视化区域中添加了背景网格。

    	var tfClient = new ROSLIB.TFClient({
    			ros : ros,
    			fixedFrame : base_frame,
    			angularThres : 0.01,
    			transThres : 0.01,
    			rate : 10.0
    		});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建一个TF客户端,订阅tf2_web_republisher功能包发布的TF数据,更新可视化对象中的机器人状态。其中有一个似曾相识的参数——fixedFrame,与rviz中的属性相同。

    	var urdfClient = new ROS3D.UrdfClient({
    			ros : ros,
    			tfClient : tfClient,
    			path : 'http://resources.robotwebtools.org/',
    			rootObject : viewer.scene,
    			loader : ROS3D.COLLADA_LOADER
    		});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建一个URDF客户端,加载机器人模型,设置ROS节点、TF客户端模型加载路径,使用ROS3D.COLLADA_LOADER加载器,通过ROS中的robot_description参数将模型加载到COLLADA文件中。

    		$('#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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    创建一个滑动条,控制机器人的速度大小。

    	<form >
    		Teleop topic:<br>
    		<input type="text" name="Teleop Topic" id='tele_topic' value="/cmd_vel">
    		<br>
    		Base frame:<br>
    		<input type="text" name="Base frame" id='base_frame_name' value="/odom">
    		<br>
    	 <input type="button" onmousedown="submit_values()" value="Submit"> 
    	</form> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    创建两个输入框,用于设置速度控制的话题名和基坐标系名,创建确认按钮,点击后会提交输入框的表单,修改程序中的变量值。

    五、使用web浏览器控制机器人

    这里使用之前自定义的机器人模型,启动机器人模型,命令如下:

    roslaunch robot_sim_gazebo robot.launch
    
    • 1

    启动成功,RVIZ效果如下:
    在这里插入图片描述
    gazebo效果如下:
    在这里插入图片描述
    仿真器启动成功后,就可以启动tf2_web_republisher和rosbridge_server了,命令如下:

    rosrun tf2_web_republisher tf2_web_republisher
    roslaunch rosbridge_server rosbridge_websocket.launch
    
    • 1
    • 2

    现在,服务器的节点全部启动成功。以网页的形式打开keyboardteleop.html,效果如下:
    请添加图片描述
      点击submit按钮后,下方会出现速度滑动条和三维可视化界面,机器人很快就在界面中加载出现,类似于RVIZ中的可视化区域。
      如果要使用键盘按键控制机器人的移动,请确保鼠标点在网页上。然后我们就可以使用键盘上的W、A、S、D键控制gazebo仿真器中的机器人前后左右移动,web浏览器中的机器人状态也会更新。
      在以后的学习中,还可以基于web功能包实现web浏览器中的SLAM、导航、语音控制等复杂功能。http://robotwebtools.org/这个网站上提供了很多库用来开发和ROS相关的web应用。

  • 相关阅读:
    ESP-C3入门22. 基于VSCODE使用内置JTAG调试程序
    SpringBoot入门
    22python生命周期的一种案例
    MySQL半同步复制源码解析
    Elastic Stack 8.0 安装 - 保护你的 Elastic Stack 现在比以往任何时候都简单
    NoSuchModuleError: Can‘t load plugin: sqlalchemy.dialects:clickhouse解决方案
    布隆过滤器及其应用
    35 岁失业了真的会很难找到工作吗?
    电子产品量产工具-软件架构-显示系统
    二刷算法训练营Day14 | 二叉树(1/9)
  • 原文地址:https://blog.csdn.net/u011832219/article/details/125533401