Rick Waldron

@rwaldron

github.com/rwldrn

[ @nodebots, #nodebots ]




Hardware

Intrinsically Synchronous



Sync Input Handled Asynchronously

Sensors ➡ Serialport
Streams ➡ Events



TEACHING NODEBOTS
HOW TO WALK

with JavaScript




Async Output

What and When,
Now and Later




Sequence

n. A following of one thing after another

Sequential Execution

Starting at 90°... 135° (346ms) > 0° (1036) > 45° (690) > 180° (1036) > 90° (690)




delay()

Execution Blocking



#include <Servo.h>

// create servo object to control a servo
Servo servo;

void setup() {
  // attaches the servo on pin 9 to the servo object
  servo.attach(9);

  servo.write(135);
  delay(346);

  servo.write(0);
  delay(1036);

  servo.write(45);
  delay(690);

  servo.write(180);
  delay(1036);

  servo.write(90);
  delay(690);
}


function delay( ms ) {
  var start = Date.now();
  while ( Date.now() < start + ms ) {}
}

var servo = new five.Servo(9);

servo.move(135);
delay(346);

servo.move(0);
delay(1036);

servo.move(45);
delay(690);

servo.move(180);
delay(1036);

servo.move(90);
delay(690);

// 4144 ms of BLOCKED EXECUTION.



Blocking Execution






setTimeout

// Servos will be auto-centered to 90°
var servo = new five.Servo(9);

servo.move(135);

setTimeout(function() {
  servo.move(0);

  setTimeout(function() {
    servo.move(45);

    setTimeout(function() {
      servo.move(180);

      setTimeout(function() {
        servo.move(90);

      }, 1036);
    }, 690);
  }, 1036);
}, 346);





No Thanks.

Doesn't scale, Not Composable, Drift



Timer

via timer_wrap.cc

Close, but 2-25ms disparity



process.nextTick

Define a callback to execute in the next turn of the event loop.


function loop() {
  process.nextTick( loop );
}

process.nextTick( loop );



Temporal

delays, loops, queues

Process Execution

{
  0: null,
  1: null,
  2: [ task, task ],
  3: null,
  4: [ task ],
  5: null,
  6: [ task, task ],
  7: null
}
 

Execution





Sequences

// Hitec HS-422 [ 6.0V: 0.16 sec/60° (160ms to travel 60°) ]

#include <Servo.h>

// Create servo objects
Servo servo1;
Servo servo2;

int degree = 90;

void setup() {
  // Initialize two servos on pins 9 and 10
  servo1.attach(9);
  servo2.attach(10);
}

void loop() {

  degree = degree == 90 ? 180 : 90;

  servo1.write(degree);
  servo2.write(degree);

  delay(480);
}
var five = require("johnny-five"),
    temporal = require("temporal");

five.Board().on("ready", function() {
  var servos, degree;

  // Initialize two servos on pins 9 and 10
  [ 9, 10 ].map( five.Servo );

  // Create a servo array
  servos = five.Servos();

  degree = 90;

  temporal.loop( 500, function() {
    servos.move(
      degree = degree === 90 ? 180 : 90
    );
  });
});

Sequential Execution


The temporal.queue() call...

temporal.queue([
  { delay: 346,   task: [Function] },
  { delay: 1036,  task: [Function] },
  { delay: 690,   task: [Function] },
  { delay: 346,   task: [Function] },
  { delay: 1036,  task: [Function] },
  { delay: 690,   task: [Function] }
]);

Linear Registry...

// Imagine temporal.queue([ ... ]) is invoked at 1352402416096...

// [ delay, cumulative
// [346, 346],
// [1036, 1382],
// [690, 1726],
// [346, 1036],
// [1036, 1382],
// [690, 1726]
// ]
{
  1352402416442: [ task, ... ],
  1352402417478: [ task, ... ],
  1352402418168: [ task, ... ],
  1352402418514: [ task, ... ],
  1352402419550: [ task, ... ],
  1352402420240: [ task, ... ]
}



Walking

A sequence of motions...

github.com/rwldrn/johnny-five

http://gul.ly/dbv