Monday, March 25, 2013

Cyclic Coordinate Descent & Forcing Maya UI Updates

Previously, I described my plan to implement an algorithm called Cyclic Coordinate Descent (CCD) and integrate it into Maya. The process was cumbersome, but I am happy to report that my attempt was successful. 

The largest source of trouble originated from understanding Maya's construction of composite matrices for object transformations and the various application programming interfaces for data types like Matrices and Quaternions. Initially, I went the route of using the Leap Motion SDK data types (Leap Vectors, Matrices, etc) to calculate the rotation angles for a joint while performing CCD. However, problems arose when I attempted to translate Maya's composite matrix (as an array of double values) into Leap Matrices and then back to a Maya Matrix after applying a rotation. Artifacts would result in the Leap Matrix that I could not remedy because the Leap SDK does not permit direct access to the data backing a matrix. 

After discovering the artifacts, I delved into Maya's data types but encountered more trouble because their interface for matrices has some of the same limitations that the Leap data types have- namely, direct access to matrix values is not possible. My latest (and successful) shift was to PyMel, a Python wrapper around Maya commands that adds the functionality that I needed.

With PyMel in place, the only other feat was Gimbal Lock. Gimbal Lock is an issue that results when using Euler angles for the rotation of 3D objects in space. Essentially, successive rotations can result in two rotation axes locking in the same plane. Subsequent rotations about these locked axes causes a single rotation to applied to the object with respect to that plane. Effectively, the object loses a rotational degree of freedom.

On the left, you see how each gimbal allows rotation around 
a specific axis. On the right, you can see a set of gimbals in 
gimbal lock. The inner-most gimbal can't change in pitch 
unless the gimbals are put into another positions. 
[Source: HowStuffWorks]
There are a number of ways to avoid Gimbal Lock such changing the order of rotation about axes after detecting when a sequence of rotations is likely to cause Gimbal Lock. I decided to use axis-angle rotation pairs and convert those into quaternions. There are two benefits to using this approach. The first is obviously that quaternions avoid Gimbal Lock;  they permit rotations to occur about an arbitrary axis in space. The second benefit (though not currently in use), is that they permit 3D rotation to be animated smoothly (Spherical Linear Interpolation).

As a secondary update, I have changed the way in which the Leap Motion controller interfaces with Maya. Originally, a listener object would compute position and rotation updates then send them in Maya Embedded Language (MEL) as a string over a socket command port linked to Maya. This implementation meant that I was performing CCD from within the Python script running in my Bash. Thus, references of the rotation and positions of joints had to be queried each time a transformation on a particular joint in the chain occurred. The logic behind this rests in the fact that an arbitrary rotation on a single joint node in a chain causes the positions of all connected children joints nodes to rotate as well; this propagation is a feature of the structure of a Scene Graph

My currently implementation places all CCD and any operations for joint transformations within the Maya python script. The Leap controller listener is only sending coordinates of end-effector positions to Maya as a string. Queries, since they are now occurring within Maya and not over a socket connection, are much faster.

A few posts back I also described an issue in the Maya UI halting on position updates. I have now found a way to solve this problem- Maya has a command called refresh permits the input of a force boolean. When force is true, the command triggers a complete update of the camera views displaying the objects in a scene. I am currently using this to visualize intermediate stages of the CCD algorithm.

References
1) Cyclic Coordinate Descent (CCD)
2) PyMel - Python-Maya Wrapper Application Programming Interface
3) YouTube: Gimbal Lock
4) How Stuff Works (Image): Gimbal Lock
4) Wikipedia: Euler angles
5) Wikipedia: Quaternions
6) Wikipedia: Spherical Linear Interpolation (Slerp)
7) Maya Embedded Language (MEL)
8) Wikipedia: Scene Graph
9) PyMel API - Refresh Command

No comments:

Post a Comment