Dear subscribers,

As this months's moderator, I feel it is now time to wrap up and

summarize this discussion. It seems that everything has been said and

we should try to end this specific topic. Below is a brief summary and

some comments on analogous issues in 3-D analysis. Please feel free to

point out any errors, and further contributions on 3-D joint angles are

certainly welcome. Who knows, we may even revive the "helical angle

wars" that took place on Biomch-L between 1989 and 1992.

Paolo de Leva's posting yesterday, elaborating on an earlier reply from

Michael Feltner, describes an elegant way to compute the angle

between two body segments, each defined by two markers. This method

uses the fact that a dot product is proportional to the cosine of the

angle between two vectors. Michael shared his Fortran code, and you

can find Matlab code for the same algorithm in the Kinemat

package, see http://www.isbweb.org/software/movanal/kinemat/angle2d.m

This technique allows a plus & minus 180 degree range of motion and

has the advantage that it also works in 3-D.

As said by Paolo, and in earlier contributions, ATAN2 can be used

to obtain the absolute orientation of a body segment. It is then

a simple matter to subtract the orientations of two segments to get

the angle between them. This will give the same result as the "dot

product" method, but can only be used with 2-D marker data.

Please note that there was an error in Chris Kirtley's last posting.

The order of arguments in the atan2 function should be atan2(y,x), and

not atan2(x,y)! I think the y,x order came about because atan2(a,b) was

thought of as a 360-degree version of atan(a/b). I verified the

parameter order for Matlab, Fortran, and C. Please check your

documentation if you use other languages.

An advantage of using ATAN2, as opposed to ATAN, ASIN and ACOS, is that

the code is smaller but also that "if" statements are avoided. As a general

rule, "if" is risky when applied to measured data; an "if" can amplify noise

when not used carefully. Allan Carman's code using "IF( x != 0.0 )"

works, but one should realize that the "if" is really only used when x is

exactly zero, which never occurs in real-world data. If you had a bug in

the "else" branch of such an "if", you would never know it, if you only

processed real data. I have made such mistakes myself... It is always

better to use algorithms where no "if" is needed.

Finally, I would like to mention that similar issues arise when

computing 3-D (cardanic) joint angles. The usual procedure is to first

compute attitude matrices for each of the two segments, multiply one matrix

by the inverse of the other to obtain the relative attitude, and finally

extract Euler/Cardanic angles from this relative attitude matrix.

Young-Hoo Kwon described this last step on the Kwon3D site:

http://www.kwon3d.com/theory/euler/euler_angles.html

Unfortunately, few programmers/authors have taken advantage of the ATAN2

function.

Borrowing the example from Kwon3D, let's assume a 3x3 attitude matrix

with 3-D joint angles (theta, phi, psi) as follows:

cos(th)cos(ps) sin(ph)sin(th)cos(ps)+cos(ph)sin(ps) -cos(ph)sin(th)cos(ps)+sin(ph)sin(ps)

T = -cos(th)sin(ps) -sin(ph)sin(th)sin(ps)+cos(ph)sin(ps) cos(ph)sin(th)sin(ps)+sin(ph)cos(ps)

sin(th) -sin(ph)cos(th) cos(ph)cos(th)

As in Kwon3D, we label these matrix elements as t11, t12, t13, etc.

Using such an attitude matrix, obtained from measurements, the joint

angles can be easily extracted as follows:

ph = atan2(-t32,t33)

th = atan2(t31,sqrt(t32*t32+t33*t33))

ps = atan2(-t21,t11)

(..sqrt is the square root function)

Note that 4 of the 9 matrix elements were not used, but if T is a true

rotation matrix, i.e. orthonormal, using the other elements would give

identical results.

It is interesting to note that Herman Woltring's PRP.FORTRAN code, first

announced on Biomch-L in 1990, consistently uses ATAN2 whereas some more

recent authors (including Kwon3D and KineMat) do not. Herman would have

had much to say about the current discussion, but as you know he died in

November 1992.

See:

http://isb.ri.ccf.org/biomch-l/archives/biomch-l-1990-02/00023.html

http://www.isbweb.org/software/movanal/prp.fortran

So I am glad that now the entire Biomch-L readership has rediscovered

this wonderful mathematical function ATAN2. Thanks to Chris Kirtley

for raising the question!

If you are writing any kind of movement analysis software, be sure to

visit the movement analysis section of the ISB software pages:

http://www.isbweb.org/software/movanal.html .

An archive of the Biomch-L "helical angle wars" can be found at

http://isb.ri.ccf.org/biomch-l/files/angles3d.topic

--

Ton van den Bogert, Biomch-L co-moderator

--

A.J. (Ton) van den Bogert, PhD

Department of Biomedical Engineering

Cleveland Clinic Foundation

9500 Euclid Avenue (ND-20)

Cleveland, OH 44195, USA

Phone/Fax: (216) 444-5566/9198

---------------------------------------------------------------

To unsubscribe send SIGNOFF BIOMCH-L to LISTSERV@nic.surfnet.nl

For information and archives: http://isb.ri.ccf.org/biomch-l

---------------------------------------------------------------

