Full Stack Robotics – hybridgroup.com – Arduino



Full Stack Robotics – hybridgroup.com – Arduino

0 0


preso-fullstack-2014


On Github hybridgroup / preso-fullstack-2014

Full Stack Robotics

hybridgroup.com

Good Afternoon

This is #fullstackcon

I am @deadprogram

Ringleader

@hybrid_group

The other guy is @adzankich

Serious Programming Guy

@hybrid_group

hybridgroup.com

kidsruby.com

Full Stack Robotics

Starring

What Is 'Full Stack Robotics'?

Arduino

var Cylon = require('cylon');

Cylon.robot({
  connection: { 
    name: 'arduino', 
    adaptor: 'firmata', 
    port: '/dev/ttyACM0' 
  },
  
  device: { 
    name: 'led', 
    driver: 'led', 
    pin: 13 
  },

  work: function(my) {
    every((1).second(), function(){ my.led.toggle() });
  }
}).start();

Spark

var Cylon = require('cylon');

Cylon.robot({
  connection: {
    name: 'spark', 
    adaptor: 'spark',
    accessToken: 'XXXYYYZZZ',
    deviceId: '1234XXX7890'
  },

  device: {
    name: 'led', 
    driver: 'led', 
    pin: 'D7'
  },

  work: function(my) {
    every((1).second(), my.led.toggle);
  }
}).start();

Intel Edison

var Cylon = require('cylon');

Cylon.robot({
  connection: {
    name: 'edison', 
    adaptor: 'intel-iot'
  },

  device: {
    name: 'led', 
    driver: 'led', 
    pin: 4
  },

  work: function(my) {
    every((1).second(), my.led.toggle);
  }
}).start();

Choose Your Own Hardware Adventure!

To win a Sphero, tweet

@gosphero and @cylonjs

To win a Spark Core, tweet

@spark_io and @cylonjs

It All Starts With A Customer...

Brewforce

var Cylon = require('cylon');

Cylon.config({
  api: {
    host: '0.0.0.0', port: '8080', ssl:  false
  }
})
 
Cylon.api();

Cylon.robot({
  name: 'brewforce',
  connections: [
    { name: 'pebble', adaptor: 'pebble' },
    { name: 'edison', adaptor: 'intel-iot' },
    { 
      name: 'sfcon', 
      adaptor: 'force', 
      sfuser: process.env.SF_USERNAME, 
      sfpass: process.env.SF_SECURITY_TOKEN 
    }
  ],
  devices: [
    { name: 'pump', driver: 'direct-pin', pin: 6, connection: 'edison' },
    { name: 'tap', driver: 'button', pin: 4, connection: 'edison' },
    { name: 'fault', driver: 'button', pin: 2, connection: 'edison' },
    { name: 'pebble', driver: 'pebble', connection: 'pebble' },
    { name: 'salesforce', driver: 'force', connection: 'sfcon' }
  ],
  work: function() {
    this.tap.on('press', function() {
      if (!this.pumping) {
        this.activatePump();
      }
    }.bind(this));

    this.fault.on('press', function() {
      this.reportFault();
    }.bind(this));
  },

  served: 0,
  pumping: false,
  dispenserId: 5,
  droneId: 4,

  activatePump: function() {
    this.pumping = true;
    this.pump.digitalWrite(1);
    this.served += 1;
    var date = new Date(),
        dateStr = date.toISOString(),
        toSend = { 
          dispenserId: this.dispenserId,
          drinkId: this.served,
          event: 'online',
          eventTimestamp: dateStr,
          details: 'dispenser'
        };
    
    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('Err:', err);
      console.log('Data:', data);
    });

    setTimeout(function() {
      this.pump.digitalWrite(0);
      this.pumping = false;
    }.bind(this), 2000);

    console.log("Total customers served: " + toSend.drinkId);
    this.pebble.send_notification("Total customers served: " + toSend.drinkId);    
  },

  reportFault: function() {
    console.log("Pushing fault to SF.....");
    var date = new Date(),
        dateStr = date.toISOString(),
        toSend = { dispenserId: this.dispenserId,
                   drinkId: this.served,
                   event: 'error',
                   eventTimestamp: dateStr,
                   details: 'dispenser'
        };

    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('Err:', err);
      console.log('Data:', data);
    });

    this.pebble.send_notification("there was an error");
  },
  
  airDrop: function() {
    var date = new Date();
    var dateStr = date.toISOString();
    var toSend = { 
      dispenserId: this.droneId,
      drinkId: this.served,
      event: 'en route',
      eventTimestamp: dateStr,
      details: 'drone'
    };

    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('airDrop Err:', err);
      console.log('airDrop Data:', data);
    });

    this.pebble.send_notification("delivery sent by drone");
  },

  delivered: function() {
    var date = new Date();
    var dateStr = date.toISOString();
    var toSend = { 
      dispenserId: this.droneId,
      drinkId: this.served,
      event: 'delivery complete',
      eventTimestamp: dateStr,
      details: 'drone'
    };

    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('delivered Err:', err);
      console.log('delivered Data:', data);
    });

    this.pebble.send_notification("delivery sent by drone");
  },

  commands: function() {
    return {
      air_drop: this.airDrop,
      delivered: this.delivered,
      report_fault: this.reportFault,
      activate_pump: this.activatePump
    };
  }  
}).start();

