Anatomy of a Robot

A while back, I wrote a blog post about spherical robots.   I had taken it upon myself to learn a bit more about robotics with the intention of building a simple autonomous robot.  Well, over two years later, I’m at a point where I can do some actual robotics work.  I look back on what I’ve learned… and the rabbit hole of a trek that led me here.

The Coursera Rabbit Hole

mindstormbrick

What goes into a robot?  Well, naively I thought that you hook up servos and sensors tosome kind of micro controller and away you go.  It’s the Lego Mindstorms version of Robotics.  Of course, that *IS* one way to look at robots… but really, that’s just the beginning… the “Hello World” program of building robots.  I wanted to build something a little more sophisticated than the “recommended age 12-adult” crowd.

itunes-artworkWell, for the answer we look to the Control of Mobile Robots class offered on Coursera.  In this class, Dr. Magnus Egerstedt introduces Control Systems.  The class itself does not get into the hardware of building robots, but digs into the abstraction layers necessary for successfully modeling and controlling things that interact with the real world. 

What exactly do I mean when I say “Control things?” Well, think about yourself for a moment.  If you’re standing and someone shoves you, you are able to react in a way to keep yourself stable and standing… or simply put you’re in control of your body.  The act of keeping yourself upright is a complex set of muscle movements that need to be carried out correctly but you don’t need to think about how to control each muscle… you just do it.  The instinctive impulse to lean or step is handled by your innate control system.

itunes-artworkIt’s not enough, however, for a robot to be “controllable”.  My goal is to build a robot that’s autonomous.   That requires some form of higher level artificial intelligence.  It turns out that Coursera offers another class geared toward exactly this: Artificial Intelligence Planning!  In this class, Dr. Gerhard Wickler and Professor Austin Tate take you through a survey of programmatic problem solving algorithms.  I was amused to learn that like all other computer science problem, artificial intelligence problem solving comes down to a search algorithm.

At the end of this course, you’ll be able to write a program that given some set of circumstances and corresponding set of possible actions, it will figure out what to do to accomplish its goals; assuming that some possible set of actions can achieve the goal.

small-icon.hoverThis lead me to the next problem… perception.  An autonomous robot has sensors and it needs to be able to figure out some “state” of the universe in order for it to use its problem solving capabilities.  How on earth do you map images/sounds/echolocation to logical states of the universe?  Through machine learning.  As it turns out, Coursera offers a LOT of classes on exactly this.  The most notable of these classes is Coursera’s co-founder‘s class on Machine learning…  Here, you learn all kinds of algorithms for automatically classifying and identifying logical states based on noisy or confusing input.

itunes-artworkA more advanced class that I really enjoyed focused on state of the art Neural Networks.  The class is called Neural Networks for Machine Learning and is taught by Dr. Geoffrey Hinton.  This class goes into great depth on various kinds of Neural Networks.  This class totally blew my mind.  I have no doubt that the correct application of neural nets with the right kind of self-motivating planner will lead to formidable AIs.

Putting it all together

First let’s talk about hardware.  Below is a list of hardware that I’m going to use and I’ll parallel it with what I feel may be the human anatomy counter-part.

IMG_0465I’m going to use an Arduino Uno as the primary interface with all of my robot’s actuators.  It represents the spinal cord and instinctive nervous system of the robot.   The Arduino is a very simple microcontroller that isn’t terribly fast.  It also doesn’t have much in the way of memory.  It does have extremely easy interfaces with motors and sensors.  This makes it ideal for running a closed loop System. (See Control of Mobile Robots class for details).

raspberrypiConnected to the Arduino will be a Raspberry Pi. The Pi will be the brains of the Robot. All higher order problem solving will occur here.  The brain and the spinal cord will talk to each other using SPI.  Naturally the Raspberry Pi will be the master of the SPI bus.  As the robot gets more complex, it might be necessary to attach more than one microcontroller (maybe not all arduinos)… especially if I start working with more complex sensors.

shapelockThe supports and overall skeleton of my robot will be created with Shape Lock.  It’s a material that can be melted, shaped and re-used over and over.  It claims to be machinable (using my dremmel) and durable.  I imagine that if I need stronger load bearing parts, I can prototype in shape lock and carve some other material based on the prototype.  Wood is a likely candidate.

Okay. The big pieces are out of the way.  Now the fun stuff.  What sensors / servos will I use?  I have a variety of electric motors, solenoids and steppers that I picked up from Adafruit. It’s likely that my first robot will be a simple differential drive deal.. but eventually I’d like to go back to my ideas in the original blog post and create a spherical robot.   In the end, the actual drive system and sensors don’t matter that much… they’re just the accessories of the Mr. Potato head.  All interchangeable.

