These Bots AreMade For Walkin’ – jsconf.co October 16, 2015



These Bots AreMade For Walkin’ – jsconf.co October 16, 2015

0 1


these-bots-are-made-for-walkin

Presentation used at various conferences in 2014 and 2015

On Github dtex / these-bots-are-made-for-walkin

These Bots AreMade For Walkin’

jsconf.co October 16, 2015

Donovan Buck

dtex

  • JavaScript robotics. Specifically it’s about Johnny-Five
  • The first time I saw NodeConf in 2012.
  • Attended nodebotsday 2013.
  • I decided to build my own robot… and I wanted a walking robot.
  • But I discovered something…

WalkingIs Hard!

Really, really hard

DARPA Robotics Challenge

There are two big challenges.
  • The robot has to maintain its balance.
  • This can be done with Static or Dynamic gaits
  • Static gaits are those where the center of gravity
  • Dynamic gaits are the opposite
So for reasons (budget) I decided to go with a static gait. I also decided on a hexapod, thinking that it wouldn’t be hard to keep a robot with six legs upright, but it’s still an issue. Second challenge:

Robot Anatomy

For the second challenge we need to talk about robot anatomy

Robot Anatomy

I thought, to make it walk all I had to do was put the end effector on the ground and turn the coxa. That gives you…

Drunk Robot

  • End effector describes a circle around the coxa axis of rotation
  • Legs are working against each other
  • We want them to work together and move the robot forward smoothly, in a straight line.

Sober Robot

  • To do this we have to move all three joints in concert
  • That’s a whole lot of stuff that needs to happen.
  • Is it even possible?

Rick Waldron

@rwaldron

  • In May of 2014 Rick Waldron presented at EmpireJS
  • Bits of Nodebots Next
  • Showing some things that were possible with Johnny-Five

Bits of NodeBots Next

  • 12 Servos, 100fps = 9,600 commands in this 8 second clip
  • node.js -> Johnny Five -> Firmata -> Node Serialport -> Firmata -> Arduino
  • It works!
  • Rick had to create his animation from scratch

Animation()

  • Timeline
  • Cue Points & Key Frames
  • Tweening
  • Easing Functions
  • Metaphors from 2D and 3D animation apps
  • I’m going to show some Animation code real quick.

Using Animation()

var five = require("johnny-five");
var board = new five.Board().on("ready", function() {

  var right = new five.Servo(11),
      left = new five.Servo(10);

  var legs = new five.Servo.Array([right, left]);
  var legsAnimation = new five.Animation(legs);

  legsAnimation.enqueue({
    duration: 5000,
    easing: "inOutQuad",
    cuePoints: [ 0, 0.25, 0.5, 0.6, 1.0],
    keyFrames: [
      [null, {degrees: 110}, -90, false, {degrees: 0}],
      [null, {degrees: 90}, 20, -90, {degrees: 140}]
    ]
  });
});
  • Require J5, Create a board
  • The magical handshake
  • Create servos. First point:
  • Servo array = target, Animation = timeline
  • Enqueue segment
  • Pretty easy right?

Using Animation()

