Sign in to follow this  
Lokeer

Errors in generating transformations for a point

Recommended Posts

I'm adding features to an existing program being worked on by a few people, and while there's no source control worth speaking of, I'd rather not reimplement too terribly much or confuse too many people if I can possibly avoid it. The problem is to move the tip of a probe to some target point. The rest of the program uses joysticks for this, but I'm experimenting with some motion planning, so I'm taking the motion from last timestep and adding another motion this timestep, and the errors propagate nastily until the probe goes flying off into the wild blue yonder. The objects in the system use transformation matrices applied in series, and the order runs like this: 1. Translate down Y axis (extend probe into the scene) 2. Rotate about Y axis (rotate about long axis of probe) 3. Rotate about X axis (swing up/down) 4. Rotate about Z axis (swing left/right) The idea is to have the probe always pass through the pivot point, while poking around in a scene. Imagine poking a stick through a hole in a fence and tapping things on the far side of the fence. Here's my code. The error tends to swing the probe tip upward vertically, and towards the center horizontally. Oddly enough, the error gets larger as the target point moves away from the origin, and stays close to zero if the target is very close to one of the coordinate axes. I don't expect any rotation more than about 60 degrees in X or Z, but I've been getting errors of of up .3% at the edges of my workspace, and closer to .05% in the areas I often use. (for a hard sample, when pointing at (-2, 2, 0) from (0,0,6), I get an error of .0897)
void CProbeGrasper_LTE::MoveTo(VECTOR& target, float distFromTip) {
  // get the coordinate frame for the probe's origin
  VECTOR frameBase=frame->GetWorldPosition();
  VECTOR frameX=frame->GetWorldVector(VECTOR(1,0,0).v);
  VECTOR frameY=frame->GetWorldVector(VECTOR(0,1,0).v);
  VECTOR frameZ=frame->GetWorldVector(VECTOR(0,0,1).v);
  // vector to the target point
  VECTOR baseToTarget=target-frameBase;

  // convert baseToTarget into frame coordinates, and extract local X, Y, and Z.
  double xProjection=frameX*baseToTarget;
  double yProjection=frameY*baseToTarget;
  double zProjection=frameZ*baseToTarget;

  // compute the angles.  Using atanf doesn't do any better.
  double degreesZ=atan2(-zProjection,yProjection)*DEGS_PER_RAD;
  double degreesX=atan2(-xProjection,yProjection)*DEGS_PER_RAD;
  double dist=baseToTarget.Normalize();

  // despite odd names, this works.  "degreesX" means "degrees from the X axis,
  // in the XY plane", while SetXRotation means "rotation about the X axis".
  probe->SetXRotation(degreesZ);
  probe->SetZRotation(degreesX);
  probe->SetInsertion(-dist-distFromTip);
}

At first I thought this was just floating-point roundoff error, but after switching to double-precision (the VECTORs are still floats, but the roundoff error would be largest in the angle calculations), I'm getting exactly the same degree of error. (And considering that floats are supposed to be good for 6 significant figures, and the errors are creeping in at the 3rd or 4th significant figure, it's probably something else.) Do I need to toss in a little extra compensation to make up for the order of matrices? Thanks in advance!

Share this post


Link to post
Share on other sites
The code for both is trivial: the CRotation_LTE class simply stores the axis of the rotation, and the number of degrees to rotate by. SetXRotation(double deg) looks like this:
void CProbe_LTE::SetXRotation(double degrees) {
mXRotation=degrees;
mpXTipRotation->SetAngleD(mXRotation);
TransformAltered();
}
void CRotation_LTE::SetAngleD(double deg) {
rotation[0]=deg;
}
void CSceneNode_LTE::TransformAltered() {
mTransformAltered=true;
mInvTransformAltered=true;
}


TransformAltered() simply sets two boolean flags to note that the transformation matrix for the object has altered, and will have to be recalculated in the next timestep.

SetZRotation is the same. We keep the tranformations about each axis separate, so Each of the transformation classes we use calls a Transform() method on request, which for CRotation_LTE, just calls glRotatef(rotation[0], rotation[1], rotation[2], rotation[3]).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this