Injecting Computation to Homer Simpson

After reading Stephen Wolfram mind blowing blog post “Injecting Computation Everywhere”, I tried to reproduce some of the demos he had for his SXSW talk. The results obtained adding just a little bit of code were quite surprising to me. Here is what happened when I injected the data from an accelerometer connected to an Arduino into the Wolfram Language using a few Graphics3D directives, six spheres and a pair of tubes:

Tadaa! Homer Simpson started computing the trajectory of a three-dimensional object!

simpson.gif

To create this experiment I used the same hardware listed by Arnoud in this post “Connecting to an accelerometer over a serial connection” (but instead of connecting the Arduino to the Raspberry Pi, I used my own laptop):

Once everything has been wired follow these steps:

  • First upload the following Sketch to your Arduino:
 void setup()
 {   Serial.begin(115200); }
 void loop()
{
  long x = analogRead(0);
  long y = analogRead(1);
  long z = analogRead(2);
  Serial.write(x);
  Serial.write(y);
  Serial.write(z);
  delay(100);
}
  • Take note of the serial port name that you will be using.

  • Connect the Arduino into the Wolfram Language. (The name of my port was “usbmodemfa131”, replace it for the one you are using)

serial = DeviceOpen["Serial", {"/dev/tty.usbmodemfa131", "BaudRate" -> 115200}]
  • Check the data streamed by the Serial when the accelerometer lies flat:
Partition[DeviceReadBuffer[serial], 3]
  • Then set a function to scale the three coordinates XYZ between -1g and 1g:
g[x_] := Divide[84 - x, -84]
  • When the function is applied to the buffer’s values, and the accelerometer lies flat, the average vector should approximate {0,0,1}g
Partition[g /@ DeviceReadBuffer[serial], 3] // Mean // N
  • Once the accelerometer has been calibrated, run the following ScheduledTask every 0.1 seconds:
RunScheduledTask[ bee = Partition[g /@ DeviceReadBuffer[serial], 3] // Mean // Normalize // N, 0.1]

Now, you are ready to dynamically control Homer Simpson’s eyes :slight_smile:

Graphics3D[{
  Orange,
  Sphere[Dynamic[3*bee], 0.2],
  White,
  Sphere[eyeL = {0.1, 0.9, -2}, 1],
  Sphere[eyeR = {0.1, -0.9, -2}, 1],
  Gray,
  Sphere[Dynamic[Normalize[3 bee - eyeL] + eyeL], 0.25],
  Sphere[Dynamic[Normalize[3 bee - eyeR] + eyeR], 0.25],
  Yellow,
  Tube[{{-1, 0, -4}, {3, 0, -4}}, 2.5],
  Tube[{{0.8, 0, -1.8}, {1, 0, -0.8}}, 0.4],
  Brown,
  Sphere[{3, 0, -3}, 2.3]},
 Lighting -> {{"Ambient", GrayLevel[.1]}, {"Point", White, Dynamic[3.5 bee]}},
 ViewPoint -> {-0.8, -2.1, 2.5}, 
 ViewVertical -> {-1.2, -0.8, 0.5},
 PlotRange -> {{-4, 3}, {-3.2, 3.2}, {-7.5, 4}},
 Background -> Black,
 Boxed -> False]
8 Likes

For those of you who don’t have an Arduino but are still willing to inject computation to Homer Simpson :slight_smile: I devised the following method to emulate an accelerometer using a webcam:

homer_track.gif

redXYZ[x_] := {Divide[35 - x[[2]], 35], Divide[50 - x[[1]], -35], Divide[20 - x[[3]], 20]}

RunScheduledTask[
 bee = redXYZ[Flatten[ReplaceAll[1,
     ComponentMeasurements[
      ColorNegate[
       CommonestFilter[
        Binarize[
         ImageApply[If[#[[1]] > #[[2]] + #[[3]], #, {1, 1, 1}] &,
          ImageReflect[ImageResize[CurrentImage[], 100], Left -> Right]]
         ],2]],
      {"Centroid", "EquivalentDiskRadius"}]]]], 0.4]

After filtering the red object from the CurrentImage[], ComponentMeasurements’ “Centroid” is giving the XY coordinates and “EquivalentDiskRadius” provides the depth Z. Then, redXYZ[] calibrates the coordinates of the “bee” that is being refreshed every 0.4 seconds by the ScheduledTask.

If a red object is being detected correctly…

Dynamic[bee]

… then, you are ready to have fun playing with Homer:

Graphics3D[{Orange, Sphere[Dynamic[4*bee], 0.2], White, Sphere[eyeL = {0.1, 0.9, -2}, 1], Sphere[eyeR = {0.1, -0.9, -2}, 1], Gray, Sphere[Dynamic[Normalize[4*bee - eyeL] + eyeL], 0.25], Sphere[Dynamic[Normalize[4*bee - eyeR] + eyeR], 0.25], Yellow, Tube[{{-1, 0, -4}, {3, 0, -4}}, 2.5], Tube[{{0.8, 0, -1.8}, {1, 0, -0.8}}, 0.4], Brown, Sphere[{3, 0, -3}, 2.3], Black, Sphere[{3, 0, -0.65}, 0.5]}, Lighting -> {{"Ambient", GrayLevel[.15]}, {"Point", White, Dynamic[4.5*bee]}}, ViewPoint -> {-0.32, -1.8, 3.6}, ViewVertical -> {-1.44`, 0.12`, -0.2`}, PlotRange -> {{-4, 5.5}, {-7, 7}, {-7.5, 4}}, Background -> Black, Boxed -> False]
5 Likes