keyFrames: [
  [null, null, {degrees: s.f.c[5]}, null, null, null, null, {degrees: s.f.c[5]}, null, {degrees: s.f.c[0]}, null, null, null, null, {degrees: s.f.c[5]}], // r1c
  [null, { step: lift.femur, easing: easeOut }, {degrees: s.f.f[5], easing: easeIn}, null, null, null, null, {degrees: s.f.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.f.f[0], easing: easeIn}, null, null, null, null, {degrees: s.f.f[5]}],
  [null, { step: lift.tibia, easing: easeOut }, {degrees: s.f.t[5], easing: easeIn}, null, null, null, null, {degrees: s.f.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.f.t[0], easing: easeIn}, null, null, null, null, {degrees: s.f.t[5]}],

  [null, null, null, false, null, {degrees: s.f.c[2]}, null, {degrees: s.f.c[2]}, null, null, {degrees: s.f.c[5]}, null, {degrees: s.f.c[0]}, null, {degrees: s.f.c[2]}],
  [null, null, null, false, { step: lift.femur, easing: easeOut }, {degrees: s.f.f[2], easing: easeIn}, null, {degrees: s.f.f[2]}, null, null, {degrees: s.f.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.f.f[0], easing: easeIn}, null, {degrees: s.f.f[2]}],
  [null, null, null, false, { step: lift.tibia, easing: easeOut }, {degrees: s.f.t[2], easing: easeIn}, null, {degrees: s.f.t[2]}, null, null, {degrees: s.f.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.f.t[0], easing: easeIn}, null, {degrees: s.f.t[2]}],

  [null, null, null, null, false, null, {degrees: s.m.c[1]}, {degrees: s.m.c[1]}, null, null, null, {degrees: s.m.c[5]}, null, {degrees: s.m.c[0]}, {degrees: s.m.c[1]}],
  [null, null, null, null, false, { step: lift.femur, easing: easeOut }, {degrees: s.m.f[1], easing: easeIn}, {degrees: s.m.f[1]}, null, null, null, {degrees: s.m.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.m.f[0], easing: easeIn}, {degrees: s.m.f[1]}],
  [null, null, null, null, false, { step: lift.tibia, easing: easeOut }, {degrees: s.m.t[1], easing: easeIn}, {degrees: s.m.t[1]}, null, null, null, {degrees: s.m.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.m.t[0], easing: easeIn}, {degrees: s.m.t[1]}],

  [null, false, null, {degrees: s.m.c[4]}, null, null, null, {degrees: s.m.c[4]}, {degrees: s.m.c[5]}, null, {degrees: s.m.c[0]}, null, null, null, {degrees: s.m.c[4]}],
  [null, false, { step: lift.femur, easing: easeOut }, {degrees: s.m.f[4], easing: easeIn}, null, null, null, {degrees: s.m.f[4]}, {degrees: s.m.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.m.f[0], easing: easeIn}, null, null, null, {degrees: s.m.f[4]}],
  [null, false, { step: lift.tibia, easing: easeOut }, {degrees: s.m.t[4], easing: easeIn}, null, null, null, {degrees: s.m.t[4]}, {degrees: s.m.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.m.t[0], easing: easeIn}, null, null, null, {degrees: s.m.t[4]}],

  [null, null, false, null, {degrees: s.r.c[3]}, null, null, {degrees: s.r.c[3]}, null, {degrees: s.r.c[5]}, null, {degrees: s.r.c[0]}, {degrees: s.r.c[1]}, null, {degrees: s.r.c[3]}],
  [null, null, false, { step: lift.femur, easing: easeOut }, {degrees: s.r.f[3], easing: easeIn}, null, null, {degrees: s.r.f[3]}, null, {degrees: s.r.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.r.f[0], easing: easeIn}, {degrees: s.r.f[1]}, null, {degrees: s.r.f[3]}],
  [null, null, false, { step: lift.tibia, easing: easeOut }, {degrees: s.r.t[3], easing: easeIn}, null, null, {degrees: s.r.t[3]}, null, {degrees: s.r.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.r.t[0], easing: easeIn}, {degrees: s.r.t[1]}, null, {degrees: s.r.t[3]}],

  [null, null, null, null, null, false, null, {degrees: s.r.c[0]}, null, null, null, null, {degrees: s.r.c[5]}, null, {degrees: s.r.c[0]}],
  [null, null, null, null, null, false, { step: lift.femur, easing: easeOut }, {degrees: s.r.f[0], easing: easeIn}, null, null, null, null, {degrees: s.r.f[5]}, { step: lift.femur, easing: easeOut }, {degrees: s.r.f[0], easing: easeIn}],
  [null, null, null, null, null, false, { step: lift.tibia, easing: easeOut }, {degrees: s.r.t[0], easing: easeIn}, null, null, null, null, {degrees: s.r.t[5]}, { step: lift.tibia, easing: easeOut }, {degrees: s.r.t[0], easing: easeIn}]
]
  • This is terrible
  • It's the keyframe array for a simple walking sequence
  • Incredibly tedious and error prone

Divide by Zero

legs.to(Infinity);
  • Easy to make mistakes
  • Could have cost hundreds of dollars

Ronald Jaramillo

@ronaldxjt

  • Ronald Jaramillo created Go-Johnny-Go
  • A nice GUI for building J5 animations

Go-Johnny-Go

  • Define cuepoint
  • Define keyframes
  • Playback
  • Export

Animation()

  • Using a leap motion controller.
  • Wake, walk, turn, reverse, sleep
  • Pretty cool… Not cool.
  • Explicitly telling every limb what to do
  • Without regard to the robot’s environment.
  • Setting the angle of each servo
  • We are not putting our end effectors where they might actually need to be.
  • This is a fancy remote controlled toy
  • We want robots that can be aware of their environment, respond to changing conditions and do the tasks we give them in a “smart” way.