Perceptrons as a digit classifier

perceptron-diagIt’s been a while since I posted.  I’ve continued to mess around with Machine Learning.  As a seemingly natural extension of Andrew Ng‘s class, I took Geoffrey Hinton‘s Neural Networks for Machine Learning class.  I have to say, it totally blew my mind.  If we haven’t already gotten to a near-sentient AI, I’m convinced that we’re very close.

For my own exploration of Machine Learning, I’ve decided to work through the family of neural network types in a similar order to the sequence presented in Geoffrey Hinton’s class.  That means, that I start with the very first type of neural network, the Perceptron.

A Perceptron takes multiple input values and makes a single logistic decision about it.  I took a collection of MNIST digits to see how well a Perceptron would do at identifying them.  You’d imagine that this would be a natural fit for a Perceptron as digits are reasonably distinct… but I discovered that there really is not enough information stored within the weights of a perceptron to make it an effective classifier for MNIST.

Here’s what the perceptron weights looked like for number 3. White means positive coefficients and black means negative.  Gray means near-zero.  The images read from left to right and represent the state after increasing batches of 1000 labeled cases.

perceptron-0.5

Here you can see that the more batches you run against the perceptron, the more complex the weights get.  These complexities are probably overfitting. I thought, meh. Let me see how well it performed.  Now, as 3s only represent about 10% of the label data, if I always guess “Not a 3″, I would see a 90% correct guess.  This means that I wanted a value higher than 90%. It turns out that my classifier scored 90.26% which caused me to suspect that my perceptron had guessed all 0s.   From actually looking at the guesses, though, I realized that no… the perceptron was actually guessing based on data, so I needed to dig a bit more into what it was doing.   Here’s the distribution of its answers:

Correct Negative: 4034
Correct Positive: 479
False Negative: 466
False Positive: 21

So for real, it was guessing right about 90% of the time.  What screws it over ends up being its false negatives.  blah.

I decided to try something.  Instead of weighting positive and negative cases equally when determining weights, I thought that I would add a term called alpha which weights positive and negative cases differently.  In this case, since the positive case only happens one in 10 times, I wanted to weight the negative cases by 1/10th, so I set alpha to 0.1.

perceptron-0.1

Here is an image of the coefficients using the values weighted by alpha.  You can see that, especially in the earlier batches that the shape of the 3 is a lot fuzzier and we have less complexity, even in the later iterations.  So how well did THIS set of coefficients work?

Correct Negative 3962
Correct Positive 472
False Negative 538
False Positive 28

It seems like it did a lot worse.  It had a lot more false negatives. The false positives and correct positives also dropped but not by much.  It seems like the fuzzier coefficients caused the perceptron to be less certain about a particular trial.

 

Happy Birthday, Bob Ross!

Today would be Bob Ross‘s 70th birthday. 

For those of you who aren’t familiar with Bob Ross, he was an artist who’s best known for his PBS show, The Joy of Painting.  I’d say that Bob Ross informed a LOT of my creative processes growing up. I’d watch this show religiously even though my family would never have been able to afford oil paints or canvas.   For a short while, I tried to reproduce his techniques with poster paint and notebook paper, but without much success.

According to the wikipedia article, Bob spent time in the Air Force before dedicating himself to painting.  It’s hard to imagine the painter in a military environment… but apparently, he got quite a lot of the inspirations for his famous landscapes from where he was stationed in Alaska.

Happy Birthday, Bob.  Thank you for being such an inspiration.

 

SparkFun Color LCD Shield – First Impressions

I picked up a SparkFun Color LCD Shield while I was shopping for some sensors and battery packs.  I thought that maybe I could use it to help visualize sensor data prior to passing it off to my Raspberry Pi.

The shield itself didn’t come with headers… which is okay, because I had a few extra from a purchase I made from adafruit. A short solder job later, It’s plugged into my Uno.

I grabbed the Arduino library from github, plugged it in and tried to run the examples.  Initially, the board didn’t seem to function, but after reading the documentation a little more, I realized that sparkfun ships one of two different models. I happened to get one that didn’t run with the default code. The change to the examples is extremely trivial.  You change the following line:

lcd.init(EPSON);

to

lcd.init(PHILLIPS);

