4 <meta charset="utf-8" />
6 <link rel="stylesheet" href="assets/stylesheets/bootstrap.min.css">
7 <link rel="stylesheet" href="assets/stylesheets/jquery-ui.css">
8 <link rel="stylesheet" href="assets/stylesheets/jquery.minicolors.css">
11 .minicolors-theme-default.minicolors { margin: 5px; }
12 .bottom-leds > .minicolors-theme-default.minicolors { margin: 5px 0; }
13 .top-leds > .minicolors-theme-default.minicolors { margin-top: 70px; }
14 .wt-icon {background: url('assets/images/wt_top.png'); background-size: cover; background-size: 100%; background-repeat: no-repeat; background-position: center; height: 260px;}
17 <script type="text/javascript">
19 var ros = new ROSLIB.Ros();
20 ros.connect('ws://wildthumper:9090');
21 var isDragging = false;
23 ros.on('connection', function() {
24 $("#information").append(`
25 <div class="alert alert-dismissible alert-success">
26 <span data-dismiss="alert">Connected to websocket server.</span>
31 ros.on('error', function(error) {
32 $("#information").append(`
33 <div class="alert alert-dismissible alert-danger">
34 <span data-dismiss="alert">Error connecting to websocket server.</span>
39 ros.on('close', function() {
40 $("#information").append(`
41 <div class="alert alert-dismissible alert-info">
42 <span data-dismiss="alert">Connection to websocket server closed.</span>
47 //tfClient.subscribe('base_link', function(tf) {
48 // var now = new Date();
49 // $("#pose").text(now.toLocaleTimeString() + ": (" + tf.translation.x + ", " + tf.translation.y + ")");
51 // robotMarker.x = tf.translation.x;
52 // robotMarker.y = -tf.translation.y;
53 // robotMarker.rotation = viewer2D.scene.rosQuaternionToGlobalTheta(tf.rotation);
55 var poseTopic = new ROSLIB.Topic({ros: ros, name: '/robot_pose', messageType: 'geometry_msgs/Pose'});
56 var sensorTopic = new ROSLIB.Topic({ros: ros, name: '/sensors', messageType: 'wild_thumper/Sensor'});
57 var batteryTopic = new ROSLIB.Topic({ros: ros, name: '/battery', messageType: 'sensor_msgs/BatteryState'});
58 var ledStripeTopic = new ROSLIB.Topic({ros: ros, name: '/led_stripe', messageType: 'wild_thumper/LedStripe'});
60 poseTopic.subscribe(function(message) {
62 $("#pose").text(now.toLocaleTimeString() + ": (" + message.position.x + ", " + message.position.y + ")");
65 sensorTopic.subscribe(function(message) {
66 sensordiv = $("#sensors")
67 sensordiv.find("input[name=light]").val(message.light);
68 sensordiv.find("input[name=temp]").val(message.temp.toFixed(1));
69 sensordiv.find("input[name=humidity]").val(message.humidity);
70 sensordiv.find("input[name=pressure]").val(message.pressure.toFixed(1));
71 sensordiv.find("input[name=co]").val(message.co);
74 batteryTopic.subscribe(function(message) {
75 powerdiv = $("#power");
76 powerdiv.find("input[name=voltage]").val(message.voltage.toFixed(1));
77 powerdiv.find("input[name=current]").val(message.current.toFixed(1));
80 viewer2D = new ROS2D.Viewer({
87 .bind('mousewheel', function(e) {
88 if (e.originalEvent.wheelDelta/120 > 0) {
89 viewer2D.scaleToDimensions(10, 10)
91 viewer2D.scaleToDimensions(5, 5)
94 .mousedown(function() {
96 mousePreX = undefined;
97 mousePreY = undefined;
102 .mousemove(function(event) {
104 if (mousePreX != undefined && mousePreY != undefined) {
105 var diffX = event.pageX - mousePreX;
106 var diffY = event.pageY - mousePreY;
107 console.log("Moving viewer2D by " + diffX + ", " + diffY);
108 viewer2D.shift(diffX, diffY);
110 mousePreX = event.pageX;
111 mousePreY = event.pageY;
115 // Setup the nav client.
116 NAV2D.OccupancyGridClientNav({
118 rootObject : viewer2D.scene,
120 serverName : '/move_base'
123 // Initialize the teleop.
124 teleop = new KEYBOARDTELEOP.Teleop({
129 // Create a UI slider using JQuery UI.
130 $('#speed-slider').slider({
136 slide : function(event, ui) {
137 // Change the speed label.
138 $('#speed-label').html('Speed: ' + ui.value + ' m/s');
140 teleop.scale = (ui.value * 2);
144 // Set the initial speed.
145 $('#speed-label').html('Speed: ' + ($('#speed-slider').slider('value')) + ' m/s');
146 teleop.scale = ($('#speed-slider').slider('value') * 2);
148 $('.led_color').minicolors({
151 defaultValue: '#000000',
152 change: function(value) {
153 var rgb = $(this).minicolors('rgbObject');
154 var nums = jQuery.parseJSON($(this).prop("name"));
155 var msg = new ROSLIB.Message({
158 jQuery.each(nums, function(i, num) {
161 red: parseInt(rgb.r*127/255),
162 green: parseInt(rgb.g*127/255),
163 blue: parseInt(rgb.b*127/255)
166 ledStripeTopic.publish(msg);
171 <title>Wild Thumper control</title>
173 <body onload="init()">
174 <div class="container-fluid">
175 <div id="information">
178 <nav class="navbar navbar-expand-lg navbar-light bg-light">
179 <a class="navbar-brand" href="#">Wild Thumper</a>
180 <ul class="nav nav-tabs" role="tablist">
181 <li class="nav-item">
182 <a class="nav-link active" href="#data" data-toggle="tab" role="tab">Data</a>
184 <li class="nav-item">
185 <a class="nav-link" href="#navigation" data-toggle="tab" role="tab">Navigation</a>
187 <li class="nav-item">
188 <a class="nav-link" href="#lights" data-toggle="tab" role="tab">Lights</a>
192 <div class="tab-content">
193 <div id="data" class="tab-pane active" role="tabpanel">
195 <div id="power" class="col-auto">
197 <label>Voltage:</label>
198 <div class="input-group">
199 <input type=text name="voltage" class="form-control" readonly>
200 <div class="input-group-append">
201 <span class="input-group-text">V</span>
204 <label>Current:</label>
205 <div class="input-group">
206 <input type=text name="current" class="form-control" readonly>
207 <div class="input-group-append">
208 <span class="input-group-text">A</span>
212 <div id="sensors" class="col-auto">
214 <label>Light:</label>
215 <div class="input-group">
216 <input type=text name="light" class="form-control" readonly>
217 <div class="input-group-append">
218 <span class="input-group-text">lx</span>
221 <label>Temperature:</label>
222 <div class="input-group">
223 <input type=text name="temp" class="form-control" readonly>
224 <div class="input-group-append">
225 <span class="input-group-text">℃</span>
228 <label>Humidity:</label>
229 <div class="input-group">
230 <input type=text name="humidity" class="form-control" readonly>
231 <div class="input-group-append">
232 <span class="input-group-text">%</span>
235 <label>Pressure:</label>
236 <div class="input-group">
237 <input type=text name="pressure" class="form-control" readonly>
238 <div class="input-group-append">
239 <span class="input-group-text">kPa</span>
243 <input type=text name="co" class="form-control" readonly>
247 <div id="navigation" class="tab-pane" role="tabpanel">
248 <div id="pose"></div>
250 <div id="speed-label"></div>
251 <div id="speed-slider"></div>
253 <div id="lights" class="tab-pane" role="tabpanel">
255 <div class="col-md-2 offset-md-1" >
256 <div class="d-flex justify-content-center">
257 <input class="led_color" type="hidden" name="[0]"/>
258 <input class="led_color" type="hidden" name="[1]"/>
259 <input class="led_color" type="hidden" name="[2]"/>
260 <input class="led_color" type="hidden" name="[3]"/>
263 <div class="row wt-icon">
264 <div class="col-md-2 align-self-center bottom-leds">
265 <input class="led_color" type="hidden" name="[14]"/>
266 <input class="led_color" type="hidden" name="[15]"/>
268 <div class="col-md-8">
269 <div class="d-flex justify-content-center top-leds">
270 <input class="led_color" type="hidden" name="[7]"/>
271 <input class="led_color" type="hidden" name="[6]"/>
272 <input class="led_color" type="hidden" name="[5]"/>
273 <input class="led_color" type="hidden" name="[4]"/>
276 <div class="col-md-2 align-self-center bottom-leds">
277 <input class="led_color" type="hidden" name="[13]"/>
278 <input class="led_color" type="hidden" name="[12]"/>
282 <div class="d-flex justify-content-center">
283 <input class="led_color" type="hidden" name="[8]"/>
284 <input class="led_color" type="hidden" name="[9]"/>
285 <input class="led_color" type="hidden" name="[10]"/>
286 <input class="led_color" type="hidden" name="[11]"/>
289 <div class="col-md-3 offset-md-1">
290 <div class="form-group row">
291 <label class="col-sm-2 col-form-label">Alle</label>
292 <div class="col-sm-10">
293 <input class="led_color" type="text" name="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]" class="form-control"/>
296 <div class="form-group row">
297 <label class="col-sm-2 col-form-label">Front</label>
298 <div class="col-sm-10">
299 <input class="led_color" type="text" name="[0, 1, 2, 3]" class="form-control"/>
302 <div class="form-group row">
303 <label class="col-sm-2 col-form-label">Aft</label>
304 <div class="col-sm-10">
305 <input class="led_color" type="text" name="[8, 9, 10, 11]" class="form-control"/>
308 <div class="form-group row">
309 <label class="col-sm-2 col-form-label">Top</label>
310 <div class="col-sm-10">
311 <input class="led_color" type="text" name="[4, 5, 6, 7]" class="form-control"/>
314 <div class="form-group row">
315 <label class="col-sm-2 col-form-label">Bottom</label>
316 <div class="col-sm-10">
317 <input class="led_color" type="text" name="[12, 13, 14, 15]" class="form-control"/>
325 <script src="assets/javascripts/jquery-3.3.1.min.js"></script>
326 <script src="assets/javascripts/popper.min.js"></script>
327 <script src="assets/javascripts/bootstrap.min.js"></script>
328 <script src="assets/javascripts/jquery-ui.min.js"></script>
329 <script src="assets/javascripts/easeljs.min.js"></script>
330 <script src="assets/javascripts/eventemitter2.js"></script>
331 <script src="assets/javascripts/roslib.js"></script>
332 <script src="assets/javascripts/ros2d.js"></script>
333 <script src="assets/javascripts/nav2d.js"></script>
334 <script src="assets/javascripts/keyboardteleop.js"></script>
335 <script src="assets/javascripts/jquery.minicolors.js"></script>