More Bits ofNodebots Next

  • We need to be able to map the environment in more detail and at a much farther range.
  • We need to be able to do way finding.
  • First we need to be able to position our end effectors in a way that is not predetermined.

The Next Dimension

  • Joint coordinate space
  • Now we’re dealing with points in global coordinate space.
  • Instead of a single degree value we are working with three-tuples… X,Y and Z coordinates.
  • Animation() handles that.
  • But we needed a way to position the end effectors.

Raquel Vélez

@rockbot

  • Demoed Manny-The-Manipulator at JSConf in 2013.
  • At Manny’s heart was Vektor
  • A suite of linear algebra tools for helping with inverse kinematics.
  • What is inverse kinematics

Manny the Manipulator

Forward Kinematics

  • We take a series of known values (our segment lengths and joint angles)
  • Calculate where the end effector will be.
  • In this example Raquel is positioning the servos, and the end effector position is being calculated.

Manny the Manipulator

Inverse Kinematics

  • We are given the desired end effector position and joint lengths
  • We have to find the angles that get our end effector to that point.
  • In this example Raquel is dragging the end effector and the angles are being calculated.
  • Vector gives us tools to help solve for that. But we still needed a way to define our kinematic chains.

Tharp

  • A node module that allows us to define kinematic chains, systems of chains (robots).
  • Tharp takes in an end effector position and segment lengths then spits out servo angles.

Using Tharp Chains

var r1 = new Tharp.Chain({
  chainType: "CoxaY-FemurZ-TibiaZ",
  origin: [4.25, 2.875, 8.15],
  segments: { femur: 7.6125, tibia: 10.4 },
  startAt: [11.25, 0, 12.15],
  constructor: five.Servos,
  actuators: [
    { pin: 40, offset: 24, startAt: 0, range: [0, 90] },
    { pin: 39, offset: 87, startAt: 78, range: [-80, 78] },
    { pin: 38, offset: 165, invert: true, startAt: -140, range: [-160, -10] }
  ]
});
  • Define a kinematic chain
  • Select chain type, Define origin point, Set segment lengths, Set start position Define actuators

Using Tharp Robots

var phoenix = new Tharp.Robot({
  robotType: "hexapod",
  chains: [r1, l1, r2, l2, r3, l3]
});
  • Define a robot
  • Select robot type
  • Define chains
  • Now we have everything we need to set an X,Y,Z coordinate on a chain and Johnny-Five will put the end effector there.

Tharp

  • Our first movement is a “wake up” animation segment
  • Instead of tweening between angles we are tweening between XYZ tuples.
  • Show palm movement.
  • Now here, we are not using animation(). We have rotation about all three axes, and translation along all three axes while maintaining our end effector positions in global coordinate space.
  • Next steps for Tharp are support for more chain, and robot types. We also want to wrap a variety of gaits into Tharp for each robot type.

Johnny-Fiveis Awesome!

  • Johnny-Five is amazing.
  • It takes hard things and makes them incredibly easy.
  • Almost anyone can get up and running with robotics in an afternoon.
  • Connected by Default
  • Embeddable (Pi, T2, Edison, BBB)

The Communityis Awesome!

  • Remarkably Diverese
  • International
  • Friendly
  • Accomodating
  • 86 Contributors
  • You Should Join Us!
  • Remarkably diverese team
  • 86 Contributors/li>
  • Friendly & Helpful

The Futureis Awesome!

JerryScript

V7

  • As JavaScript developers our range of influence is growing
  • What’s expected from us will change
  • I promise that unless you are retiring soon you will have opportunities to build for other types of hardware
  • The time you spend playing with Nodebots will pay off.

Links

johnny-five.io

github.com/Traverso/go-johnny-go

github.com/rockbot/vektor

github.com/dtex/tharp

dtex

  • Thanks for Listening

Go Be Awesome!

dtex.us/jsconfco

dtex

  • Thanks for Listening
These Bots AreMade For Walkin’ jsconf.co October 16, 2015 Donovan Buck dtex JavaScript robotics. Specifically it’s about Johnny-Five The first time I saw NodeConf in 2012. Attended nodebotsday 2013. I decided to build my own robot… and I wanted a walking robot. But I discovered something…