{"id":17,"date":"2005-03-25T21:00:06","date_gmt":"2005-03-26T02:00:06","guid":{"rendered":"http:\/\/www.essentialmath.com\/blog\/?p=17"},"modified":"2005-11-19T09:22:16","modified_gmt":"2005-11-19T14:22:16","slug":"angular-dynamics-matrices-or-quaternions","status":"publish","type":"post","link":"https:\/\/www.essentialmath.com\/blog\/?p=17","title":{"rendered":"Angular Dynamics: Matrices or Quaternions?"},"content":{"rendered":"<p>One of the questions asked during the tutorial was whether matrices or quaternions were more efficient for angular rigid body dynamics.  My response was that a matrix would be more efficient, because a quaternion requires a conversion to a matrix to compute the transformed inertial tensor matrix.  If we analyze the operation count, this certainly appears to be true:<br \/>\n<!--more--><br \/>\n<strong>Matrix:<\/strong><br \/>\nIntegration: 21 multiplies, 18 adds<br \/>\n<em>Total:<\/em> 21 multiplies, 18 adds<\/p>\n<p><strong>Quaternion:<\/strong><br \/>\nIntegration: 16 multiplies, 12 adds<br \/>\nConvert to matrix: 12 multiplies, 12 adds<br \/>\n<em>Total:<\/em> 28 multiplies, 24 adds<\/p>\n<p>The matrix conversion operation count assumes that the quaternion is pre-normalized.  So it&#8217;s close, but the matrix is still cheaper.<\/p>\n<p>However, as Erin Catto (again) pointed out to me afterwards, this doesn&#8217;t take orthonormalization of the matrix into account.  One thing I forgot is that because of floating point error, the rotation matrix can drift away from being orthogonal, i.e. the basis vectors can become non-normalized and no longer perpendicular.  <\/p>\n<p>To correct this, Gram-Schmidt orthonormalization needs to be performed after integrating.   This consists of normalizing the first basis vector, and then subtracting out the non-perpendicular components of the other two (relative to the other vectors) and normalizing them as well (I&#8217;m paraphrasing greatly here &#8212; see the book or <a href=\"http:\/\/planetmath.org\/encyclopedia\/GramSchmidtOrthogonalization.html\">this reference<\/a> for more information).  Each normalization takes 6 multiplies, 2 adds and a reciprocal square root (approximation or no, you still need to compute something).  Orthogonalizing the three vectors takes 18 multiplies and 15 adds.  The total is 36 multiplies, 21 adds, and three reciprocal square roots.<\/p>\n<p>The equivalent operation for a quaternion is a simple normalization.  This takes 8 multiplies, 3 adds and a reciprocal square root.  Technically we can still rotate vectors with an unnormalized quaternion, but keeping the values of the quaternion close to 0 maintains a higher level of precision.<\/p>\n<p>Now if we compare the operation counts, we get:<\/p>\n<p><strong>Matrix:<\/strong><br \/>\nIntegration: 21 multiplies, 18 adds<br \/>\nOrthonormalization: 36 multiplies, 21 adds, 3 reciprocal square roots<br \/>\n<em>Total:<\/em>57 multiplies, 39 adds, 3 reciprocal square roots<\/p>\n<p><strong>Quaternion:<\/strong><br \/>\nIntegration: 16 multiplies, 12 adds<br \/>\nNormalization: 8 multiplies, 3 adds, 1 reciprocal square root<br \/>\nConvert to matrix: 12 multiplies, 12 adds<br \/>\n<em>Total:<\/em> 36 multiplies, 27 adds, 1 reciprocal square root<\/p>\n<p>Taking this into account &#8212; and even assuming we have a fast method for computing the reciprocal square root &#8212; the quaternion clearly wins on speed.  It also takes less space.  So unless someone else has another correction for me, I&#8217;m not sure why you&#8217;d ever use matrices as your base format for physical simulation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the questions asked during the tutorial was whether matrices or quaternions were more efficient for angular rigid body dynamics. My response was that a matrix would be more efficient, because a quaternion requires a conversion to a matrix to compute the transformed inertial tensor matrix. If we analyze the operation count, this certainly [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,6],"tags":[],"class_list":["post-17","post","type-post","status-publish","format-standard","hentry","category-mathematical","category-tutorial"],"_links":{"self":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=17"}],"version-history":[{"count":0,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/17\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}