Connected Devices

Drink Dispenser

Intel Edison + Salesforce

activatePump: function() {
    this.pumping = true;
    this.pump.digitalWrite(1);
    this.served += 1;
    var date = new Date(),
        dateStr = date.toISOString(),
        toSend = { 
          dispenserId: this.dispenserId,
          drinkId: this.served,
          event: 'online',
          eventTimestamp: dateStr,
          details: 'dispenser'
        };
    
    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('Err:', err);
      console.log('Data:', data);
    });

    setTimeout(function() {
      this.pump.digitalWrite(0);
      this.pumping = false;
    }.bind(this), 2000);

    console.log("Total customers served: " + toSend.drinkId);
    this.pebble.send_notification("Total customers served: " + toSend.drinkId);    
  },

Wearables

Wearable Demo

Intel Edison + Pebble + Salesforce

reportFault: function() {
    console.log("Pushing fault to SF.....");
    var date = new Date(),
        dateStr = date.toISOString(),
        toSend = { dispenserId: this.dispenserId,
                   drinkId: this.served,
                   event: 'error',
                   eventTimestamp: dateStr,
                   details: 'dispenser'
        };

    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('Err:', err);
      console.log('Data:', data);
    });

    this.pebble.send_notification("there was an error");
  },

Mobile

Mobile Demo

Intel Edison + Pebble + Commander + Salesforce

Cylon.config({
  api: {
    host: '0.0.0.0', port: '8080', ssl:  false
  }
})
 
Cylon.api();
commands: function() {
    return {
      air_drop: this.airDrop,
      delivered: this.delivered,
      report_fault: this.reportFault,
      activate_pump: this.activatePump
    };
  }

Robots

Drone Demo

Intel Edison + Salesforce + ARDrone + Commander + Pebble (Featuring Cylon.js)

DigiSpark (Featuring Gobot)

airDrop: function() {
    var date = new Date();
    var dateStr = date.toISOString();
    var toSend = { 
      dispenserId: this.droneId,
      drinkId: this.served,
      event: 'en route',
      eventTimestamp: dateStr,
      details: 'drone'
    };

    this.salesforce.post('/Drink/', toSend, function(err, data) {
      console.log('airDrop Err:', err);
      console.log('airDrop Data:', data);
    });

    this.pebble.send_notification("delivery sent by drone");
  },
var cylon = require('cylon');
var restler = require('restler');

cylon.robot({
  connections: [
    {name: 'dualshock3', adaptor: 'joystick'}, 
    {name: 'ardrone', adaptor: 'ardrone', port: '192.168.1.1'}
  ],
  devices: [
    {name: 'controller', driver: 'dualshock-3', connection: 'dualshock3'}, 
    {name: 'drone', driver: 'ardrone', connection: 'ardrone'}
  ]
})
  .on("ready", function(bot) {
    var offset = 32767.0;
    var rightStick = {
      x: 0.0,
      y: 0.0
    };
    var leftStick = {
      x: 0.0,
      y: 0.0
    };
    bot.controller.on("circle:press", function() {
      restler.get('http://192.168.1.1:3000/commands/drop_package')
        .on('complete', function(result) {
          console.log("response from drone: " + JSON.stringify(result));
        });
    });
    bot.controller.on("square:press", function() {
      bot.drone.takeoff();
    });
    bot.controller.on("triangle:press", function() {
      bot.drone.hover();
    });
    bot.controller.on("x:press", function() {
      bot.drone.land();
    });
    bot.controller.on("right_x:move", function(data) {
      rightStick.x = data;
    });
    bot.controller.on("right_y:move", function(data) {
      rightStick.y = data;
    });
    bot.controller.on("left_x:move", function(data) {
      leftStick.x = data;
    });
    bot.controller.on("left_y:move", function(data) {
      leftStick.y = data;
    });

    setInterval(function() {
      var pair = leftStick;
      if (pair.y < 5) {
        bot.drone.front(validatePitch(pair.y, offset));
      } else if (pair.y > 5) {
        bot.drone.back(validatePitch(pair.y, offset));
      }
      if (pair.x > 5) {
        bot.drone.right(validatePitch(pair.x, offset));
      } else if (pair.x < 5) {
        bot.drone.left(validatePitch(pair.x, offset));
      }
    }, 0);

    setInterval(function() {
      var pair = rightStick;
      if (pair.y < 5) {
        bot.drone.up(validatePitch(pair.y, offset));
      } else if (pair.y > 5) {
        bot.drone.down(validatePitch(pair.y, offset));
      }
      if (pair.x > 20) {
        bot.drone.clockwise(validatePitch(pair.x, offset));
      } else if (pair.x < 20) {
        bot.drone.counterClockwise(validatePitch(pair.x, offset));
      }
    }, 0);

    setInterval(function() {
      bot.drone.hover();
    }, 10);
  })
  .on('error', function(err) {
    console.log(err);
  })
  .start();

function validatePitch(data, offset) {
  var value = Math.abs(data) / offset;
  if (value >= 0.1) {
    if (value <= 1.0) {
      return Math.round(value * 100.0) / 100.0;
    } else {
      return 1.0;
    }
  } else {
    return 0.0;
  }
}

Was that fun?

Join the Robot Evolution!

cylonjs.com

@cylonjs

Thank you!

@deadprogram

@adzankich