One thing that I noticed about the shield… the updating is very slow, so you have to be extremely mindful of how you want to change your pixels. Simply clearing the display has a visible redraw. I wrote a short program to play around with the buttons on the shield. Essentially, it just draws or undraws rectangles based on whether or not buttons are pressed. Here’s the code itself.  If you try it out, you can see what I mean about the redraw rate.  Either this is an artifact of the sparkfun library or it’s a limitation of the device itself. I guess I can look at the library and see if there’s anything obvious.

#include <ColorLCDShield.h>
LCDShield lcd;

byte cont = 40;  // Good center value for contrast
int lastS1 = 0;
int lastS2 = 0;
int lastS3 = 0;

void setup() {
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
  pinMode(4, INPUT);
  digitalWrite(4, HIGH);
  pinMode(5, INPUT);
  digitalWrite(5, HIGH);

  lcd.init(PHILLIPS);  
  lcd.contrast(cont);
}

void loop() {
  int s1 = digitalRead(3);
  int s2 = digitalRead(4);
  int s3 = digitalRead(5);

  if (s1 == lastS1 && s2 == lastS2 && s3 == lastS3) {
      return;
  }

  if (s1 != lastS1) {
    if (s1) {
      lcd.setRect(80, 35, 131, 51, 1, WHITE);
    } else {
      lcd.setRect(80, 35, 131, 51, 1, CYAN);
    }
    lastS1 = s1;
  }

  if (s2 != lastS2) {
    if (s2) {
      lcd.setRect(80, 67, 131, 83, 1, WHITE);
    } else {
      lcd.setRect(80, 67, 131, 83, 1, MAGENTA);
    }
    lastS2 = s2;
  }

  if (s3 != lastS3) {
    if (s3) {
      lcd.setRect(80, 99, 131, 115, 1, WHITE);
    } else {
      lcd.setRect(80, 99, 131, 115, 1, BLUE);
    }
    lastS3 = s3;
  }
}

Perception and PCA

In Machine Learning, you can use Principal Component Analysis as a lossy transform that lets you reduce the complexity of data in order to improve the performance of computationally expensive operations.

So like, what does PCA actually do? It crunches multiple dimensions into a single dimension.  Consider for a moment the idea of BMI, or Body/Mass Index.  It takes 2 dimensions, mass and height and crunches them into a single dimension which somewhat describes both.  The diagram to the right kind of expresses this idea of shrinking the number of dimensions.  Here, Dimension X is a conglomerate of Dimensions A and B such that position x corresponds to point a on Dimension A and point b on Dimension B.

As I’ve learned more about algorithmic learning, I’ve found myself believing that really, we humans learn in similar ways.  This led me to the observation that perhaps the 4 spacial dimensions of space-time may actually not actually be “real” dimensions at all. Maybe our brains take in the high-dimensionality described by String Theory and collapse it, through electro-chemical processes similar to PCA into the 4 dimensions we interact with.

It could be that the world we live in is far more complex than we perceive. We could be thinking in the blue Dimension X when really we exist in A and B.

Booting my Raspberry Pi

Yeah I spent the $35 to get myself a Raspberry Pi. Here it is!

Admittedly, It’s taken me a bit longer than I’d have expected to get it to boot.  First, I bought the wrong USB power cable.  I thought that the connector was a “Mini-USB” but really it was a “Micro-USB”. You’d think that with the volume of electronics I own, I’d know the difference between the two… but you’d be wrong.

My next folly was with the operating system.  First I tried the Arch Linux build, but for some reason, it didn’t copy to my SD card properly. My instinct was that the Amazon Basics SD Card wasn’t compatible for some reason or another, but that was a false trail.  I instead copied the recommended Raspbian “Wheezy” image… and viola! I have it booting!

Here’s a screen shot part way through the boot.  The Composite Video output doesn’t seem to line up very well with my old Dell monitor.

The boot process is pretty swift and the distribution automatically DHCPs a network address and starts sshd, so it’s possible to ssh in as soon as it finishes coming up.

Once inside, I poked around a little bit. Here’s the CPU info

pi@raspberrypi ~ $ cat /proc/cpuinfo
Processor	: ARMv6-compatible processor rev 7 (v6l)
BogoMIPS	: 697.95
Features	: swp half thumb fastmult vfp edsp java tls 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xb76
CPU revision	: 7

Hardware	: BCM2708
Revision	: 0002
Serial		: 0000000048e7f498

I distinctly remember commenting that a “100mhz computer with 128 megs of ram will always make a good linux box.” Here’s a linux box that has way way more as far as capabilities… for $35. Maybe we’ve reached the future.

When is Math.abs(x) < 0?

I was monitoring a long running Hadoop job yesterday at work when I began noticing one of the tasks which make up that job began failing for an odd reason: Illegal Partition.

