Skip to content

New properties api #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,33 +132,41 @@ events.

#### client.takeoff()

Sets the internal `fly` state to `true`.
Sets `client.flyBit = true`.

#### client.land()

Sets the internal `fly` state to `false`.
Sets `client.flyBit = false`.

#### client.up(speed) / client.down(speed)

Makes the drone gain or reduce altitude. `speed` can be a value from `0` to `1`.
Controls the vertical movement of the drone.

#### client.clockwise(speed) / client.counterClockwise(speed)

Causes the drone to spin. `speed` can be a value from `0` to `1`.
Sets `client.upDown` to `speed` or `-speed`. `speed` can be be from `0` to `1`.

#### client.front(speed) / client.back(speed)

Controls the pitch, which a horizontal movement using the camera
as a reference point. `speed` can be a value from `0` to `1`.
as a reference point.

Sets `client.frontBack` to `speed` or `-speed`. `speed` can be be from `0` to `1`.

#### client.left(speed) / client.right(speed)

Controls the roll, which is a horizontal movement using the camera
as a reference point. `speed` can be a value from `0` to `1`.
as a reference point.

Sets `client.leftRight` to `speed` or `-speed`. `speed` can be be from `0` to `1`.

#### client.clockwise(speed) / client.counterClockwise(speed)

Controls the rotation of the drone.

Sets client.clockSpin to `speed` or `-speed`. `speed` can be be from `0` to `1`.

#### client.stop()

Sets all drone movement commands to `0`, making it effectively hover in place.
Sets all drone movement properties to `0`, making it effectively hover in place.

#### client.config(key, value)

