Make a longer arm

edited May 11 in How To...

So i'm working on something like this example:

https://processing.org/examples/arm.html

I was wondering how one could program a longer arm. As in more arm parts. I'm pretty okay with programming but this is still a bit above what i'm capable of...

This is what i'm trying to do:

http://i.imgur.com/6pJJxhu.png

Answers

  • In the example, the angles the arms bend depend on the position of the mouse.

    This works well because the mouse has an X and a Y component, each of which controls the angle for one of the arms.

    If you are going to have an arm with more segments, you will need to determine how the angle those segments make is determined. Then you just need to do more arm segments!

    Here's an example of me extending the example so that it starts with a segment who's angle depends on how much time has passed:

    float x, y;
    float angle0 = 0.0;
    float angle1 = 0.0;
    float angle2 = 0.0;
    float segLength = 100;
    
    void setup() {
      size(640, 360);
      strokeWeight(30);
      stroke(255, 160);
    
      x = width * 0.3;
      y = height * 0.5;
    }
    
    void draw() {
      background(0);
    
      angle0 = map(abs(-5000+millis()%10000),0,5000,-HALF_PI,HALF_PI); 
      angle1 = (mouseX/float(width) - 0.5) * -PI;
      angle2 = (mouseY/float(height) - 0.5) * PI;
    
      pushMatrix();
    
      segment(x, y, angle0); 
      segment(segLength, 0, angle1);
      segment(segLength, 0, angle2);
      popMatrix();
    }
    
    void segment(float x, float y, float a) {
      translate(x, y);
      rotate(a);
      line(0, 0, segLength, 0);
    }
    
  • edited May 19

    If you want your robot arm to have multiple segments connected by joints -- eg like a chain -- consider using the Box2D Library For Processing

    https://github.com/shiffman/Box2D-for-Processing

    See this discussion answer for a general idea of using Box2D to model a multi-segment jointed object:

    https://gamedev.stackexchange.com/a/50324

  • edited May 19

    Yeah, well, unless you want to do all the math, stick to Box2D or one of the other libraries to do realistic simulations (unless you're really gonna stick to some simple, boring idea).

  • @Rutger1

    One needs to defined how the different parts of your arm interact with each other. You will need to work with the concept of forces and in this case, you need to work with the concept of torques. Imaging your 5-piece arm all coiled up, or the tip of the arm driven to the beginning of the arm, toward the main pivot point. How will the other parts behave? When doing this type of programming, you will need to design your program to manage all the interactions of your robotic arm. This is why it is suggested to look at box2D library as it does all the work for you. If you want to stick to processing code and do all the calculations yourself, then you should stick to TfGuy44 example and master his code and then take it from there.

    For box2D check: http://natureofcode.com/book/chapter-5-physics-libraries/ and go to section 5.11 and 5.18 just to have a glimpse...

    Interesting enough, your multiple arm idea is a simple approach or how a cord (a string line) will behave if there was not gravity. Here on Earth, you will need to include the downward pulling force so you system will be acting under some constrains. In other words, you will need to put extra code to make it work on Earth ;;)

    Kf

  • Hello,

    an arm with segments can be done easily using a Logo turtle approach.

    see

    https://en.wikipedia.org/wiki/Logo_(programming_language)#Turtle_and_graphics

    The hard part is to make it follow the mouse, I haven't done this yet.

    you could direct each angle with keyboard keys though.

    here is an example with random movements using Logo turtle approach (forward, left). Press any key.

    Best, Chrisir ;-)

    /**
     * this is for a robot arm: 
     * https://forum.processing.org/two/discussion/22518/make-a-longer-arm#latest
     * using Logo Turtle approach : 
     * Turtle3D RectBox
     * 2017-02-07 by Jeremy Douglass - Processing 3.2.3
     * https:// forum.processing.org/two/discussion/20706/how-3d-turtle-like-in-logo-but-3d-math-problem
     */
    
    color RED = color(255, 2, 2); 
    color GREEN = color(0, 255, 2); 
    color BLUE = color(2, 2, 255);
    
    color GRAY = color(127); 
    color DARKGRAY = color(90);
    color LIGHTGRAY = color(167);
    
    color WHITE = color(255); 
    color BLACK = color(0); 
    
    // when I grow up I'll become a class 
    int max=6; 
    float[] angles= new float [max];
    float[] movement= new float [max];
    PVector[] position = new PVector[max]; 
    // must have max or more colors: 
    color[] colorsSegment = {
      RED, GREEN, BLUE, WHITE, 
      LIGHTGRAY, DARKGRAY, GRAY, RED, 
      GREEN, BLUE, WHITE, LIGHTGRAY, 
      DARKGRAY, GRAY, 
      RED, GREEN, BLUE, WHITE}; 
    
    boolean movementAllowed = false; 
    int timeStart;
    
    // ---------------------------------------------------------
    
    void setup() {
      size(1300, 800);
      strokeWeight(5);
      init();
    }
    
    void draw() {
      background(192);
    
      fill(0); 
      text("press any key", width/2, 330);
    
      if (millis()-timeStart>1000) {
        movementAllowed=true;
      }
    
      pushMatrix();
      translate(width/2, height-10) ;
      left(90); 
      robotArm();
      popMatrix(); 
    
      for (int i=0; i<angles.length-1; i++) {
        noStroke(); 
        fill(LIGHTGRAY); 
        ellipse(position[i].x, position[i].y, 11, 11);
        fill(BLACK); 
        ellipse(position[i].x, position[i].y, 3, 3);
      }
    }
    
    // ------------------------------------------------------
    
    void robotArm() {
    
      int lengthSegment = 90; 
    
      fill(0); 
      noStroke(); 
      // x,y are swapped here 
      rect(-10, -30, 10, 60);  
    
      pushMatrix(); 
    
      // display 
      for (int i=0; i<angles.length; i++) {   
        segment (angles[i], lengthSegment, colorsSegment[i]);
        position[i]=new PVector( screenX(0, 0), screenY(0, 0) );
      }
    
      // move the arm 
      if (movementAllowed) {
        for (int i=0; i<angles.length; i++) { 
          // move the arm 
          angles[i]+=movement[i];
          // boundaries 
          if (angles[i]>70) 
            movement[i]=-abs(movement[i]);
          if (angles[i]<-70) 
            movement[i]=abs(movement[i]);
        }
      }
      popMatrix();
    
    
      //
    }
    
    void segment( float angle, int lengthSegment, color col ) {
      // one segment of the arm 
      stroke(col);
    
      right(angle);
      forward(lengthSegment);
    }
    
    // -----------------------------------------------------
    
    void keyPressed() {
      movementAllowed=false; 
      timeStart=millis();
      init();
    }
    
    // -----------------------------------------------------
    
    void init() {
      for (int i=0; i<angles.length; i++) { 
        angles[i]=random(-75, 75);
        movement[i]=random(-1.3, 1.3);
      }
    }
    
    // -----------------------------------------------------
    // turtle functions 
    
    void forward(int x) {
      line(0, 0, x, 0);
      translate(x, 0);
    }
    
    void forwardJump(int x) {
      translate(x, 0);
    }
    
    void left(float amount) {
      // expects degree
      rotate( - radians(amount));
    }
    
    void right(float amount) {
      // expects degree
      rotate(radians(amount));
    }
    //
    
  • edited May 21

    @kfrajer Yes, but for more intuitive movement of a string, you need to have finite elasticity = more work :D

  • Did you try mine?

    What do you mean by finite elasticity?

  • I just realized that the initial example also works with a kind of Logo turtle in that the coordinates do add up

  • and mouse support using none mouse button, left mouse button and right mouse button

    /**
     * this is for a robot arm:
     * 
     * https://forum.processing.org/two/discussion/22518/make-a-longer-arm#latest
     * using : 
     * Turtle3D RectBox
     * 2017-02-07 Jeremy Douglass - Processing 3.2.3
     * https:// forum.processing.org/two/discussion/20706/how-3d-turtle-like-in-logo-but-3d-math-problem
     */
    
    // constants 
    color RED = color(255, 2, 2); 
    color GREEN = color(0, 255, 2); 
    color BLUE = color(2, 2, 255);
    
    color GRAY = color(127); 
    color DARKGRAY = color(90);
    color LIGHTGRAY = color(167);
    
    color WHITE = color(255); 
    color BLACK = color(0); 
    
    // when I grow up I'll become a class 
    // data on the segments
    int max=6; 
    float[] angles= new float [max];  // all in degree
    float[] movement= new float [max];
    PVector[] position = new PVector[max]; 
    // must have "max" or more colors: 
    color[] colorsSegment = {
      RED, GREEN, BLUE, WHITE, 
      LIGHTGRAY, DARKGRAY, GRAY, RED, 
      GREEN, BLUE, WHITE, LIGHTGRAY, 
      DARKGRAY, GRAY, 
      RED, GREEN, BLUE, WHITE}; 
    
    
    boolean movementAllowed = false; 
    int timeStart;
    int timeDuration=990;
    boolean autoReset = false; 
    
    // ---------------------------------------------------------
    
    void setup() {
      size(1300, 800);
      strokeWeight(5);
      init();
    }
    
    void draw() {
      background(192);
    
      mousePressedCall();
    
      fill(0); 
      textAlign(CENTER); 
      text("press any key for a random form\n\n"
        +"move mouse x,y for segments 0&1\n"
        +"click left mouse button and move mouse x,y for segments 2&3\n"
        +"click right mouse button and move mouse x,y for segments 4&5\n", 
        width/2, 130);
      textAlign(LEFT);
    
      if (millis()-timeStart>timeDuration) {
        // movementAllowed=true;
      }
    
      if (autoReset) {
        if (random(100)>97)
          init();
      }
    
      pushMatrix();
      translate(width/2, height-10) ;
      left(90); 
      robotArm();
      popMatrix(); 
    
      // show the joints extra 
      for (int i=0; i<angles.length-1; i++) {
        noStroke(); 
        fill(LIGHTGRAY); 
        ellipse(position[i].x, position[i].y, 11, 11);
        fill(BLACK); 
        ellipse(position[i].x, position[i].y, 3, 3);
      }
    
      for (int i=1; i<angles.length; i++) {
        // too far down? 
        if (position[i].y>height-30) {
    
          // too far down on right side?
          if (position[i].x>width/2+10) {
            // right side
            // make the joint before go left
            int i3=i-1;
            movement[i3]=-abs(movement[i3]);
            // Or make all the joint before it go left
            for (int i2=i-1; i2>0; i2--) {
              // movement[i2]=-abs(movement[i2]);
            }
          } else {
            // left side
            // make the joint before go right
            int i3=i-1; 
            movement[i3]=abs(movement[i3]);
            // Or make all the joint before it go left
            for (int i2=i-1; i2>0; i2--) { 
              // movement[i2]=abs(movement[i2]);
            }
          }
        }
      }//for
      //
    }
    
    // ------------------------------------------------------
    
    void robotArm() {
    
      int lengthSegment = 90; 
    
      // the box the arm is standing on 
      fill(0); 
      noStroke(); 
      // x,y are swapped here 
      rect(-10, -30, 10, 60);  
    
      pushMatrix(); 
    
      // display 
      for (int i=0; i<angles.length; i++) {   
        segment (angles[i], lengthSegment, colorsSegment[i]);
        position[i]=new PVector( screenX(0, 0), screenY(0, 0) );
      }
    
      // move the arm 
      if (movementAllowed) {
        for (int i=0; i<angles.length; i++) { 
          // move the arm 
          angles[i]+=movement[i];
          // boundaries 
          if (angles[i]>70) 
            movement[i]=-abs(movement[i]);
          if (angles[i]<-70) 
            movement[i]=abs(movement[i]);
        }
      }
      popMatrix();
      //
    }
    
    void segment( float angle, int lengthSegment, color col ) {
    
      // one segment of the arm 
    
      stroke(col);
    
      right(angle);
      forward(lengthSegment);
    }
    
    // -----------------------------------------------------
    
    void keyPressed() {
      movementAllowed=false; 
      timeStart=millis();
      init();
    }
    
    void mousePressedCall() {
    
      int index0=0;
      int index1=1;
      if (mouseButton==LEFT) {
        index0=2;
        index1=3;
      } else if (mouseButton==RIGHT) {
        index0=4;
        index1=5;
      }
    
      // formula for degree
      float calcAnglesIndex0  = (mouseX/float(width) - 0.5) * (2*70); // those 2 do the same thing  
      float calcAnglesIndex1  = map ( mouseY, 0, height, -70, 70);
    
      // 
      angles[index0] += calcAnglesIndex0-angles[index0] ; 
      angles[index1] += calcAnglesIndex1-angles[index1] ;
    }
    
    void mousePressedCall_Old_Version() {
    
      int index0=0;
      int index1=1;
      if (mouseButton==LEFT) {
        index0=2;
        index1=3;
      } else if (mouseButton==RIGHT) {
        index0=4;
        index1=5;
      }
    
      // formula for degree
      angles[index0] = (mouseX/float(width) - 0.5) * (2*70);
      angles[index1] = map ( mouseY, 0, height, -70, 70);
    }
    
    // -----------------------------------------------------
    
    void init() {
      for (int i=0; i<angles.length; i++) {
    
        angles[i]   = random(-75, 75);
    
        movement[i] = random(0.3, 1.0);
        if (random(100)>50)
          movement[i]*=1;
      }//for
    }//func
    
    // -----------------------------------------------------
    // turtle functions 
    
    void forward(int x) {
      // turtle goes x steps forward drawing a line
      line(0, 0, x, 0);
      translate(x, 0);
    }
    
    void forwardJump(int x) {
      // turtle jumps x steps forward without drawing a line
      translate(x, 0);
    }
    
    void right(float amount) {
      // turtle rotates right on the spot without drawing  
      // expects degree
      rotate(radians(amount));
    }
    
    void left(float amount) {
      // turtle rotates left on the spot without drawing 
      // expects degree
      rotate( - radians(amount));
    }
    //
    
  • Nice demo @Chrisir... I like the idea that you use x-y to control two different picot points at the time.

    Kf

  • @Chrisir I think you posted your comment at the same time as mine. I never saw your comment, mine was meant to have come after @kfrajer's comment. Now it looks very awkward.

Sign In or Register to comment.