Programación de Drones
Vehículos Aéreos No Tripulados
Presentación• Carlos Toxtli Hernández• Desarrollador multiplataforma• 13 años de experiencia.
UAV• Un vehículo aéreo no tripulado, UAV por siglas en
inglés (Unmanned Aerial Vehicle), o sistema aéreo no tripulado, UAS (Unmanned Aerial System), conocido en castellano por sus siglas como VANT o drone, es una aeronave que vuela sin tripulación humana a bordo.
No confundir con naves controladas a distancia• Las Aeronaves Radio controladas o Aeronaves
R/C, no presentan ningún tipo de autonomía, ejemplo: Los helicópteros controlados a control remoto.
• Los Drones tiene la capacidad de ser autónomos y pueden despegar, volar y aterrizar automáticamente.
Drones repartidores de pizza
• http://www.youtube.com/watch?v=ZDXuGQRpvs4
Drones para uso comercial
• En Estados Unidos se considera ilegal el uso comercial de aviones no tripulados y se espera en 2015 se regularice.
Arduplane• Cuentan con alas y hélices.
http://www.youtube.com/watch?v=DdC77fH1xAw
Multicopters
Ejemplo• http://www.youtube.com/watch?v=uVNtE6LMD2o• http://www.youtube.com/watch?v=8IItm9vqW88
Como conectarse
Como controlarlo
Marcas
Imprime tu Dronehttp://www.thingiverse.com/thing:129855
Parrot AR Drone
Placa madre
Duración batería• La incluida dura 9 minutos• La extendida 15 minutos• Las extendidas (de venta en internet) hasta 24
minutos.
Clips y seguros
Pinzas sujetadoras para carga
Base para cargar un objeto
Helices
Engraneshttp://www.thingiverse.com/thing:21342
Impresoras 3d comerciales
Impresoras 3D armables
Software Repetier para imprimirlas
Programación• Principales lenguajes en los que se programa.• C• C#• Objective C• Javascript• Java
Conexión• Para conectarse es por medio de la red Wifi a la
red llamada ardrone2_SERIE• Es posible conectarse vía telnet al dispositivo
Descarga del SDK• Sitio web• https://projects.ardrone.org/projects/show/ardrone
-api
Install node.jsNodejs.org
Ejemplo de código
var arDrone = require('ar-drone');var client = arDrone.createClient();client.takeoff();clientafter(5000, function() {this.clockwise(0.5);}).after(3000, function() {this.animate('flipLeft', 15);}).after(1000, function() {this.stop();this.land();});
Ejecutar el programa
Obtener imágenes• var arDrone = require('ar-drone');• var client = arDrone.createClient();• var pngStream = client.getPngStream();• pngStream.on('data', getPngStream);• var videoStream = client.getVideoStream();• videoStream.on('data', getVideoStream);
• client.on('navdata', getNavData);
• function getPngStream(data)• {• console.dir('Imagen PNG');• console.dir(data);• }
Obtener video y datos• function getVideoStream(data)• {• console.dir('Secuencia de video');• console.dir(data);• }
• function getNavData(data)• {• if(data.droneState.emergencyLanding)• {• console.dir('Ups se atoró');• }• }
Usar OpenCV para la visión
• OpenCV es el framework mas popular para procesar imágenes y analizarlas.
• Para instalar la versión para Node.js es de la siguiente forma.
• npm install opencv
Datos de vuelo• { header: 1432778632,• droneState: • { flying: 0,• videoEnabled: 0,• visionEnabled: 1,• controlAlgorithm: 0,• altitudeControlAlgorithm: 1,• startButtonState: 0,• controlCommandAck: 1,• cameraReady: 1,• travellingEnabled: 0,• usbReady: 1,• navdataDemo: 1,• navdataBootstrap: 0,• motorProblem: 0,• communicationLost: 0,• softwareFault: 0,• lowBattery: 0,• userEmergencyLanding: 0,• timerElapsed: 0,• MagnometerNeedsCalibration: 0,• anglesOutOfRange: 0,• tooMuchWind: 0,• ultrasonicSensorDeaf: 0,• cutoutDetected: 0,• picVersionNumberOk: 1,• atCodecThreadOn: 1,• navdataThreadOn: 1,• videoThreadOn: 1,• acquisitionThreadOn: 1,• controlWatchdogDelay: 0,• adcWatchdogDelay: 0,• comWatchdogProblem: 0,• emergencyLanding: 0 },• sequenceNumber: 22318,• visionFlag: 0,•
demo: { controlState: 'CTRL_LANDED', flyState: 'FLYING_OK', batteryPercentage: 58, rotation: { frontBack: 1.293, pitch: 1.293, theta: 1.293, y: 1.293, leftRight: 0.829, roll: 0.829, phi: 0.829, x: 0.829, clockwise: -105.603, yaw: -105.603, psi: -105.603, z: -105.603 }, frontBackDegrees: 1.293, leftRightDegrees: 0.829, clockwiseDegrees: -105.603, altitude: 0, altitudeMeters: 0, velocity: { x: 0, y: 0, z: 0 }, xVelocity: 0, yVelocity: 0, zVelocity: 0, frameIndex: 0, detection: { camera: [Object], tagIndex: 0 }, drone: { camera: [Object] } },
Mas y más datos• pwm: • { motors: [ 0, 0, 0, 0 ],• satMotors: [ 255, 255, 255, 255 ],• gazFeedForward: 340.91461181640625,• gazAltitude: -25.660755157470703,• altitudeIntegral: 0,• vzRef: -800,• uPitch: 7,• uRoll: -34,• uYaw: -14,• yawUI: -25.660755157470703,• uPitchPlanif: 0,• uRollPlanif: 0,• uYawPlanif: 0,• uGazPlanif: 0.00017481952090747654,• motorCurrents: [ 0, 0, 0, 0 ],• altitudeProp: 0,• altitudeDer: -25.62909698486328 },• visionDetect: • { nbDetected: 0,• type: [ 0, 0, 0, 0 ],• xc: [ 0, 0, 0, 0 ],• yc: [ 0, 0, 0, 0 ],• width: [ 0, 0, 0, 0 ],• height: [ 0, 0, 0, 0 ],• dist: [ 0, 0, 0, 0 ],• orientationAngle: [ 0, 0, 0, 0 ],• rotation: [ [Object], [Object], [Object], [Object] ],• translation: [ [Object], [Object], [Object], [Object] ],• cameraSource: [ 0, 0, 0, 0 ] },• games: { counters: { doubleTap: 0, finishLine: 0 } },• magneto: • { mx: -29,• my: -21,• mz: 47,• raw: { x: 72.59765625, y: 100.93359375, z: -169.08984375 },• rectified: • { x: -121.61617279052734,• y: 253.83740234375,• z: 347.0871276855469 },• offset: • { x: 202.01583862304688,• y: -157.86355590820312,• z: -509.63116455078125 },• heading: • { unwrapped: -104.56443786621094,• gyroUnwrapped: 0,• fusionUnwrapped: -105.60394287109375 },• ok: 1,• state: 257,• radius: 4.649235341397054e+35,• error: { mean: -2.1708750025476598e-23, variance: 56699894794027010 } },• • √ hdvideoStream: • { hdvideoState: 256,• storageFifo: { nbPackets: 1, size: 38 },• usbkey: { size: 3851560, freespace: 2559462, remainingTime: 4998 },• frameNumber: 1313 },
wifi: { linkQuality: 1 }, gps: { latitude: 25.663727, longitude: -100.2799144, elevation: 516.93, hdop: 1, data_available: 7, unk_0: [ 1, 0, 0, 0, 0, 0, 0, 0 ], lat0: 25.6637006, lon0: -100.2798947, lat_fuse: 25.663731514862402, lon_fuse: -100.27991142172012, gps_state: 1, unk_1: [ 0,0 ], vdop: 0, pdop: 0, speed: 0.11999999731779099, last_frame_timestamp: 1500.13, degree: 189.77999877929688, degree_mag: 0, unk_2: [ 215, 163, 136, 64, 10, 215, 35, 61, 0, 0, 240, 65, 8, 0, 0, 0 ], channels: [ [Object] ], gps_plugged: 1, unk_3: [ 136, 0,0 ], gps_time: 0, week: 0, gps_fix: 0, num_satellites: 0, unk_4: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ned_vel_c0: 0, ned_vel_c1: 0, ned_vel_c2: 0, pos_accur_c0: 0, pos_accur_c1: 0, pos_accur_c2: 0, speed_accur: 0, time_accur: 0, unk_5: [ 0, 0,0 ],temperature: 0,pressure: 0 },}
Funciones• arDrone.createClient([options])• client.createREPL()• client.getPngStream()• client.getVideoStream()• client.takeoff(callback) • client.land(callback)• client.up(speed) / client.down(speed)• client.clockwise(speed) / client.counterClockwise(speed)• client.front(speed) / client.back(speed)• client.left(speed) / client.right(speed)• client.stop()• client.calibrate(device_num)• client.config(key, value, callback)• client.disableEmergency()• arDrone.createUdpControl()
La parte divertida• client.animate(animation, duration)• ['phiM30Deg', 'phi30Deg', 'thetaM30Deg', 'theta30Deg',
'theta20degYaw200deg’,'theta20degYawM200deg', 'turnaround', 'turnaroundGodown', 'yawShake’,'yawDance', 'phiDance', 'thetaDance', 'vzDance', 'wave', 'phiThetaMixed’,'doublePhiThetaMixed', 'flipAhead', 'flipBehind', 'flipLeft', 'flipRight’]
• client.animateLeds(animation, hz, duration)• ['blinkGreenRed', 'blinkGreen', 'blinkRed', 'blinkOrange',
'snakeGreenRed’,'fire', 'standard', 'red', 'green', 'redSnake', 'blank', 'rightMissile’,'leftMissile', 'doubleMissile', 'frontLeftGreenOthersRed’,'frontRightGreenOthersRed', 'rearRightGreenOthersRed’,'rearLeftGreenOthersRed', 'leftGreenRightRed', 'leftRedRightGreen’,'blinkStandard']
Mezcla arduino con AR Drone
https://gist.github.com/maxogden/4152815
Compartir en un servidor la cámara del Drone
• https://github.com/Soarez/ar-drone-png-stream
Controlar desde tu navegador
• https://github.com/functino/drone-browser
Detectar caras con Drone• var arDrone = require('ar-drone');• var cv = require('opencv');• var http = require('http');• var fs = require('fs');
• console.log('Connecting png stream ...');
• var pngStream = arDrone.createPngStream();• //var stream = arDrone.createUdpNavdataStream();• var client = arDrone.createClient();• var processingImage = false;• var lastPng;• var face_cascade = new cv.CascadeClassifier('node_modules/opencv/data/haarcascade_frontalface_alt2.xml');• var navData;• var flying = false;• var startTime = new Date().getTime();• var log = function(s){• var time = ( ( new Date().getTime() - startTime ) / 1000 ).toFixed(2);
• console.log(time+" \t"+s);• }• pngStream• .on('error', console.log)• .on('data', function(pngBuffer) {• //console.log("got image");• lastPng = pngBuffer;• });
• var faceInterval = setInterval( detectFaces, 150);
• client.takeoff();• client.after(5000,function(){ • log("going up");• this.up(1);• }).after(1000,function(){ • log("stopping");• this.stop(); • flying = true;• });
• client.after(60000, function() {• flying = false;• this.stop();• this.land();• });
• client.on('navdata', function(navdata) {• navData = navdata;• })
• var server = http.createServer(function(req, res) {• if (!lastPng) {• res.writeHead(503);• res.end('Did not receive any png data yet.');• return;• }
• res.writeHead(200, {'Content-Type': 'image/png'});• res.end(lastPng);• });
• server.listen(8080, function() {• console.log('Serving latest png on port 8080 ...');• });
• var detectFaces = function(){ • if( ! flying ) return;• if( ( ! processingImage ) && lastPng )• {• processingImage = true;• cv.readImage( lastPng, function(err, im) {• var opts = {};• face_cascade.detectMultiScale(im, function(err, faces) {
• var face;• var biggestFace;
• for(var k = 0; k < faces.length; k++) {
• face = faces[k];• if( !biggestFace || biggestFace.width < face.width ) biggestFace = face;
• //im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], [0, 255, 0], 2);• }
• if( biggestFace ){• face = biggestFace;• console.log( face.x, face.y, face.width, face.height, im.width(), im.height() );
• face.centerX = face.x + face.width * 0.5;• face.centerY = face.y + face.height * 0.5;
• var centerX = im.width() * 0.5;• var centerY = im.height() * 0.5;
• var heightAmount = -( face.centerY - centerY ) / centerY;• var turnAmount = -( face.centerX - centerX ) / centerX;
• turnAmount = Math.min( 1, turnAmount );• turnAmount = Math.max( -1, turnAmount );
• log( turnAmount + " " + heightAmount );
• //heightAmount = Math.min( 1, heightAmount );• //heightAmount = Math.max( -1, heightAmount );• heightAmount = 0;
• if( Math.abs( turnAmount ) > Math.abs( heightAmount ) ){• log( "turning "+turnAmount );• if( turnAmount < 0 ) client.clockwise( Math.abs( turnAmount ) );• else client.counterClockwise( turnAmount );• setTimeout(function(){• log("stopping turn");• client.clockwise(0);• //this.stop();• },100);• }• else {• log( "going vertical "+heightAmount );• if( heightAmount < 0 ) client.down( heightAmount );• else client.up( heightAmount );• setTimeout(function(){• log("stopping altitude change");• • client.up(0);
• },50);
• }
• }
• processingImage = false;• //im.save('/tmp/salida.png');
• }, opts.scale, opts.neighbors• , opts.min && opts.min[0], opts.min && opts.min[1]);• • });• };• };
Mexicanos y Drones Uncommon Air
Projects• ¿Cuál fue su experiencia incursionando con Drones?• Comenzamos con la información de internet e
investigando en foros, y los conocimientos de aeronáutica y biónica fueron importantes.
• Hemos desarrollado, cuadricópteros, hexa y octocópteros con un fuselaje de fibra de carbono con capacidad de carga que dobla al de la competencia.
• La filosofía DIY ha hecho posible que la implementación de innovaciones no requiera de meses de análisis, no estás sólo, generas y compartes conocimiento
Experiencia de Uncommon Air
Projects• En México apenas comenzamos el acercamiento con
clientes, la mayoría tiene necesidades básicas que se cumplen con un drone que sea fácil de controlar y les permita visualizar las alturas
• El principal reto que vemos en el mercado es competir con empresas que ofrecen precios muy bajos con calidad desechable
• Aunque muchos lo ven con ojos de invasión de privacidad, nosotros creemos que la expansión de esta tecnología a sectores populares representa el empoderamiento del usuario, de multitudes, el no ser sólo espectador sino tener una herramienta para conocer, actuar, es como si te dieran el poder de volar, qué harías con él?... Al contrario de la creencia, ofrecemos tener un poco de libertad
Mexicanos y Drones Jordi Muñoz
• Co-Founder y CTO de 3DRobotics• Ganador al Premio Estudiante Emprendedor 2013• ¿Cuál es su experiencia en UAVs ?• Yo inicie en DIY drones, de hecho yo invente el
Ardupilot (lo que es hoy el APM), la ultima versión que yo hice personalmente fue el APM 2.5.
Ligas recomendadas• http://3drobotics.com/• https://projects.ardrone.org/projects/show/ardrone
-api
Gracias• La presentación estará publicada en:
• http://www.facebook.com/carlos.toxtli
Recommended