Tuesday, October 21, 2008

Inverse Kinematics and Processing



Basic inverse kinematics code rewritten for processing from Keith Peters of bit-101. The idea is to replicate the motion of your shoulder, upper arm, elbow, lower arm, and hand in two dimensions. The angular value of the "shoulder" and "elbow" will be written to corresponding servo motors that are being controlled by Arduino.

Here is the code:

int sx,sy,ex,ey,hx,hy;
int armLength,ua,la;
float uad, lad;
void setup(){
size(500,500);
background(255, 224, 150);
sx = width/2;
sy = height/2;
armLength = int(width/5);
}

void draw(){
fill(255);
rect(0,0,width,height);
upperArm();
}

void upperArm(){
int dx = mouseX - sx;
int dy = mouseY - sy;
float distance = sqrt(dx*dx+dy*dy);

int a = armLength;
int b = armLength;
float c = min(distance, a + b);

float B = acos((b*b-a*a-c*c)/(-2*a*c));
float C = acos((c*c-a*a-b*b)/(-2*a*b));

float D = atan2(dy,dx);
float E = D + B + PI + C;

ex = int((cos(E) * a)) + sx;
ey = int((sin(E) * a)) + sy;
print("UpperArm Angle= "+degrees(E)+" ");

hx = int((cos(D+B) * b)) + ex;
hy = int((sin(D+B) * b)) + ey;
println("LowerArm Angle= "+degrees((D+B)));

stroke(255,0,0,100);
fill(240,0,0,200);
ellipse(sx,sy,10,10);
ellipse(ex,ey,8,8);
ellipse(hx,hy,6,6);
stroke(0);
line(sx,sy,ex,ey);
line(ex,ey,hx,hy);
}

Awesome Data Visualization Site

My friend Loren Klein sent me a link to a site called Very Small Array. The specific page shows the map of the five boroughs. Instead of the borough names, the names of States with the closest equivalent in population are used. I really recommend checking out the rest of the site.

Money Map

For my self portrait in Crafting with Data, I mapped the use of my bank card using Google Maps. I entered all of the locations I used my card during the month of September. I included the date, amount spent, and what the item purchased was.

Multi-Value Serial Communication

I want to thank Meredith for writing this post. I merely changed my name to her's.

I worked with Meredith Hasson on the serial communication lab for this week. We followed the lab instructions and did the first basic serial circuit using a flex sensor, a photo cell and a switch. We were able to get it working and thus, began to play with moving the ball around the screen.



We then changed both the Arduino and Processing code up a bit and went for snow. We made the background color change based on how much light the photocell was receiving. When it was getting lots of light, it would be a light background and when it was not receiving any light, it was a black background. The white balls were moving around based off of random numbers, but we utilized the flex sensor to decide how many balls would be present. When bent one way there were lots of balls and when bent the other there were fewer balls.



Here is our code:

Arduino:

int analogOne = 0; // analog input
int analogTwo = 1; // analog input
int digitalOne = 2; // digital input

int sensorValue = 0; // reading from the sensor

void setup() {
// configure the serial connection:
Serial.begin(9600);
// configure the digital input:
pinMode(digitalOne, INPUT);
}

void loop() {
// read the sensor:
sensorValue = analogRead(analogOne);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(”,”);

// read the sensor:
sensorValue = analogRead(analogTwo);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(”,”);

// read the sensor:
sensorValue = digitalRead(digitalOne);
// print the last sensor value with a println() so that
// each set of four readings prints on a line by itself:
Serial.println(sensorValue, DEC);
}

Processing:

import processing.serial.*; // import the Processing serial library
Serial myPort; // The serial port

float bgcolor; // Background color
float fgcolor; // Fill color
float xpos, ypos; // Starting position of the ball

void setup() {
size(640,480);
myPort = new Serial(this, Serial.list()[2], 9600);

// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil(’\n’);
}

void draw() {
//background(xpos);
fill(xpos, 50);
rect(0, 0, width, height);
fill(fgcolor);
// Draw the shape
for(int i = 0; i <= ypos; i++){
// ellipse(i*10, height/2, 10, 10);
ellipse(random(width), random(height), 10, 10);
}
}

// serialEvent method is run automatically by the Processing applet
// whenever the buffer reaches the byte value set in the bufferUntil()
// method in the setup():

void serialEvent(Serial myPort) {
// read the serial buffer:
String myString = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {

myString = trim(myString);

// split the string at the commas
// and convert the sections into integers:
int sensors[] = int(split(myString, ','));

// print out the values you got:
for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensors.length > 1) {
xpos = map(sensors[0], 190,900,1,255);
ypos = map(sensors[1], 220,540,1,200);
fgcolor = sensors[2] * 255;
}
}
}