The 10 Rules Of RobotOps

robotops.com

Good Afternoon

This is #df14

I am @deadprogram

Ringleader

@hybrid_group

The other guy is @adzankich

Serious Programming Guy

@hybrid_group

hybridgroup.com

kidsruby.com

The 10 Rules Of RobotOps

Starring

Also Starring

Featuring

What's 'RobotOps'?

DevOps For Robots

Declarative Code Syntax (#1)

Spark Core (Featuring Cylon.js)


var Cylon = require('cylon');

Cylon.robot({
  connection: {
    name: 'spark', adaptor: 'spark',
    accessToken: 'ecc7a925d3b92bf1f9c942de25a14916a7e4a4bc',
    deviceId: '53ff72065067544854310187'
  },

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

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

Command Line Interface (#2)

gort.io

Demo - Remote Update Spark Firmware

Multiple Platforms/Devices (#3)

Demo - Spark Turtlebot + Salesforce


var Cylon = require('cylon');

Cylon.robot({
  connection: {
    name: 'spark', adaptor: 'spark',
    accessToken: 'ecc7a925d3b92bf1f9c942de25a14916a7e4a4bc',
    deviceId: '53ff72065067544854310187'
  },

  devices: [
    {name: 'leftMotor', driver: 'motor', pin: "D1"},
    {name: 'rightMotor', driver: 'motor', pin: "A7"},
    {name: 'leftDirection', driver: 'direct-pin', pin: "D3"},
    {name: 'rightDirection', driver: 'direct-pin', pin: "D4"}
  ],

  work: function(my) {
    my.leftDirection.digitalWrite(1);
    my.rightDirection.digitalWrite(1);
    my.leftMotor.speed(100);
    my.rightMotor.speed(100);
    after((10).seconds(), function() {
      my.leftDirection.digitalWrite(0);
      my.rightDirection.digitalWrite(0);
    });
    after((20).seconds(), function() {
      my.leftDirection.digitalWrite(1);
      my.rightDirection.digitalWrite(0);
    });
    after((21).seconds(), function() {
      my.leftDirection.digitalWrite(0);
      my.rightDirection.digitalWrite(1);
    });
    after((22).seconds(), function() {
      my.leftDirection.digitalWrite(1);
      my.rightDirection.digitalWrite(0);
    });
    after((23).seconds(), function() {
      my.leftDirection.digitalWrite(0);
      my.rightDirection.digitalWrite(1);
    });
    after((24).seconds(), function() {
      my.leftMotor.turnOff();
      my.rightMotor.turnOff();
    });
  }
}).start();
            

Choose Your Own Hardware Adventure!

To win a Spark Core Starter Kit, tweet

@sparkdevices and @cylonjs

To win a Sphero, tweet

@gosphero and @cylonjs

Code Generators (#4)

Demo - Generate New Robot

Test-Driven Robotics (#5)

Demo - Run Tests

Built-In API (#6)

Common Protocol for Programming Physical I/O

cppp.io

Admin Tools (#7)

robeaux.io

Demo - Raspberry Pi Robot (RaPiRo)

Robeaux Demo

Documentation & Support (#8)

Security (#9)

3DRobotics Iris (Featuring Gobot)

Iris Demo

Swarms (#10)

Pebble (Featuring Artoo)

Salesforce + ARDrone + OpenCV (Featuring Cylon.js)

Sphero + DigiSpark (Featuring Gobot)


require 'artoo'
require 'http'

connection :pebble, :adaptor => :pebble
device     :watch,  :driver  => :pebble, :name => 'pebble'

api :host => '0.0.0.0', :port => '8080'

name 'pebble'

def button_push(*data)
  unless data[1].nil?
    HTTP[:content_type => 'application/json'].get "http://192.168.1.3:3000/api/robots/drone/commands/face_off"
  end
end

work do
  pebble.send_notification("Hello Pebble!")
  on pebble, :button => :button_push
end
            

var Cylon = require('cylon');
var rest = require('restler');
var haarcascade = "" + __dirname + "/haarcascade_frontalface_alt.xml";
 
var DroneRobot = (function(){ 
 
  function DroneRobot() {} 
 
  DroneRobot.prototype.commands = ["face_off"];
 
  DroneRobot.prototype.connections = [
    { name: 'opencv', adaptor: 'opencv' }, 
    { name: 'ardrone', adaptor: 'ardrone', port: '192.168.1.1' }
  ];
  
  DroneRobot.prototype.devices = [
    { name: 'drone', driver: 'ardrone', connection: 'ardrone' }, 
    { name: 'window', driver: 'window', conneciton: 'opencv' }, 
    { name: 'mat', driver: 'mat', conneciton: 'opencv' }
  ];
 
  DroneRobot.prototype.work = function(my) {
    console.log("SHOW ME YOUR FACE!");
  };
 
  DroneRobot.prototype.face_off = function() {
    var my = this;
    var self = this;
    self.detect = false;
    self.image = null;
    my.drone.getPngStream().on('data', function(png) {
      my.mat.readImage(png, function(err, img) {
        self.image = img;
        if (self.detect === false) {
          my.window.show(img);
        }
      });
    });
    my.mat.on('facesDetected', function(err, im, faces) {
      var biggest, center_x, f, face, turn;
      biggest = 0;
      face = null;
      for (var i = 0; i < faces.length; i++) {
        f = faces[i];
        if (f.width > biggest) {
          biggest = f.width;
          face = f;
        }
      }
      if (face !== null && (face.width <= 100 && face.width >= 45)) {
        rest.get('http://192.168.1.1:3000/api/robots/digispark/devices/led/commands/Toggle').on('complete', function(result) {
          if (result instanceof Error) {
            console.log('Error:', result.message);
          } 
        });
        rest.get('http://127.0.0.1:3001/api/robots/mod/commands/wake_up').on('complete', function(result) {
          if (result instanceof Error) {
            console.log('Error:', result.message);
          } 
        });
        im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], 
          [0, 255, 0], 2);
        center_x = im.width() * 0.5;
        turn = -(face.x - center_x) / center_x;
        console.log("turning: " + turn);
        if (turn < 0) {
          my.drone.clockwise(Math.abs(turn * 0.7));
        } else {
          my.drone.counterClockwise(Math.abs(turn * 0.7));
        }
      } else {
        rest.get('http://192.168.1.1:3000/api/robots/digispark/devices/led/commands/Off').on('complete', function(result) {
          if (result instanceof Error) {
            console.log('Error:', result.message);
          } 
        });
        rest.get('http://127.0.0.1:3001/api/robots/mod/commands/snooze').on('complete', function(result) {
          if (result instanceof Error) {
            console.log('Error:', result.message);
          } 
        });
      }
      my.window.show(im);
    });
    my.drone.takeoff();
    after((8).seconds(), function() { my.drone.up(0.5); });
    after((10).seconds(), function() { my.drone.hover(); });
    after((13).seconds(), function() {
      self.detect = true;
      every(0.3.seconds(), function() {
        my.drone.hover();
        my.mat.detectFaces(self.image, haarcascade);
      });
      after((30).seconds(), function() { my.drone.land(); });
    });
  };
 
  return DroneRobot;
})();
 
var robot = new DroneRobot;
robot.name = "drone";
 
Cylon.robot(robot);
Cylon.api({ host: '192.168.1.3', port: '3000', ssl: false });
Cylon.start();
            

package main

import (
  "github.com/hybridgroup/gobot"
  "github.com/hybridgroup/gobot/api"
  "github.com/hybridgroup/gobot/platforms/digispark"
  "github.com/hybridgroup/gobot/platforms/gpio"
)

func main() {
  gbot := gobot.NewGobot()
  api.NewAPI(gbot).Start()

  digi := digispark.NewDigisparkAdaptor("digispark")

  led := gpio.NewLedDriver(digi, "led", "2")

  gbot.AddRobot(
    gobot.NewRobot("digispark", []gobot.Connection{digi}, []gobot.Device{led}),
  )

  gbot.Start()
}
            

package main

import (
  "fmt"

  "github.com/hybridgroup/gobot"
  "github.com/hybridgroup/gobot/api"
  "github.com/hybridgroup/gobot/platforms/sphero"
)

func main() {
  gbot := gobot.NewGobot()
  a := api.NewAPI(gbot)
  a.Port = "3001"
  a.Start()

  spheros := map[string]string{
    "/dev/rfcomm0": "Thelma",
    "/dev/rfcomm1": "Louise",
    "/dev/rfcomm2": "Grace",
  }

  connections := []gobot.Connection{}
  devices := []gobot.Device{}

  for port, name := range spheros {
    adaptor := sphero.NewSpheroAdaptor("Sphero", port)
    ball := sphero.NewSpheroDriver(adaptor, name)

    connections = append(connections, adaptor)
    devices = append(devices, ball)
  }

  mod := gbot.AddRobot(
    gobot.NewRobot("mod", connections, devices, func() { fmt.Println("Ready!") }),
  )

  mod.AddCommand("wake_up", func(params map[string]interface{}) interface{} {
    mod.Devices().Each(func(device gobot.Device) {
      device.(*sphero.SpheroDriver).SetRGB(uint8(gobot.Rand(255)), uint8(gobot.Rand(255)), uint8(gobot.Rand(255)))
      device.(*sphero.SpheroDriver).Roll(uint8(70), uint16(gobot.Rand(360)))
    })
    return true
  })

  mod.AddCommand("snooze", func(params map[string]interface{}) interface{} {
    mod.Devices().Each(func(device gobot.Device) {
      device.(*sphero.SpheroDriver).SetRGB(uint8(255), uint8(0), uint8(0))
      device.(*sphero.SpheroDriver).Roll(uint8(0), uint16(0))
    })
    return true
  })

  gbot.Start()
}
            

Was that fun?

Join the Robot Evolution!

cylonjs.com

@cylonjs

gobot.io

@gobotio

artoo.io

@artooio

gort.io

robotops.com

Thank you!

@deadprogram

@adzankich