[x3d-public] BVH to X3D import working; right-handed coordinate system

Don Brutzman brutzman at nps.edu
Tue Jan 10 06:51:33 PST 2017


Thanks for helpful feedback Joe.

On 1/9/2017 10:32 AM, Joe D Williams wrote:
> [...]
> Good work on the degrees to radians conversion steps.
> Always fun to apply some pi to it.
>
> Still wondering about that zxy to xyz order change from euler to fixed.
> Does 'fixed' really mean 'fixed' in this conversion context?

Am avoiding use of term 'fixed' since it is ambiguous.

Reference links:

	X3D Scene Authoring Hints: Coordinate Systems
	http://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html#CoordinateSystems

There were a few twists in the trail for figuring out right-handed (please) versus left-handed (shudder) coordinate system.  Lack of clear documentation greatly exacerbated this problem.

Notes:

a.  All recorded rotations were right-handed orientation about corresponding axis for phi (X axis), theta (Y axis) and psi (Z axis).

b.  All recorded rotation values for 1.bvh were in degrees.  I don't know (yet) if all BVH files are like that, not well documented and might be inconsistently applied.

c.  BVH statement "CHANNELS 3 Zrotation Xrotation Yrotation" indicates order that data appears in the file (not a left-handed coordinate system).

d.  Looking at BVH skeleton, first inspection might (incorrectly) indicate left-handed coordinate system since "Right" values are negative while height values are positive and z values are positive in forward direction of humanoid.  However it is important to remember that the humanoid is facing along the Z axis towards the default viewpoint, so it is rotated around.  Thus the negative Right values are OK, the Right side of the Human has been rotated 180 degrees (about vertical Y axis) to face the viewer.

Rephrased:  the humanoid's local coordinate system is right handed, both for individual angles and for axes.  If you stand at origin and face Z axis (out of screen) then Y is up, right hand is -X axis, left hand is +X axis, +Z is forward.

e.  Here are some code excerpts.  Sharp readers will see strict right-handed X Y Z ordering throughout.

=========================================================================

if (channelNamesString.equalsIgnoreCase("Zrotation Xrotation Yrotation") || // JOINT
     channelNamesString.endsWith        ("Zrotation Xrotation Yrotation"))   // ROOT channels 0, 1
//					           Xposition Yposition Zposition Zrotation Xrotation Yrotation      // ROOT channels 0, 1
{
     phi = values[3*channelIndex+1]; // Euler angle about X axis,  second channel
   theta = values[3*channelIndex+2]; // Euler angle about Y axis,   third channel
     psi = values[3*channelIndex+0]; // Euler angle about Z axis, initial channel
}

	AxisAngle4d axisAngle = getAxisAngleRotation( // computation is also order dependent
			  phi * Math.PI / 180.0, // degrees to radians
			theta * Math.PI / 180.0,
			  psi * Math.PI / 180.0);
	outputX3D.append(fourDigitFormat.format(axisAngle.x)).append(" ")
			 .append(fourDigitFormat.format(axisAngle.y)).append(" ")
			 .append(fourDigitFormat.format(axisAngle.z)).append(" ")
			 .append(fourDigitFormat.format(axisAngle.angle));

=========================================================================

     /**
      * Compute local AxisAngle4d SFRotation from Euler-angle rotations
	 * @see Joint#getAxisAngleRotation
      */
     public AxisAngle4d getAxisAngleRotation (double phi, double theta, double psi)
     {
             // javax.vecmath conversions (boy is this a convoluted API or what!)
             AxisAngle4d axisAngleX = new AxisAngle4d(1.0, 0.0, 0.0, phi);
             AxisAngle4d axisAngleY = new AxisAngle4d(0.0, 1.0, 0.0, theta);
             AxisAngle4d axisAngleZ = new AxisAngle4d(0.0, 0.0, 1.0, psi);

             AxisAngle4d axisAngleIdentity  = new AxisAngle4d(0.0, 0.0, 1.0, 0.0);
             Quat4d      quaternionIdentity = new Quat4d ();    quaternionIdentity.set(axisAngleIdentity);

             Quat4d      quaternionX      = new Quat4d ();      quaternionX.set(axisAngleX);
             Quat4d      quaternionY      = new Quat4d ();      quaternionY.set(axisAngleY);
             Quat4d      quaternionZ      = new Quat4d ();      quaternionZ.set(axisAngleZ);
             Matrix4d    matrixCurrent    = new Matrix4d();
             Matrix4d    matrixRotated    = new Matrix4d();    matrixRotated.set(quaternionIdentity);

             matrixCurrent.set(quaternionZ);

             matrixRotated.set(quaternionIdentity);         // TODO check order!
             matrixCurrent.set(quaternionZ);	matrixRotated.mul(matrixCurrent);
             matrixCurrent.set(quaternionX);	matrixRotated.mul(matrixCurrent);
             matrixCurrent.set(quaternionY);	matrixRotated.mul(matrixCurrent);

             Quat4d      quaternionRotated   = new Quat4d ();    quaternionRotated.set(matrixRotated);
             AxisAngle4d axisAngleRotated    = new AxisAngle4d(); axisAngleRotated.set(quaternionRotated);
             return axisAngleRotated;
     }

=========================================================================

Anyway, of course it is straightforward once we have something working.

Unnoticed symptom while debugging: wild angle value changes are always a clue that degree values are being interpreted as radians. (Conversely, unmoving/minimal angle changes are a clue that radians are being interpreted as degrees.)

Important lesson re-learned:  you get what you inspect, not what you expect.  I hadn't noticed any large-angle values until verbosely computing & reporting bounds on the BVH column data.  This is a good lesson to keep in mind, our converters should get pretty verbose and we should record conversion parameters as metadata so that we know what is actually contained in somebody else's BVH file.

Having fun with H-Anim mocap!

all the best, Don
-- 
Don Brutzman  Naval Postgraduate School, Code USW/Br       brutzman at nps.edu
Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA   +1.831.656.2149
X3D graphics, virtual worlds, navy robotics http://faculty.nps.edu/brutzman



More information about the x3d-public mailing list