Source code for baldor.euler

#!/usr/bin/env python
"""
Generic Euler rotations
"""
import math
import numpy as np
# Local modules
import baldor as br


[docs]def to_axis_angle(ai, aj, ak, axes='sxyz'): """ Return axis-angle rotation from Euler angles and axes sequence Parameters ---------- ai: float First rotation angle (according to axes). aj: float Second rotation angle (according to axes). ak: float Third rotation angle (according to axes). axes: str, optional Axis specification; one of 24 axis sequences as string or encoded tuple Returns ------- axis: array_like axis around which rotation occurs angle: float angle of rotation Examples -------- >>> import numpy as np >>> import baldor as br >>> axis, angle = br.euler.to_axis_angle(0, 1.5, 0, 'szyx') >>> np.allclose(axis, [0, 1, 0]) True >>> angle 1.5 """ T = to_transform(ai, aj, ak, axes) axis, angle, _ = br.transform.to_axis_angle(T) return axis, angle
[docs]def to_quaternion(ai, aj, ak, axes='sxyz'): """ Returns a quaternion from Euler angles and axes sequence Parameters ---------- ai: float First rotation angle (according to axes). aj: float Second rotation angle (according to axes). ak: float Third rotation angle (according to axes). axes: str, optional Axis specification; one of 24 axis sequences as string or encoded tuple Returns ------- q: array_like Quaternion in w, x, y z (real, then vector) format Notes ----- Quaternions :math:`w + ix + jy + kz` are represented as :math:`[w, x, y, z]`. Examples -------- >>> import numpy as np >>> import baldor as br >>> q = br.euler.to_quaternion(1, 2, 3, 'ryxz') >>> np.allclose(q, [0.435953, 0.310622, -0.718287, 0.444435]) True """ try: firstaxis, parity, repetition, frame = br._AXES2TUPLE[axes.lower()] except (AttributeError, KeyError): br._TUPLE2AXES[axes] # validation firstaxis, parity, repetition, frame = axes i = firstaxis + 1 j = br._NEXT_AXIS[i+parity-1] + 1 k = br._NEXT_AXIS[i-parity] + 1 if frame: ai, ak = ak, ai if parity: aj = -aj ai /= 2.0 aj /= 2.0 ak /= 2.0 ci = math.cos(ai) si = math.sin(ai) cj = math.cos(aj) sj = math.sin(aj) ck = math.cos(ak) sk = math.sin(ak) cc = ci*ck cs = ci*sk sc = si*ck ss = si*sk q = np.empty((4, )) if repetition: q[0] = cj*(cc - ss) q[i] = cj*(cs + sc) q[j] = sj*(cc + ss) q[k] = sj*(cs - sc) else: q[0] = cj*cc + sj*ss q[i] = cj*sc - sj*cs q[j] = cj*ss + sj*cc q[k] = cj*cs - sj*sc if parity: q[j] *= -1.0 return q
[docs]def to_transform(ai, aj, ak, axes='sxyz'): """ Return homogeneous transformation matrix from Euler angles and axes sequence. Parameters ---------- ai: float First rotation angle (according to axes). aj: float Second rotation angle (according to axes). ak: float Third rotation angle (according to axes). axes: str, optional Axis specification; one of 24 axis sequences as string or encoded tuple Returns ------- T: array_like Homogeneous transformation (4x4) Examples -------- >>> import numpy as np >>> import baldor as br >>> T = br.euler.to_transform(1, 2, 3, 'syxz') >>> np.allclose(np.sum(T[0]), -1.34786452) True >>> T = br.euler.to_transform(1, 2, 3, (0, 1, 0, 1)) >>> np.allclose(np.sum(T[0]), -0.383436184) True """ try: firstaxis, parity, repetition, frame = br._AXES2TUPLE[axes] except (AttributeError, KeyError): br._TUPLE2AXES[axes] # validation firstaxis, parity, repetition, frame = axes i = firstaxis j = br._NEXT_AXIS[i+parity] k = br._NEXT_AXIS[i-parity+1] if frame: ai, ak = ak, ai if parity: ai, aj, ak = -ai, -aj, -ak si, sj, sk = math.sin(ai), math.sin(aj), math.sin(ak) ci, cj, ck = math.cos(ai), math.cos(aj), math.cos(ak) cc, cs = ci*ck, ci*sk sc, ss = si*ck, si*sk T = np.identity(4) if repetition: T[i, i] = cj T[i, j] = sj*si T[i, k] = sj*ci T[j, i] = sj*sk T[j, j] = -cj*ss+cc T[j, k] = -cj*cs-sc T[k, i] = -sj*ck T[k, j] = cj*sc+cs T[k, k] = cj*cc-ss else: T[i, i] = cj*ck T[i, j] = sj*sc-cs T[i, k] = sj*cc+ss T[j, i] = cj*sk T[j, j] = sj*ss+cc T[j, k] = sj*cs-sc T[k, i] = -sj T[k, j] = cj*si T[k, k] = cj*ci return T