clodon2
clodon2

Reputation: 61

Processing 3D Local Rotation

So I am trying to emulate a robotic arm in Processing, and have most of it working. The problem I'm having is that the last arm segment (excluding the pinchers) needs to rotate along it's own relative y-axis. My current implementation rotates on the y-axis after translating, and the solution works IF the arm segment is at a position where x and z are 0.

The problem is if the arm is rotated off of {0, y, 0}, the y rotation appears to apply relative to the bottom of the segment? I'm not exactly sure why this is happening.

Arm segment location calculation:

public float[] getArmPiecePos(ArmPiece parent, ArmPiece child){
float x_child = sin(child.total_rotation[2]) * (child.size[1] / 2) + sin(parent.total_rotation[2]) * (parent.size[1] / 2);
float y_child = - cos(child.total_rotation[2]) * (child.size[1] / 2) - cos(parent.total_rotation[2]) * (parent.size[1] / 2);
float z_child = sin(child.total_rotation[1]) * (x_child);
x_child *= cos(child.total_rotation[1]);
float x = x_child + parent.x;
float y = y_child + parent.y;
float z = -z_child + parent.z;
float[] final_pos = {x, y, z};

return final_pos;

Arm segment translation + rotation:

pushMatrix();
float[] piece_pos = mf.getArmPiecePos(this.parent, this);
this.x = piece_pos[0];
this.y = piece_pos[1];
this.z = piece_pos[2];
translate(this.x, this.y, this.z);
rotateX(this.total_rotation[0]);
rotateY(this.total_rotation[1]);
rotateZ(this.total_rotation[2]);
fill(100);
box(this.size[0], this.size[1], this.size[2]);
popMatrix();

Default Arm Pos:

Default Arm Position

Intended Effect:

Intended Effect

Actual Effect:

actual arm effect

Project: https://github.com/clodon2/LeArmSimulator

Upvotes: 2

Views: 73

Answers (2)

Neil Butcher
Neil Butcher

Reputation: 608

I believe that the code shown performs the translation first and then the rotation.

These 2 operations need to happen in the correct order (they do not commute).

Performing the translation first then the rotations (which will be around the original origin) will introduce an unexpected displacement; performing the rotations in the wrong order will also confuse the result.

I'm not sure how your rotate#, translate and this.# are all implemented, but try to fix the ordering.

Maybe just reverse the translation and rotation:

rotateX(this.total_rotation[0]);
rotateY(this.total_rotation[1]);
rotateZ(this.total_rotation[2]);
translate(this.x, this.y, this.z);

But it may need a more elaborate change (it's possible the translation needs to be split into before-rotation and after rotation-parts; or the rotations are in the wrong order).

Upvotes: 0

apodidae
apodidae

Reputation: 2723

The following source code demonstrates rotation of a 3D box along the Y axis and hopefully will help solve your issue.

void setup() {
  size(600, 600, P3D);
  surface.setTitle("Rotate upper segments with horizontal mouse movements.");
}

void draw() {
  background(209);
  translate(width/2, height/2 + 100);
  box(50, 150, 30);
  pushMatrix();
  translate(0, -125);
  rotateY(map(mouseX, 0, width, -PI, PI));
  box(50, 100, 30);
  translate(0, -75);
  box(100, 50, 30);
  popMatrix();
}

Upvotes: 1

Related Questions