For those of you not familiar with Hadoop jobs, part of it involves splitting up massive amounts of data into smaller, more manageable pieces; or partitioning the data.  The goal of partitioning is to get N roughly equal chunks where N is generally pretty big.

The specific illegal partition value that was coming up was negative. “But that’s not possible!” I thought to myself! The expression I was using to choose partitions used Math.abs(x), or the Absolute value of x.  Specifically:

partition = Math.abs(x) % N

Ok, now at a glance, you tell me how that could be negative… It turns out though, that for at least a critical value of x, Math.abs(x) will return negative: Integer.MIN_VALUE.

As it turns out, Integer.MIN_VALUE is the smallest value that a 32-bit number can hold in java: -2,147,483,648. and if you try to Math.abs(Integer.MIN_VALUE), the result is STILL Integer.MIN_VALUE.  Is this a bug? It turns out that it’s not.  If you read the javadoc for Math.abs(), it points out that:

“Note that if the argument is equal to the value of Long.MIN_VALUE, the most negative representable long value, the result is that same value, which is negative.”

Now, exactly why is that the case?  Well, for you to get the absolute value of Integer.MIN_VALUE, you’ve got to be able to represent the result as a 32-bit integer too… which is impossible, as the largest integer you could possibly represent is 2,147,483,647 which is one smaller than we need it to be.  Maybe this was coded so that the Integer.MIN_VALUE would be preserved?  I decided to look at the source.

So … here’s the implementation:

public static int abs(int a) {
    return (a < 0) ? -a : a;
}

Okay… that’s a much simpler than what I thought it’d be, however it does point out that it’s not just Math.abs(x) that has this problem… it’s any negation of Integer.MIN_VALUE.  Anotherwords, the following must be a true expression:

Integer.MIN_VALUE == -Integer.MIN_VALUE

Give it a shot if you don’t believe me, fire up eclipse and try it out!  In fact, eclipse will highlight the expression with a warning that says “Comparison of identical expressions”.

Okay… I’m not sure how i feel about this.  so WWCD? (What would C do?) … so I gave it a shot… Here’s a C program that exercises this exact question:

int main(int argc, char *argv[]) {
    int x = -2147483648;
    int y = -2147483647;
    printf("X: %d %d\n", x, abs(x));
    printf("Y: %d %d\n", y, abs(y));
}

What do you think the answer is?  It actually surprised me a little:

X: -2147483648 -2147483648
Y: -2147483647 2147483647

It seems like C behaves the same way.  Apparently this isn’t just a Java problem.  Bottom line? watch and test around -2,147,483,648. It’s a critical value.

Evil Robots – It’s all in the LEDs

By picking up machine learning and micro-controllers, I’ve found myself at a juncture.  A natural spot where these two hobbies naturally coincide.  Robots.

I can honestly say that I’ve never really thought much about Asimov or his three laws of Robotics until this point.  So… what are these three laws? and what the hell do they do?

  1. A robot may not injure a human being or, through inaction, allow a human being to come to harm.
  2. A robot must obey the orders given to it by human beings, except where such orders would conflict with the First Law.
  3. A robot must protect its own existence as long as such protection does not conflict with the First or Second Laws.

They make perfect sense right? These laws make it clear that robots shouldn’t harm humans.  The thing is, though… that a huge body of sci-fi exists which totally disregard putting the three laws.  Seriously.  I bet you could name at least three evil robots.  Why didn’t their creators program in the 3 laws?  Well, primarily, it’d make for a pretty boring plot… but I actually think that in real life, we won’t see robots programmed with the three laws because well… these laws are hard to code! I mean, how do you even begin to go about coding them?  I have a more obvious and far easier way of preventing evil robots from taking over — DON’T USE RED LEDS!

Let’s take a look at some well known evil robots and let’s see if we can identify a common characteristic. Ok?

Probably the first evil AI that comes to mind is the HAL 9000.  This lovable computer from Arthur C. Clarke’s 2001 attempts to kill the entire crew of the spacecraft, Discovery.  It would have succeeded too, if it wasn’t for a meddling kid named Dave Bowman.

I’m not a huge Kubrick fan, but I must admit that he did an excellent job of making HAL seem very creepy.  You’ll note that the camera mysteriously has a bright red LED glowing right smack in the middle.  I’m not really sure how a camera can operate with light bring projected through its aperture, but meh. It’s the future… oh wait… it should have happened 11 years ago… but that’s a tangent. Bottom line. Evil AI. Red LED.

 