As this months's moderator, I feel it is now time to wrap up and

summarize this discussion. It seems that everything has been said and

we should try to end this specific topic. Below is a brief summary and

some comments on analogous issues in 3-D analysis. Please feel free to

point out any errors, and further contributions on 3-D joint angles are

certainly welcome. Who knows, we may even revive the "helical angle

wars" that took place on Biomch-L between 1989 and 1992.

Paolo de Leva's posting yesterday, elaborating on an earlier reply from

Michael Feltner, describes an elegant way to compute the angle

between two body segments, each defined by two markers. This method

uses the fact that a dot product is proportional to the cosine of the

angle between two vectors. Michael shared his Fortran code, and you

can find Matlab code for the same algorithm in the Kinemat

package, see http://www.isbweb.org/software/movanal/kinemat/angle2d.m

This technique allows a plus & minus 180 degree range of motion and

has the advantage that it also works in 3-D.

As said by Paolo, and in earlier contributions, ATAN2 can be used

to obtain the absolute orientation of a body segment. It is then

a simple matter to subtract the orientations of two segments to get

the angle between them. This will give the same result as the "dot

product" method, but can only be used with 2-D marker data.

Please note that there was an error in Chris Kirtley's last posting.

The order of arguments in the atan2 function should be atan2(y,x), and

not atan2(x,y)! I think the y,x order came about because atan2(a,b) was

thought of as a 360-degree version of atan(a/b). I verified the

parameter order for Matlab, Fortran, and C. Please check your

documentation if you use other languages.

An advantage of using ATAN2, as opposed to ATAN, ASIN and ACOS, is that

the code is smaller but also that "if" statements are avoided. As a general

rule, "if" is risky when applied to measured data; an "if" can amplify noise

when not used carefully. Allan Carman's code using "IF( x != 0.0 )"

works, but one should realize that the "if" is really only used when x is

exactly zero, which never occurs in real-world data. If you had a bug in

the "else" branch of such an "if", you would never know it, if you only

processed real data. I have made such mistakes myself... It is always

better to use algorithms where no "if" is needed.

Finally, I would like to mention that similar issues arise when

computing 3-D (cardanic) joint angles. The usual procedure is to first

compute attitude matrices for each of the two segments, multiply one matrix

by the inverse of the other to obtain the relative attitude, and finally

extract Euler/Cardanic angles from this relative attitude matrix.

Young-Hoo Kwon described this last step on the Kwon3D site:

http://www.kwon3d.com/theory/euler/euler_angles.html

Unfortunately, few programmers/authors have taken advantage of the ATAN2

function.

Borrowing the example from Kwon3D, let's assume a 3x3 attitude matrix

with 3-D joint angles (theta, phi, psi) as follows:

cos(th)cos(ps) sin(ph)sin(th)cos(ps)+cos(ph)sin(ps) -cos(ph)sin(th)cos(ps)+sin(ph)sin(ps)

T = -cos(th)sin(ps) -sin(ph)sin(th)sin(ps)+cos(ph)sin(ps) cos(ph)sin(th)sin(ps)+sin(ph)cos(ps)

sin(th) -sin(ph)cos(th) cos(ph)cos(th)

As in Kwon3D, we label these matrix elements as t11, t12, t13, etc.

Using such an attitude matrix, obtained from measurements, the joint

angles can be easily extracted as follows:

ph = atan2(-t32,t33)

th = atan2(t31,sqrt(t32*t32+t33*t33))

ps = atan2(-t21,t11)

(..sqrt is the square root function)

Note that 4 of the 9 matrix elements were not used, but if T is a true

rotation matrix, i.e. orthonormal, using the other elements would give

identical results.

It is interesting to note that Herman Woltring's PRP.FORTRAN code, first

announced on Biomch-L in 1990, consistently uses ATAN2 whereas some more

recent authors (including Kwon3D and KineMat) do not. Herman would have

had much to say about the current discussion, but as you know he died in

November 1992.

See:

http://isb.ri.ccf.org/biomch-l/archives/biomch-l-1990-02/00023.html

http://www.isbweb.org/software/movanal/prp.fortran

So I am glad that now the entire Biomch-L readership has rediscovered

this wonderful mathematical function ATAN2. Thanks to Chris Kirtley

for raising the question!

If you are writing any kind of movement analysis software, be sure to

visit the movement analysis section of the ISB software pages:

http://www.isbweb.org/software/movanal.html .

An archive of the Biomch-L "helical angle wars" can be found at

http://isb.ri.ccf.org/biomch-l/files/angles3d.topic

--

Ton van den Bogert, Biomch-L co-moderator

--

A.J. (Ton) van den Bogert, PhD

Department of Biomedical Engineering

Cleveland Clinic Foundation

9500 Euclid Avenue (ND-20)

Cleveland, OH 44195, USA

Phone/Fax: (216) 444-5566/9198

---------------------------------------------------------------

To unsubscribe send SIGNOFF BIOMCH-L to LISTSERV@nic.surfnet.nl

For information and archives: http://isb.ri.ccf.org/biomch-l

---------------------------------------------------------------