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();
});

 

Component Classes in this example:

Hi! The Johnny-Five community is building new projects every day. We made this newsletter to tell you about what's new, what's good, and what's next for Open Source robotics. Join us in exploring what we can make together.

Fork me on GitHub