The second Robot AI I’d like to point out came into being about a decade after 2001: A Space Odyssey, the Cylon.  You will notice the scanning visual thingy on this robot? Yes. Red LED. It marks an entire race of sentient AIs whose entire purpose is to eradicate humanity from the cosmos.  Okay. I know what you’re thinking… didn’t KITT also have a Red LED sensor? KITT wasn’t evil! Hah.  The original version of that AI was KARR which WAS evil. KITT is just pretending to be good to piss off it’s evil twin.

Skipping forward to the 80s, we come across The Terminator. This robot is doubly evil.  It’s totally got not one but TWO red LEDs.  The Terminator is the progeny of an AI who tricked the superpowers of earth into engaging in nuclear war.  That’s not just evil… it’s totally passive aggressive too.  I’m pretty sure that SkyNET had red LEDs all over it.

Need more convincing? Okay. Let’s go.

Here are the “Squiddies” from the Matrix.  These AIs are all about rending humans limb from limb. They are basically ruthless killing machines.  Note the sheer number of red lights. I rest my case.

Red LEDs = EVIL

So like, what the hell? Why use Red LEDs at all?  It probably has to do with power. I mean, power corrupts right?  Let’s take a look at one more example.  This should hammer home the corruptive power of the red LED.

Otto Octavius, a mild mannered scientist creates an 8-limbed exoskeleton that’ll revolutionize the world.  He uses red LEDs for their power… but cancels it out by building a rather fragile looking anti-evil circuit into the suit.  Learn from Otto’s mistake. If you make yourself some kinda futuristic, armored, super-powered exoskeleton? DON’T MAKE THE ANTI-EVIL CIRCUIT THE MOST FRAGILE PART!

So okay.  What happens if we don’t use red LEDs? Are there any example of powerful robots who don’t have them? Maybe we *NEED* to use red LEDs… I’ll leave you with one final image.  You come to your own conclusions.

 

Approximating complex functions using Linear Regression

So far I’ve only been validating my Linear Regression algorithm using actual linear data.

Something that was pointed out in Andrew Ng‘s class was.. though linear regression is inherently… well… linear, the dataset that you try to learn against need not be data scattered around a straight line.  It all depends on what features you use.

I was curious to see what kind of functions I could have skynet approximate… so I chose two.  e^x and sine(x).  You can see in the picture above, I generated a largely scattered dataset around a small section of e^x. The blue line running through the center are the values generated by my hypothesis.  The features used in this case were created by raising x to higher powers (in this case, up to x^15)… anotherwords, my features were: x, x^2, x^3 … x^15.

You can see that the hypothesis here is definitely NOT linear.  Pretty impressive.

Here’s a much tougher function to approximate… however the 16 higher order features came pretty close to htiting sin(x).  I bet if I included factorial terms in the feature set, linear regression would have figured out the taylor series that makes up sin(x).

I played around with the regularization term, lambda in each of these plots, but surprisingly, it didn’t affect the hypothesis that much.  It might be because the test data that I generate is not terribly ambiguous, so even regularized, the cost functions don’t change shape very much… they’re just translated upward slightly.

Added Logistic Regression to Skynet

Skynet has continued to progress.  I’ve now validated my Logistic Regression code.

To the left you can see some label data plotted.  The blue is labeled true and red false.

This iteration of code improves the Sketchpad class significantly.  Arrow keys now allow you to move forward and backward between the different plots and the name of the actively displayed graph is displayed in the upper left corner.  Previously, the Sketchpad only drew circles, but I’ve added the ability for it to draw squares and Xs (took a page from Octave).

Okay, so how did the logistic regression do?  You can see to the right the hypothesis plotted.  It comes pretty darn close with 98.7% correctly labeled with a modest iteration count of 1.5k

Maybe it was because a large portion of the code is shared, I found that once the underlying math was solid, Logistic Regression just worked.   If I crank up the iterations to 10x, I get a 99.9% of my data correctly labeled.  At 15x, I achieve 100%.

Obviously this is an extremely simple dataset.  It was generated by labeling anything to the right of a slope to be true… so for more complex datasets, I’m sure 100x iterations or more will be necessary.  I definitely feel the need to crack open the Numerical Recipes book and find more sophisticated function minimizing algorithm.

At 100k iterations, the Gradient Descent process took a noticeably longer time to compute for Logistic Regression than a comparable Linear Regression counterpart.  I’m guessing that this has to do with a more mathematically intense Sigmoid function.   At some point, I’ll go through and profile the hell out of the code to see where my hotspots are.   My assumption is that my inefficient Matrix math will be the leading offender.. but complex math like Sigmoid or Log are likely good low hanging fruit for optimization.