Expand Down
113 changes: 80 additions & 33 deletions lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ function Client(options) {

options = options || {};

this.flyBit = false;
this.emergencyBit = false;
this.leftRight = 0;
this.frontBack = 0;
this.upDown = 0;
this.clockSpin = 0;

this._udpControl = options.udpControl || new Client.UdpControl(options);
this._udpNavdatasStream = options.udpNavdataStream || new Client.UdpNavdataStream(options);
this._pngStream = new Client.PngStream(options);
this._interval = null;
this._ref = {};
this._pcmd = {};
this._repeaters = [];
this._afterOffset = 0;
this._disableEmergency = false;
Expand Down Expand Up @@ -57,13 +62,21 @@ Client.prototype.resume = function() {

Client.prototype._handleNavdata = function(navdata) {
if (navdata.droneState && navdata.droneState.emergencyLanding && this._disableEmergency) {
this._ref.emergency = true;
this.emergencyBit = true;
} else {
this._ref.emergency = false;
this.emergencyBit = false;
this._disableEmergency = false;
}

this.emit('navdata', navdata);
// request demo navdata if 'demo' option is not included
// also: don't emit navdata if 'demo' option is not present
// @TODO: Make this behavior configurable in the constructor
if (!navdata.demo) {
this._udpControl.config('general:navdata_demo', 'TRUE');
} else {
this.emit('navdata', navdata);
}

this._processNavdata(navdata);
};

Expand Down Expand Up @@ -117,8 +130,18 @@ Client.prototype._setInterval = function(duration) {
};

Client.prototype._sendCommands = function() {
this._udpControl.ref(this._ref);
this._udpControl.pcmd(this._pcmd);
this._udpControl.ref({
flyBit : this.flyBit,
emergencyBit : this.emergencyBit
});

this._udpControl.pcmd({
leftRight : this.leftRight,
frontBack : this.frontBack,
upDown : this.upDown,
clockSpin : this.clockSpin,
});

this._udpControl.flush();

this._repeaters
Expand All @@ -137,18 +160,18 @@ Client.prototype.disableEmergency = function() {
};

Client.prototype.takeoff = function() {
this._ref.fly = true;
return true;
this.flyBit = true;
};

Client.prototype.land = function() {
this._ref.fly = false;
return true;
this.flyBit = false;
};

Client.prototype.stop = function() {
this._pcmd = {};
return true;
this.leftRight = 0;
this.frontBack = 0;
this.upDown = 0;
this.clockSpin = 0;
};

Client.prototype.config = function(key, value) {
Expand Down Expand Up @@ -182,29 +205,53 @@ Client.prototype._repeat = function(times, fn) {
this._repeaters.push({times: times, method: fn});
};

var pcmdOptions = [
['up', 'down'],
['left', 'right'],
['front', 'back'],
['clockwise', 'counterClockwise'],
]
Client.prototype.left = function(speed) {
this.leftRight = speed;
};

pcmdOptions.forEach(function(pair) {
Client.prototype[pair[0]] = function(speed) {
speed = parseFloat(speed);
Client.prototype.right = function(speed) {
this.leftRight = -speed;
};

this._pcmd[pair[0]] = speed;
delete this._pcmd[pair[1]];
Client.prototype.front = function(speed) {
this.frontBack = speed;
};

return speed;
};
Client.prototype.back = function(speed) {
this.frontBack = -speed;
};

Client.prototype[pair[1]] = function(speed) {
speed = parseFloat(speed);
Client.prototype.up = function(speed) {
this.upDown = speed;
};

this._pcmd[pair[1]] = speed;
delete this._pcmd[pair[0]];
Client.prototype.down = function(speed) {
this.upDown = -speed;
};

Client.prototype.clockwise = function(speed) {
this.clockSpin = speed;
};

Client.prototype.counterClockwise = function(speed) {
this.clockSpin = -speed;
};

Client.prototype.toJSON = function() {
var json = {};
for (var key in this) {
var isPrivate = (key.substr(0, 1) === '_');
if (isPrivate) {
continue;
}

var value = this[key];
if (typeof value === 'function') {
continue;
}

return speed;
};
});
json[key] = value;
}

return json;
};
43 changes: 17 additions & 26 deletions lib/control/AtCommandCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ AtCommandCreator.prototype.ref = function(options) {

var args = [0];

if (options.fly) {
if (options.flyBit) {
args[0] = args[0] | REF_FLAGS.takeoff;
}

if (options.emergency) {
if (options.emergencyBit) {
args[0] = args[0] | REF_FLAGS.emergency;
}

Expand All @@ -35,19 +35,21 @@ AtCommandCreator.prototype.ref = function(options) {
AtCommandCreator.prototype.pcmd = function(options) {
options = options || {};

// flags, leftRight, frontBack, upDown, clockWise
var args = [0, 0, 0, 0, 0];

for (var key in options) {
var alias = PCMD_ALIASES[key];
var value = options[key];

if (alias.invert) {
value = -value;
}

args[alias.index] = at.floatString(value);
args[0] = args[0] | PCMD_FLAGS.progressive;
var args = [
0,
at.floatString(options.leftRight),
at.floatString(options.frontBack),
at.floatString(options.upDown),
at.floatString(options.clockSpin),
];

// determine if the drone is supposed to move or not
var move = args.some(function(value) {
return value !== 0;
});

if (move) {
args[0] = args[0] | PCMD_FLAGS.progressive;
}

return this.raw('PCMD', args);
Expand Down Expand Up @@ -95,17 +97,6 @@ var PCMD_FLAGS = exports.PCMD_FLAGS = {
progressive : (1 << 0),
};

var PCMD_ALIASES = exports.PCMD_ALIASES = {
left : {index: 1, invert: true},
right : {index: 1, invert: false},
front : {index: 2, invert: true},
back : {index: 2, invert: false},
up : {index: 3, invert: false},
down : {index: 3, invert: true},
clockwise : {index: 4, invert: false},
counterClockwise : {index: 4, invert: true},
};

// from ARDrone_SDK_2_0/ControlEngine/iPhone/Release/ARDroneGeneratedTypes.h
var LED_ANIMATIONS = exports.LED_ANIMATIONS = [
'blinkGreenRed',
Expand Down
10 changes: 10 additions & 0 deletions lib/control/at.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
var at = exports;

at.floatString = function(number) {
// undefined returns 0
if (number === undefined) {
return 0;
}

// interpret strings as numbers (THIS IS JAVASCRIPT ... *troll*)
if (typeof number === 'string') {
number = parseFloat(number);
}

// Not sure if this is correct, but it works for the example provided in
// the drone manual ... (should be revisted)
var buffer = new Buffer(4);
Expand Down
20 changes: 8 additions & 12 deletions test/unit/control/test-AtCommandCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ test('AtCommandCreator', {
assert.equal(cmd.args.length, 1);
assert.equal(cmd.args[0], 0);

var cmd = this.creator.ref({fly: true});
var cmd = this.creator.ref({flyBit: true});
assert.ok(cmd.args[0] & AtCommandCreator.REF_FLAGS.takeoff);

var cmd = this.creator.ref({emergency: true});
var cmd = this.creator.ref({emergencyBit: true});
assert.ok(cmd.args[0] & AtCommandCreator.REF_FLAGS.emergency);
},

Expand All @@ -47,17 +47,13 @@ test('AtCommandCreator', {

// test all the aliases mapping to pcmd args
var val = 0.75;
assert.equal(this.creator.pcmd({left: val}).args[1], at.floatString(-val));
assert.equal(this.creator.pcmd({right: val}).args[1], at.floatString(val));
assert.equal(this.creator.pcmd({front: val}).args[2], at.floatString(-val));
assert.equal(this.creator.pcmd({back: val}).args[2], at.floatString(val));
assert.equal(this.creator.pcmd({up: val}).args[3], at.floatString(val));
assert.equal(this.creator.pcmd({down: val}).args[3], at.floatString(-val));
assert.equal(this.creator.pcmd({clockwise: val}).args[4], at.floatString(val));
assert.equal(this.creator.pcmd({counterClockwise: val}).args[4], at.floatString(-val));
assert.equal(this.creator.pcmd({leftRight: val}).args[1], at.floatString(val));
assert.equal(this.creator.pcmd({frontBack: val}).args[2], at.floatString(val));
assert.equal(this.creator.pcmd({upDown: val}).args[3], at.floatString(val));
assert.equal(this.creator.pcmd({clockSpin: val}).args[4], at.floatString(val));

// test multiple aliases togeter
var cmd = this.creator.pcmd({left: 0.1, clockwise: 0.3});
var cmd = this.creator.pcmd({leftRight: -0.1, clockSpin: 0.3});
assert.equal(cmd.args[1], at.floatString(-0.1));
assert.equal(cmd.args[4], at.floatString(0.3));

Expand All @@ -66,7 +62,7 @@ test('AtCommandCreator', {
assert.equal(cmd.args[0] & AtCommandCreator.PCMD_FLAGS.progressive, false);

// test progressive bit being set automatically
var cmd = this.creator.pcmd({left: 0.1});
var cmd = this.creator.pcmd({leftRight: 0.1});
assert.ok(cmd.args[0] & (1 << 0));
},

Expand Down
8 changes: 8 additions & 0 deletions test/unit/control/test-at.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@ var test = require('utest');
var at = require(common.lib + '/control/at');

test('at', {
'undefined returns 0': function() {
assert.strictEqual(at.floatString(undefined), 0);
},

'-0.8': function() {
assert.equal(at.floatString(-0.8), -1085485875);
},

'"-0.8"': function() {
assert.equal(at.floatString('-0.8'), -1085485875);
},

'0': function() {
assert.equal(at.floatString(0), 0);
},
Expand Down
Loading