Está en la página 1de 60

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 Drone
http://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
Engranes
http://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
Nodejs.org
Install node.js
Ejemplo de código
var arDrone = require('ar-drone');
var client = arDrone.createClient();
client.takeoff();
client
after(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
• { header: 1432778632,
Datos de vuelo
demo:
• droneState:
{ controlState: 'CTRL_LANDED',
• { flying: 0, flyState: 'FLYING_OK',
• videoEnabled: 0, batteryPercentage: 58,
• visionEnabled: 1, rotation:
• controlAlgorithm: 0, { frontBack: 1.293,
pitch: 1.293,
• altitudeControlAlgorithm: 1,
theta: 1.293,
• startButtonState: 0, y: 1.293,
• controlCommandAck: 1, leftRight: 0.829,
• cameraReady: 1, roll: 0.829,
• travellingEnabled: 0, phi: 0.829,
x: 0.829,
• usbReady: 1,
clockwise: -105.603,
• navdataDemo: 1, yaw: -105.603,
• navdataBootstrap: 0, psi: -105.603,
• motorProblem: 0, z: -105.603 },
• communicationLost: 0, frontBackDegrees: 1.293,
leftRightDegrees: 0.829,
• softwareFault: 0,
clockwiseDegrees: -105.603,
• lowBattery: 0, altitude: 0,
• userEmergencyLanding: 0, altitudeMeters: 0,
• timerElapsed: 0, velocity: { x: 0, y: 0, z: 0 },
• MagnometerNeedsCalibration: 0, xVelocity: 0,
yVelocity: 0,
• anglesOutOfRange: 0,
zVelocity: 0,
• tooMuchWind: 0, frameIndex: 0,
• ultrasonicSensorDeaf: 0, detection: { camera: [Object], tagIndex: 0 },
• cutoutDetected: 0, drone: { camera: [Object] } },
• picVersionNumberOk: 1,
• atCodecThreadOn: 1,
• navdataThreadOn: 1,
• videoThreadOn: 1,
• acquisitionThreadOn: 1,
• controlWatchdogDelay: 0,
• adcWatchdogDelay: 0,
• comWatchdogProblem: 0,
• emergencyLanding: 0 },
• sequenceNumber: 22318,
• visionFlag: 0,

Mas y más datos
• pwm: wifi: { linkQuality: 1 },
• { motors: [ 0, 0, 0, 0 ], gps:
• satMotors: [ 255, 255, 255, 255 ],
• gazFeedForward: 340.91461181640625, { latitude: 25.663727,
• gazAltitude: -25.660755157470703, longitude: -100.2799144,
• altitudeIntegral: 0, elevation: 516.93,
• vzRef: -800,
• uPitch: 7, hdop: 1,
• uRoll: -34, data_available: 7,
• uYaw: -14, unk_0: [ 1, 0, 0, 0, 0, 0, 0, 0 ],
• yawUI: -25.660755157470703,
• uPitchPlanif: 0, lat0: 25.6637006,
• uRollPlanif: 0, lon0: -100.2798947,
• uYawPlanif: 0, lat_fuse: 25.663731514862402,
• uGazPlanif: 0.00017481952090747654,
• motorCurrents: [ 0, 0, 0, 0 ], lon_fuse: -100.27991142172012,
• altitudeProp: 0, gps_state: 1,
• altitudeDer: -25.62909698486328 }, unk_1:
• visionDetect:
• { nbDetected: 0, [ 0,
• type: [ 0, 0, 0, 0 ], 0 ],
• xc: [ 0, 0, 0, 0 ], vdop: 0,
• yc: [ 0, 0, 0, 0 ],
• width: [ 0, 0, 0, 0 ], pdop: 0,
• height: [ 0, 0, 0, 0 ], speed: 0.11999999731779099,
• dist: [ 0, 0, 0, 0 ], last_frame_timestamp: 1500.13,
• orientationAngle: [ 0, 0, 0, 0 ],
• rotation: [ [Object], [Object], [Object], [Object] ], degree: 189.77999877929688,
• translation: [ [Object], [Object], [Object], [Object] ], degree_mag: 0,
• cameraSource: [ 0, 0, 0, 0 ] }, unk_2: [
• games: { counters: { doubleTap: 0, finishLine: 0 } },
• magneto: 215, 163, 136, 64, 10, 215, 35, 61, 0, 0, 240, 65, 8, 0, 0, 0 ],
• { mx: -29, channels:
• my: -21, [ [Object] ],
• mz: 47,
• raw: { x: 72.59765625, y: 100.93359375, z: -169.08984375 }, gps_plugged: 1,
• rectified: unk_3:
• { x: -121.61617279052734, [ 136,
• y: 253.83740234375,
• z: 347.0871276855469 }, 0,
• offset: 0 ],
• { x: 202.01583862304688, gps_time: 0,
• y: -157.86355590820312,
• z: -509.63116455078125 }, week: 0,
• heading: gps_fix: 0,
• { unwrapped: -104.56443786621094, num_satellites: 0,
• gyroUnwrapped: 0,
• fusionUnwrapped: -105.60394287109375 }, unk_4: [
• ok: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
• state: 257, ned_vel_c0: 0,
• radius: 4.649235341397054e+35,
• error: { mean: -2.1708750025476598e-23, variance: 56699894794027010 } }, ned_vel_c1: 0,
• ned_vel_c2: 0,
• √ hdvideoStream: pos_accur_c0: 0,
• { hdvideoState: 256,
• storageFifo: { nbPackets: 1, size: 38 }, pos_accur_c1: 0,
• usbkey: { size: 3851560, freespace: 2559462, remainingTime: 4998 }, pos_accur_c2: 0,
• frameNumber: 1313 }, 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

También podría gustarte