Merge pull request #185 from ciandt-dev/master
Robot example integrating leap motion and ARDrone
This commit is contained in:
commit
736fe03e88
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* leap_ardrone.js
|
||||
*
|
||||
* Written by Giuliano Sposito and Fábio Uechi
|
||||
* Copyright (c) 2013-2014 CI&T Software
|
||||
* Licensed under the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
Cylon = require('cylon');
|
||||
|
||||
// constants
|
||||
var lastS = 0,
|
||||
handStartPosition = [],
|
||||
handStartDirection = [],
|
||||
UP_CONTROL_THRESHOLD = 50,
|
||||
UP_SPEED_FACTOR = 0.01,
|
||||
CIRCLE_THRESHOLD = 1.5,
|
||||
DIRECTION_THRESHOLD = 0.25,
|
||||
DIRECTION_SPEED_FACTOR = 0.05,
|
||||
TURN_SPEED = 0.5,
|
||||
TURN_TRESHOLD = 0.2,
|
||||
TURN_SPEED_FACTOR = 2.0;
|
||||
|
||||
Cylon.robot({
|
||||
|
||||
connections: [
|
||||
{ name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437' },
|
||||
{ name: 'ardrone', adaptor: 'ardrone', port: '192.168.1.1' },
|
||||
{ name: 'keyboard', adaptor: 'keyboard' }
|
||||
],
|
||||
|
||||
devices: [
|
||||
{ name: 'drone', driver: 'ardrone', connection:'ardrone' },
|
||||
{ name: 'leapmotion', driver: 'leapmotion', connection:'leapmotion' },
|
||||
{ name: 'keyboard', driver: 'keyboard', connection:'keyboard'}
|
||||
],
|
||||
|
||||
work: function(my) {
|
||||
|
||||
// HAND
|
||||
my.leapmotion.on('hand', function(hand) {
|
||||
|
||||
// detects open hand ==> reset
|
||||
if (hand.s>1.5 && lastS<=1.5) {
|
||||
handStartPosition = hand.palmPosition;
|
||||
handStartDirection = hand.direction;
|
||||
};
|
||||
|
||||
// TURNS
|
||||
if(hand.s>1.5 && Math.abs(handStartDirection[0]-hand.direction[0]) > TURN_TRESHOLD ) {
|
||||
var signal = handStartDirection[0]-hand.direction[0];
|
||||
var value = (Math.abs(handStartDirection[0]-hand.direction[0])-TURN_TRESHOLD)*TURN_SPEED_FACTOR;
|
||||
if (signal>0){
|
||||
my.drone.counterClockwise(value);
|
||||
}
|
||||
|
||||
if (signal<0){
|
||||
my.drone.clockwise(value);
|
||||
}
|
||||
}
|
||||
|
||||
// UP and DOWN
|
||||
if (hand.s>1.5 && Math.abs(hand.palmPosition[1]-handStartPosition[1]) > UP_CONTROL_THRESHOLD) {
|
||||
var signal = (hand.palmPosition[1]-handStartPosition[1]) >= 0 ? 1 : -1;
|
||||
var value = Math.round(Math.abs((hand.palmPosition[1]-handStartPosition[1]))-UP_CONTROL_THRESHOLD) * UP_SPEED_FACTOR;
|
||||
|
||||
if (signal>0) {
|
||||
my.drone.up(value);
|
||||
};
|
||||
|
||||
if (signal<0) {
|
||||
my.drone.down(value);
|
||||
}
|
||||
}
|
||||
|
||||
// DIRECTION FRONT/BACK
|
||||
if (hand.s>1.5 && (Math.abs(hand.palmNormal[2])>DIRECTION_THRESHOLD)) {
|
||||
if (hand.palmNormal[2]>0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[2]*10 + DIRECTION_THRESHOLD )*DIRECTION_SPEED_FACTOR);
|
||||
my.drone.forward( value );
|
||||
};
|
||||
|
||||
if (hand.palmNormal[2]<0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[2]*10 - DIRECTION_THRESHOLD )*DIRECTION_SPEED_FACTOR);
|
||||
my.drone.back( value );
|
||||
};
|
||||
}
|
||||
|
||||
// DIRECTION LEFT/RIGHT
|
||||
if (hand.s>1.5 && (Math.abs(hand.palmNormal[0])>DIRECTION_THRESHOLD)) {
|
||||
if (hand.palmNormal[0]>0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[0]*10 + DIRECTION_THRESHOLD )*DIRECTION_SPEED_FACTOR);
|
||||
my.drone.left( value );
|
||||
};
|
||||
|
||||
if (hand.palmNormal[0]<0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[0]*10 - DIRECTION_THRESHOLD )*DIRECTION_SPEED_FACTOR);
|
||||
my.drone.right( value );
|
||||
};
|
||||
}
|
||||
|
||||
// AUTO FREEZE
|
||||
if ( hand.s>1.5 && // open hand
|
||||
(Math.abs(hand.palmNormal[0])<DIRECTION_THRESHOLD) && // within left/right threshold
|
||||
(Math.abs(hand.palmNormal[2])<DIRECTION_THRESHOLD) && // within forward/back threshold
|
||||
Math.abs(hand.palmPosition[1]-handStartPosition[1]) < UP_CONTROL_THRESHOLD && // within up/down threshold
|
||||
Math.abs(handStartDirection[0]-hand.direction[0]) < TURN_TRESHOLD) // within turn threshold
|
||||
{
|
||||
my.drone.stop();
|
||||
}
|
||||
|
||||
// COMMAND FREEZE
|
||||
if (hand.s<=1.5 && lastS > 1.5) { // closed hand
|
||||
my.drone.stop();
|
||||
}
|
||||
|
||||
lastS = hand.s;
|
||||
|
||||
});// end hand
|
||||
|
||||
// Gestures
|
||||
my.leapmotion.on('gesture', function(gesture) {
|
||||
if (gesture.type=='circle' && gesture.state=='stop' && gesture.progress > CIRCLE_THRESHOLD ){
|
||||
if (gesture.normal[2] < 0) {
|
||||
my.drone.takeoff();
|
||||
};
|
||||
|
||||
if (gesture.normal[2] > 0) {
|
||||
my.drone.land();
|
||||
}
|
||||
}
|
||||
|
||||
// EMERGENCE STOP
|
||||
if (gesture.type=='keyTap' || gesture.type=='screenTap') {
|
||||
my.drone.stop();
|
||||
};
|
||||
}); // end gesture
|
||||
|
||||
//KEYBOARD
|
||||
my.keyboard.on('right', function(key) {
|
||||
my.drone.rightFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('left', function(key) {
|
||||
my.drone.leftFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('up', function(key) {
|
||||
my.drone.frontFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('down', function(key) {
|
||||
my.drone.backFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('w', function(key) {
|
||||
my.drone.wave();
|
||||
});
|
||||
|
||||
my.keyboard.on('s', function(key) {
|
||||
my.drone.stop();
|
||||
});
|
||||
|
||||
my.keyboard.on('l', function(key) {
|
||||
my.drone.land();
|
||||
});
|
||||
|
||||
} // end work
|
||||
}).start();
|
|
@ -0,0 +1,150 @@
|
|||
# Leapmotion Ardrone 2.0
|
||||
|
||||
This example illustrates how to use Leap Motion and the keyboard to control an ARDrone. We basically use one hand to drive the drone (takeoff, land, up, down, etc) and the arrow keys to perform some cool stunts (flips).
|
||||
|
||||
First, let's import Cylon:
|
||||
|
||||
var Cylon = require('../..');
|
||||
|
||||
Now that we have Cylon imported, we can start defining our robot
|
||||
|
||||
Cylon.robot({
|
||||
|
||||
Let's define the connections and devices:
|
||||
|
||||
```
|
||||
connections: [
|
||||
{ name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437' },
|
||||
{ name: 'ardrone', adaptor: 'ardrone', port: '192.168.1.1' },
|
||||
{ name: 'keyboard', adaptor: 'keyboard' }
|
||||
],
|
||||
|
||||
devices: [
|
||||
{ name: 'drone', driver: 'ardrone', connection:'ardrone' },
|
||||
{ name: 'leapmotion', driver: 'leapmotion', connection:'leapmotion' },
|
||||
{ name: 'keyboard', driver: 'keyboard', connection:'keyboard'}
|
||||
],
|
||||
```
|
||||
|
||||
Now that Cylon knows about the necessary hardware we're going to be using, we'll
|
||||
tell it what work we want to do:
|
||||
|
||||
work: function(my) {
|
||||
|
||||
Lets use the circle gesture to take off and land : two rounds clockwise will trigger the takeoff() and counter clockwise will tell the drone to land:
|
||||
|
||||
```
|
||||
my.leapmotion.on('gesture', function(gesture) {
|
||||
if (gesture.type=='circle' && gesture.state=='stop' && gesture.progress > CIRCLE_THRESHOLD ){
|
||||
if (gesture.normal[2] < 0) {
|
||||
my.drone.takeoff();
|
||||
};
|
||||
|
||||
if (gesture.normal[2] > 0) {
|
||||
my.drone.land();
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Whenever we get a 'hand' gesture event from Leap Motion we need to tell ARDrone what to do.
|
||||
|
||||
my.leapmotion.on('hand', function(hand) {
|
||||
|
||||
In case we turn our hand to the right or left we want the drone to rotate clockwise or counter clockwise respectively:
|
||||
|
||||
```
|
||||
if(hand.s>1.5 && Math.abs(handStartDirection[0]-hand.direction[0]) > TURN_TRESHOLD ) {
|
||||
var signal = handStartDirection[0]-hand.direction[0];
|
||||
var value = (Math.abs(handStartDirection[0]-hand.direction[0])-TURN_TRESHOLD) * TURN_SPEED_FACTOR;
|
||||
if (signal>0){
|
||||
my.drone.counterClockwise(value);
|
||||
}
|
||||
|
||||
if (signal<0){
|
||||
my.drone.clockwise(value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In case we raise our hand up or lower it down we tell the drone to go up or down respectively:
|
||||
|
||||
```
|
||||
if (hand.s>1.5 && Math.abs(hand.palmPosition[1]-handStartPosition[1]) > UP_CONTROL_THRESHOLD) {
|
||||
var signal = (hand.palmPosition[1]-handStartPosition[1]) >= 0 ? 1 : -1;
|
||||
var value = Math.round(Math.abs((hand.palmPosition[1]-handStartPosition[1]))-UP_CONTROL_THRESHOLD) * UP_SPEED_FACTOR;
|
||||
|
||||
if (signal>0) {
|
||||
my.drone.up(value);
|
||||
};
|
||||
|
||||
if (signal<0) {
|
||||
my.drone.down(value);
|
||||
}
|
||||
}
|
||||
```
|
||||
In order to move the drone forward, backward, left or right we need to detect the hand inclination. Imagine your hand is the drone and lean it towards the direction we want it to move.
|
||||
|
||||
```
|
||||
if (hand.s>1.5 && (Math.abs(hand.palmNormal[2])>DIRECTION_THRESHOLD)) {
|
||||
if (hand.palmNormal[2]>0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[2] * 10 + DIRECTION_THRESHOLD ) * DIRECTION_SPEED_FACTOR);
|
||||
my.drone.forward( value );
|
||||
};
|
||||
|
||||
if (hand.palmNormal[2]<0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[2] * 10 - DIRECTION_THRESHOLD ) * DIRECTION_SPEED_FACTOR);
|
||||
my.drone.back( value );
|
||||
};
|
||||
}
|
||||
|
||||
if (hand.s>1.5 && (Math.abs(hand.palmNormal[0])>DIRECTION_THRESHOLD)) {
|
||||
if (hand.palmNormal[0]>0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[0] * 10 + DIRECTION_THRESHOLD ) * DIRECTION_SPEED_FACTOR);
|
||||
my.drone.left( value );
|
||||
};
|
||||
|
||||
if (hand.palmNormal[0]<0) {
|
||||
var value = Math.abs(Math.round( hand.palmNormal[0] * 10 - DIRECTION_THRESHOLD ) * DIRECTION_SPEED_FACTOR);
|
||||
my.drone.right( value );
|
||||
};
|
||||
}
|
||||
```
|
||||
Whenever we close our hand we tell the drone no stop:
|
||||
|
||||
```
|
||||
if (hand.s<=1.5 && lastS > 1.5) { // closed hand
|
||||
my.drone.stop();
|
||||
}
|
||||
|
||||
});// end hand
|
||||
```
|
||||
|
||||
And finally lets use the arrow keys to tell the drone to do some cool stunts:
|
||||
|
||||
```
|
||||
my.keyboard.on('right', function(key) {
|
||||
my.drone.rightFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('left', function(key) {
|
||||
my.drone.leftFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('up', function(key) {
|
||||
my.drone.frontFlip();
|
||||
});
|
||||
|
||||
my.keyboard.on('down', function(key) {
|
||||
my.drone.backFlip();
|
||||
});
|
||||
|
||||
} //end work
|
||||
```
|
||||
|
||||
Now that our robot knows what work to do, and the work it will be doing that
|
||||
hardware with, we can start it:
|
||||
|
||||
```
|
||||
}).start();
|
||||
```
|
Loading…
Reference in New Issue