Run this example from the command line with:
node eg/bug.js
var five = require("johnny-five");
function Bug(servos) {
var part, k;
this.isMoving = false;
// Initialize list of body parts
this.parts = ["front", "left", "right", "rear"];
// Servo positions
this.history = [];
// Interval id table
this.intervals = {
fwd: null,
rev: null
};
k = -1;
// Initialize Servo properties from "servos" argument
while (++k < this.parts.length) {
part = this.parts[k];
this[part] = servos[part] || null;
}
// Unwind and wait ~10ms, center servos
setTimeout(function() {
this.idle();
}.bind(this), 10);
}
Bug.STEP_MAP = {
// steps
fwd: [
[10, -30],
[-15, 30]
],
rev: [
[-15, 30],
[15, -30]
]
};
/**
* idle Set the bug legs to center position and
* @return {Bug}
*/
Bug.prototype.idle = function() {
// If the bug is actually in motion,
// stop the servo intervals
if (this.isMoving) {
this.stop();
}
// set to center position°
this.front.to(90);
this.rear.to(90);
//return this;
};
/**
* step Take a full or half step
*
* @param {Dict} opts Properties:
* half {Boolean}
* dir {String}
* @return {Bug}
*/
Bug.prototype.step = function(opts) {
var dir, move, last, front, rear, step;
opts = opts || {};
// Get last move from history if any history exists
// Provide a "fake" history if needed (first call)
last = this.history.length ?
this.history[this.history.length - 1] : {
step: 1
};
// increment the last step
step = last.step + 1;
// If step is too high, step back to 0
if (step > 1) {
step = 0;
}
// Derive direction if provided,
// defaults to fwd
dir = opts.dir || "fwd";
// Derive position° for next move
move = Bug.STEP_MAP[dir][step];
// Assign position° from center
front = 90 + move[0];
rear = 90 + move[1];
// Write position° to servos
this.front.to(front);
this.rear.to(rear);
// Allow half step or full if provided,
// defaults to full
// enum(false|null|undefined)
if (!opts.half) {
// Wait one second and move servos back to
// center idling position, 90°
setTimeout(function() {
this.idle();
}.bind(this), 1000);
}
// Push a step into history array;
// will be used as a reference for the subsequent step
this.history.push(
// NOTE: this is a great use case example for
// ES.next concise object initializers
{
dir: dir,
step: step,
front: front,
rear: rear
}
);
};
/**
* stop Stop the bug by clearing the intervals
* @return {Bug}
*/
Bug.prototype.stop = function() {
Object.keys(this.intervals).forEach(function(key) {
if (this.intervals[key]) {
clearInterval(this.intervals[key]);
}
}, this);
//return this;
};
[
/**
* fwd Move the bug forward continuously
* @return {Bug}
*/
"fwd",
/**
* rev Move the bug backwards continuously
* @return {Bug}
*/
"rev"
].forEach(function(dir, k) {
Bug.prototype[dir] = function() {
this.isMoving = true;
this.intervals[dir] = setInterval(function() {
this.step({
dir: dir,
half: true
});
}.bind(this), 750);
// //return this;
};
});
five.Board().on("ready", function() {
var bug, ranges, servos;
bug = new Bug({
front: new five.Servo(9),
rear: new five.Servo(10)
//,
//left: new five.Servo({ pin: 5, range: [ 70, 115 ] }),
//right: new five.Servo({ pin: 6, range: [ 70, 115 ] })
});
// Inject the Servo Array into the REPL as "s"
this.repl.inject({
bug: bug,
s: new five.Servos()
});
// bug.step();
});