browse OpenProcessing

soundTunnel
Servo Arms
Aprox reloj
browse all>

browse the portfolio of Matt Richard

Foot Sensor Data: Longboarding
Homage to Szpakowski
Sabrina
Wavy Gravy
see more>
Servo Arms

Servo Arms

uploaded by
Matt Richard
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.

Video of the arm working

Check out my blog
Embed Code
Fave'd by 1 users
Sketch added to your favorites in your portfolio.
You must login/register to add this sketch to your favorites.

comments

source code

Comments

Ted Brown
16 Jan 2010, 21:47
Thank you! Thank you thank you thank you....
Jonathan Brodsky
03 Feb 2010, 07:20
hey, I just rewrote this last night with support for prismatic joints, and in a more object oriented way, so it can be easily extended to add more segments.

the prismatics don't work too great at any position besides the base of the arm, unfortunately...



int sx,sy,ex,ey,hx,hy,hxo,hyo;
int armLength,ua,la;
float uad, lad;
ArrayList segments;
int numSegments = 4;

void setup(){
size(500,500);
segments = new ArrayList();
background(255, 224, 150);
for(int i=0;i<numSegments;i++){
Segment segment = new Segment(83.4, 10);
segments.add(segment);
}
Segment current = (Segment)segments.get(3);
current.x = 0;
current.y = 250;
current.type = 1;
current = (Segment)segments.get(1);
//current.type = 1;
}
void draw(){
background(255, 224, 150);
PVector target = reach((Segment)segments.get(0), mouseX, mouseY);
for(int i=1;i<segments.size();i++){
target = reach((Segment)segments.get(i), target.x, target.y);
}
for(int i=segments.size()-1;i>0;i--){
position((Segment)segments.get(i-1), (Segment)segments.get(i));
}
for(int i=0;i<segments.size();i++){
Segment current = (Segment)segments.get(i);
current.draw();
}
}
PVector reach(Segment segment, float xpos, float ypos)
{
float dx = xpos - segment.x;
float dy = ypos - segment.y;
if(segment.type == 0){
float angle = atan2(dy, dx);
segment.rotation = angle;
//segment.rotation += (angle-segment.rotation)*0.3;
}
else{
float h = sqrt(pow(dx, 2)+pow(dy, 2));
//println(segment.rotation);
float pinRot = atan2(segment.getPin().y-segment.y, segment.getPin().x-segment.x);
float missingAngle = PI-(segment.rotation-pinRot+(PI/2));
/*
println("pin rotation: "+degrees(pinRot));
println("segment rotation: "+degrees(segment.rotation));
println("missing angle: "+degrees(missingAngle));
*/
//float a = h*sin(missingAngle);
//segment.segmentWidth = sqrt(pow(h, 2)+pow(a, 2)-2*h*a*cos(missingAngle));

segment.segmentWidth += (h*sin(missingAngle)-segment.segmentWidth)*0.3;
}
float w = segment.getPin().x - segment.x;
float h = segment.getPin().y - segment.y;
float tx = xpos - w;
float ty = ypos - h;
return new PVector(tx, ty);
}
void position(Segment segmentA, Segment segmentB)
{
//if(segmentA.type == 0){
segmentA.x = segmentB.getPin().x;
segmentA.y = segmentB.getPin().y;
//}

//else{
if(segmentA.type == 1){
segmentA.rotation = segmentB.rotation;
}
}

class Segment{
float segmentWidth, segmentHeight, vx, vy, rotation, x, y;
int type;
Segment(float _segmentWidth, float _segmentHeight){
segmentWidth = _segmentWidth;
segmentHeight = _segmentHeight;
type = 0;
}
PVector getPin()
{
float xPos = x + cos(rotation) * segmentWidth;
float yPos = y + sin(rotation) * segmentWidth;
return new PVector(xPos, yPos);
}
void draw(){
color(255, 255, 255);
ellipseMode(CENTER);
//rotate(rotation, 0, 0, 1);
ellipse(x, y, 10, 10);
ellipse(x+cos(rotation)*segmentWidth, y+sin(rotation)*segmentWidth, 10, 10);
line(x, y, x+cos(rotation)*segmentWidth, y+sin(rotation)*segmentWidth);
}
}
Mike Wu
19 Apr 2010, 16:28
thank you for sharing!

i've also been trying to expand the code to incorporate more segments and varying segment lengths but to no avail. did you eventually succeed Jonathan?

cheers
You need to login/register to comment.