For describing a human pose independent of the relative position of the person to the camera image plane we need to step out of the global coordinate system (x,y,z) and describe the relative position of limbs in local coordinate systems (x',y',z') that are given by the parent's bone each.

This uses the fact that the human body can be described as a tree of limbs, where each branch of the tree can be considered as a more or less independent kinematic chain.

Imagine that the 3 gray/white lines below represent the 1. shoulder, 2. upper arm, and 3. lower arm of a human and the yellow sphere represents the hand.

For describing the position of the lower arm relative to the upper arm - independently from its relative position to the camera image plane - we need to establish a local coordinate system.

To do so we align the local coordinate axis x' with the *parent bone*, here: the upper arm bone, i.e. the parent bone defines the child's bone local x' axis.

Now we have a rotatory degree of freedom (DOF) for choosing the y' and z' axes. To remove this DOF we define the z' axis as the cross product (vector product) of x' and the local coordinate x axis of the shoulder.

The local coordinate axis y' then is given by the cross product of x' and z'.

(x,y,z) | world frame |

(x',y',z') | body frame |

Now we can describe the yellow point by local coordinates. To do so we need to describe its coordinates that are given in the (x,y,z) world coordinates by coordinates in the (x',y',z') local coordinate system. Thus we need a change of basis.

Thus we end up with local coordinates of the yellow point in the (x',y',z') coordinate system. These (x',y',z') coordinates are independent of the relative position of the person in respect to the camera image plane.

The following animation shows the right upper arm local coordinate system during a walking sequence. The motion capture data stems from the HumanEva motion capture database.

One can see how the local coordinates for describing the lower arm position moves relative to the world coordinate system as the upper arm bone changes its position.

For describing the position of the hand (yellow sphere) within the local coordinate system induced by the upper arm bone we can use any standard representation for points in 3D, e.g. the 3 scalar values (x',y',z').

We can also describe this point by a unit direction vector pointing into the direction of the hand plus a length representing the lower arm bone length. This would be a non-minimal description using 4 scalar values: (dirX', dirY', dirZ', LowerArmBoneLength).

Another representation that splits up the point representation into a direction + bone length component is describing it by spherical coordinates (theta, phi, r). This is a minimal representation using 3 scalar values, where theta and phi describe the direction towards the point and r the bone length.

This representation can be especially useful if we are interested in differing and recognizing different motions since we describe the direction of a joint movement by only two angles (theta, phi). Typical movement patterns of a joint between two limbs can then be identified by considering how theta and phi change independently from the bone length.

In our case the spherical reference plane is the cartesian y'–z' plane, such that the inclination theta is from the x' direction, and the azimuth angles are measured from the cartesian z' axis. So points on the y' axis have an azimuth of -phi/+phi. Compare with this defintion of inclination + azimuth. Here is the code for of conversion cartesian ↔ spherical coordinates:

/// <summary> /// Given cartesian coordinates, compute the corresponding spherical coordinates /// </summary> void MathHelper::CartToSphereCoordinates(float npx, float npy, float npz, float& theta, float& phi, float& r) { r = (float) Math::Sqrt( npx*npx + npy*npy + npz*npz ); theta = (float) Math::Acos( npx / r ); phi = (float) Math::Atan2( npy, npz ); } /// <summary> /// Given spherical coordinates, compute the cartesian coordinates /// </summary> void MathHelper::SphereToCartCoordinates(float theta, float phi, float r, float& npx, float& npy, float& npz) { npz = (float) ( r * Math::Sin(theta) * Math::Cos(phi) ); npy = (float) ( r * Math::Sin(theta) * Math::Sin(phi) ); npx = (float) ( r * Math::Cos(theta) ); }

Here is a sample showing the local coordinate system in the upper right leg bone (Femur) and the spherical coordinates of the lower leg bone (Tibia):

The local coordinates (x',y',z') are displayed, but also the corresponding spherical coordinates (theta, phi, r), where

- theta is the inclination (reference axis x')
- phi the azimuth measure within the y'-z' reference plane
- r is the bone length (only nearly constant due to motion capture data measurement tolerances)

We can now plot the two angles theta (black) and phi (cyan) and identify a typical periodic behavior synchronous with a period length identical to one walking cycle:

This shows us that the computed local right Femur coordinate system for measuring the Tibia position computed for each of the 548 motion capture frames seems to make sense. If instead it waggled around we could not identify such a periodic pattern.

As mentioned before, another way to represent a position in the local coordinate system is to use a unit direction vector plus a scalar describing the vector length. Here are the corresponding plots of the unit direction vector components (dirX',dirY',dirZ') for the same motion describing the position of the Tibia:

The following animation shows 10 local coordinate systems in the most important joints of the human body:

The definition of a child LCS should only depend on the parent LCS (which represents the parent joint configuration).

Thus for defining a new LCS (dirX',dirY',dirZ') based on

- a parent LCS (dirX,dirY,dirZ)
- and a direction (translation) vector dirBone between the parent LCS and the child LCS to be created

we set

- dirX' = dirBone / |dirBone|
- dirY' = dirX' x dirRef
- dirZ' = dirX x dirY

I.e.

- the new dirX' axis is therefore identical to the bone direction vector.
- for spanning up a plane based on dirX' we need a reference vector. Here we simply take one of the axis vectors of the parent LCS (dirX, or dirY, or dirZ)
- the third axis dirZ' is the normal vector to that plane

Here are two sample motions showing the resulting LCS in each joint:

Here are the reconstructions of the poses by the resulting pose vectors where setting the root LCS in the lower hip equal to the global coordinate system:

For choosing dirRef one can choose between always taking dirX, dirY or dirZ of the parent LCS. But choosing a fixed reference axis for spanning up a plane in the new LCS to be created one can get problems when coming to the edge case, that dirX' and dirRef are pointing in the same direction. Then the cross product

dirY' := dirX' x dirRef

is the nullvector and thus dirX' and dirY' do not span up a plane! In practice a nearly approximately same direction already leads to some randomness of the plane definition.

Here is a sample what happens in such a case when defining a LCS in the right knee joint. We have taken as dirRef the (blue colored) right hip z axis (dirZ) which points nearly into the same direction as dirX' = dirBone = RightHip→RightKnee. Thus

dirY' = dirX' x dirRef

changes fast and since

dirZ' = dirX' x dirY'

dirZ' also changes fast. One can see the resulting behavior. The y- and z-axis of the LCS in the right knee rotate fast. Compare this behavior with the left knee where we have choosen a better reference axis.

The conclusion is that we have to choose a reference axis dirRef of the parent LCS that preferably does not point into the same direction as dirX' = dirBone.

public/local_coordinate_system.txt · Last modified: 2010/09/29 15:58 (external edit) · []