node.js and the AR.Drone: building a real-time dashboard using socket.io

13,466 views

Published on

How to control an AR.Drone and show data from its sensors on a real-time dashboard using node.js, socket.io and rickshaw.js.

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,466
On SlideShare
0
From Embeds
0
Number of Embeds
52
Actions
Shares
0
Downloads
68
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

node.js and the AR.Drone: building a real-time dashboard using socket.io

  1. 1. node.js & AR.Drone#njugbe meetup 3 - 13 March 2013@stevenbeeckman
  2. 2. AR.Drone? 2 ith ’s! w ra wifi controlled quadricopter e am
  3. 3. node.js packages besar-drone tm ainthttps://npmjs.org/package/ar-drone aine dardronehttps://npmjs.org/package/ardroneardrone-webhttps://npmjs.org/package/ardrone-web
  4. 4. hello worldvar arDrone = require(ar-drone);var client = arDrone.createClient();client.animateLeds(blinkGreenRed, 5, 10);client.on(navdata, console.log);
  5. 5. Real-time Dashboard?In the browser?
  6. 6. Real-time DashboardExpress.js for the serverSocket.io for push to the browser (web sockets!)Client-side: jQuery Knob Rickshaw.js
  7. 7. Schematics AR.Drone’s wifi network browser - http://localhost:3000/ socket.io http node fly.js node rtdashboard.js MacBook
  8. 8. fly.js var arDrone = require(ar-drone); //RTFM for flying commands etc var http = require(http); var client = arDrone.createClient(); var options = {host: 127.0.0.1’, port: 3000, path: /api/raw, method: POST}; var counter = 0; // naïve sampling counter client.config(general:navdata_demo, FALSE); // get all the data from the sensors client.takeoff(); client .after(3000, function() { this.down(0.1); }) .after(1000, function(){ this.stop(); this.land(); });
  9. 9. fly.js - logging to dashboard client.on(navdata, function(data){ // on receiving navdata, send data to dashboard counter = counter + 1; if(counter > 50){ // only send every 50th data header counter = 0; var raw_data_header = new Object(); if(data.rawMeasures && data.demo && data.pwm){ // data not always contains demo & pwm raw_data_header = { header: { time: data.time , sequenceNumber: data.sequenceNumber , flying: data.droneState.flying , batteryMilliVolt: data.rawMeasures.batteryMilliVolt , altitude: data.demo.altitude , velocity: {x: data.demo.xVelocity , y: data.demo.yVelocity , z: data.demo.zVelocity} , throttle: {forward: data.pwm.gazFeedForward , height: data.pwm.gazAltitude} } }; }else{
  10. 10. fly.js - logging to dashboard raw_data_header = { header: { time: data.time , sequenceNumber: data.sequenceNumber , flying: data.droneState.flying , batteryMilliVolt: 0 , altitude: 0 , velocity: {x: 0 , y: 0 , z: 0} , throttle: {forward: 0 , height: 0} } }; }
  11. 11. fly.js - logging to dashboard var data_to_be_sent = JSON.stringify(raw_data_header); var headers = { Content-Type: application/json , Content-Length: data_to_be_sent.length }; options.headers = headers; var req = http.request(options, function(res){ }); req.on(error, function(e){ // per http://nodejs.org/api/http.html#http_http_request_options_callback console.log("Problem with request: " + e.message); }) req.write(data_to_be_sent); req.end(); } });
  12. 12. rtdashboard.js var app = express(); setupApp(); function setupApp(){ ... db = mongoose.createConnection(app.set(db-uri)); db.on(error, console.error.bind(console, Connection error:)); db.once(open, function(){ console.log("Connected to database"); app.use(app.router); setupRoutes(); startServer(); }); }
  13. 13. rtdashboard.js function setupRoutes(){ app.get(/, routes.index); // contains the dashboard app.post(/api/raw, addDb, addAltitude, addSpeed, addHeading, addThrottleVertical, addThrottleHorizontal, addBattery, routes.raw); // receives some navdata from fly.js app.get(*, function(req, res){ console.log("Page not found: " + req.originalUrl); res.render(404); }); } function addDb(req, res, next){ req.db = db; // contains the database next(); } function addAltitude(req, res, next){ req.altitude = altitude; // contains a socket.io namespace object, see startServer() next(); }
  14. 14. rtdashboard.js function startServer(){ server = http.createServer(app); io = io.listen(server); server.listen(app.get(port), function(){ console.log("Express server started."); }); // each sensor gets its own socket.io namespace altitude = io.of(/altitude); speed = io.of(/speed); heading = io.of(/heading); throttle_vertical = io.of(/throttle_vertical); throttle_horizontal = io.of(/throttle_horizontal); battery = io.of(/battery); }
  15. 15. routes/index.js exports.index = function(req, res){ res.render(index, { }); }; exports.raw = function(req, res){ if(req.body.header){ var header = new Object(); header.rawData = req.body.header; // send data to dashboard on socket.io req.altitude.emit(altitude, {value: header.rawData.altitude}); req.throttle_vertical.emit(throttle, {value: header.rawData.throttle.height}); req.throttle_horizontal.emit(throttle, {value: header.rawData.throttle.forward}); req.battery.emit(battery, {value: header.rawData.batteryMilliVolt}) res.json({message: "Success"}); }else{ res.json({message: "No header received."}); } }
  16. 16. views/index.ejs <!DOCTYPE HTML> <html> <head> <title>Real-Time Dashboard</title> <link rel=stylesheet href=/bootstrap/css/bootstrap.min.css /> <link rel="stylesheet" href="/css/rickshaw.min.css"/> <script src="/js/jquery-1.9.1.min.js"></script> <script src="/js/jquery.knob.js"></script> <script src="/js/d3.v2.js"></script> <script src="/js/rickshaw.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> ... <!-- see second next slides --> </script> </head> <body> ... <!-- see next slide --> </body> </html>
  17. 17. views/index.ejs <body> ... <div class="span4"> <h3>Horizontal Throttle</h3> <div class="span2"> <input type="text" id="throttleHorizontal" data-fgColor="#66cc66" data-min="-400" data-max="400" data-cursor=true data-angleOffset=-180 data-width="70" value="0" data-readOnly=true> <!-- jQuery Knob --> </div> <div style="float: left;" id="throttleHorizontal_chart"> <!-- rickshaw graph --> </div> </div> ... </body>
  18. 18. views/index.ejs <script> $(document).ready(function(){ $("#throttle").knob(); $("#throttleHorizontal").knob(); }); var throttleHorizontal = io.connect(http://localhost/throttle_horizontal); // connect to socket.io namespace var throttleHorizontal_data = new Array(); // array for the horizontal throttle data var throttleHorizontal_graph; // see next slide ... </script>
  19. 19. views/index.ejs <script> ... throttleHorizontal.on(throttle, function(data){ $("#throttleHorizontal").val(data.value); $("#throttleHorizontal").trigger("change"); // trigger the knob to redraw itself throttleHorizontal_data.push({x: (new Date()).getTime(), y: parseInt(data.value)}); if(!throttleHorizontal_graph){ //console.log("Altitude graph doesnt yet exist, drawing it for the first and only time."); throttleHorizontal_graph = new Rickshaw.Graph( { element: document.querySelector("#throttleHorizontal_chart"), width: 80, height: 60, renderer: "line", interpolation: "step-after", series: [{ color: #66cc66, data: throttleHorizontal_data }] }); throttleHorizontal_graph.render(); }else{
  20. 20. views/index.ejs <script> ... throttleHorizontal.on(throttle, function(data){ ... }else{ //Throttle graph already exists so just update the data and rerender. throttleHorizontal_graph.series[0].data = throttleHorizontal_data; throttleHorizontal_graph.render(); } }); ... </script>
  21. 21. Fork ithttps://github.com/stevenbeeckman/ardrone-controllerhttps://github.com/stevenbeeckman/ardrone-dashboard
  22. 22. Demo time
  23. 23. Way ahead
  24. 24. Access the videostreamsFront & bottom cameraUse OpenCV for computer vision
  25. 25. Node.js on the AR.Dronehttps://gist.github.com/maxogden/4152815 autonomous AR.Drone! interface with Arduino
  26. 26. Questions?My name is @stevenbeeckman.Thanks for listening.

×