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
---------------------------------------------------------------