MAGIKS  1.1
Manipulator General Inverse Kinematic Solver
 All Classes Namespaces Files Functions Variables Pages
quaternions.py
Go to the documentation of this file.
1 ## @file quaternions.py
2 # @brief This module provides some useful functions dealing with quaternions
3 # @author Nima Ramezani Taghiabadi
4 #
5 # PhD Researcher
6 # Faculty of Engineering and Information Technology
7 # University of Technology Sydney (UTS)
8 # Broadway, Ultimo, NSW 2007, Australia
9 # Phone No. : 04 5027 4611
10 # Email(1) : nima.ramezani@gmail.com
11 # Email(2) : Nima.RamezaniTaghiabadi@uts.edu.au
12 # @version 1.0
13 #
14 #
15 # Last Revision: 03 January 2015
16 
17 import math,numpy
18 import general_python as genpy
19 from math_tools import general_math as gen
20 
21 def dbl2str(n):
22  d = abs(int(n));
23  f = int((n - d) * 1000000);
24  s = '%d.%d' % (d, f) if f > 0 else '%d' % d
25  ss = '+' if n >= 0 else '-'
26  return ss, s
27 
28 class Quaternion(object):
29  def __init__(q, w=0, x=0, y=0, z=0):
30  q.w = w
31  q.x = x
32  q.y = y
33  q.z = z
34 
35  ## Operator function for addition of two quaternions
36  def __add__(q1, q2):
37  return Quaternion(
38  q1.w + q2.w,
39  q1.x + q2.x,
40  q1.y + q2.y,
41  q1.z + q2.z,
42  )
43 
44  ## Operator function for subtraction of two quaternions
45  def __sub__(q1, q2):
46  return Quaternion(
47  q1.w - q2.w,
48  q1.x - q2.x,
49  q1.y - q2.y,
50  q1.z - q2.z,
51  )
52 
53  ## Operator function for multiplication of two quaternions
54  def __mul__(q1, q2):
55  return Quaternion(
56  q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z,
57  q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y,
58  q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x,
59  q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w,
60  )
61 
62  ## Operator function for division of two quaternions
63  def __div__(q1, q2):
64  s = float(q2.w*q2.w + q2.x*q2.x + q2.y*q2.y + q2.z*q2.z)
65  return Quaternion(
66  ( q1.w*q2.w + q1.x*q2.x + q1.y*q2.y + q1.z*q2.z) / s,
67  (- q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y) / s,
68  (- q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x) / s,
69  (- q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w) / s
70  )
71 
72  ## Operator function for the magnitude or norm of the quaternion
73  # @return A scalar float containing the norm of the given quaternion
74  def __abs__(q):
75  return math.sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z);
76 
77  ## Operator function for the negative of a quaternion
78  def __neg__(q):
79  return Quaternion(-q.w, -q.x, -q.y, -q.z)
80 
81  ## Operator function for the conjugate of a quaternion.
82  # @return The conjugate of the given quaternion (\f$ \bar q \f$)
83  def __invert__(q):
84  """Conjugate of Quaternion.
85 
86  >>> q = Quaternion((2, 2, 2, 2))
87  >>> print(q)
88  (2 + 2i + 2j + 2k)
89  >>> print(~q)
90  (2 - 2i - 2j - 2k)
91  >>> print(~~q)
92  (2 + 2i + 2j + 2k)
93 
94  """
95  return Quaternion((q.w, -q.x, -q.y, -q.z))
96 
97  def as_tuple(self):
98  return (self.w, self.x, self.y, self.z)
99 
100  ## @return The quaternion instance as a numpy vector
101  def as_vector(self):
102  return numpy.array([self.w, self.x, self.y, self.z])
103 
104  def __str__(q):
105  args = list(
106  dbl2str(q.w) +
107  dbl2str(q.x) +
108  dbl2str(q.y) +
109  dbl2str(q.z)
110  )
111  if args[0] == '+':
112  args[0] = ''
113  return '(%s%s %s %si %s %sj %s %sk)' % tuple(args)
114 
115  def normalize(q):
116  """Convert Quaternion to Unit Quaternion.
117 
118  Unit Quaternion is Quaternion who's length is equal to 1.
119 
120  >>> q = Quaternion((1, 3, 3, 3))
121  >>> q.normalize()
122  >>> print(q) # doctest: +ELLIPSIS
123  (0.1889822... + 0.5669467...i + 0.5669467...j + 0.5669467...k)
124 
125  """
126  norm = abs(q)
127  q.w = q.w / norm,
128  q.x = q.x / norm,
129  q.y = q.y / norm,
130  q.z = q.z / norm,
131 
132 
134 
135  u = 0
136  v = 1
137  w = 2
138 
139  for j in range(1,3):
140  if R[j,j] > R[u,u]:
141  u = j
142  v = j + 1
143  w = j + 2
144  if v > 2:
145  v = v - 3
146  if w > 2:
147  w = w - 3
148 
149  uvw = [u,v,w]
150  return uvw
151 
153  '''
154  Returns a vector (4 X 1) containing elements of the unit quaternion corresponding to transformation or rotation matrix TRM.
155  (TRM can be the 4*4 transformation matrix or 3*3 rotation matrix)
156  the first element of the output vector contains the scalar part of the unit quaternion and the last three elements represent the vectorial part
157 
158  '''
159  assert gen.equal(numpy.linalg.det(TRM[0:3,0:3]), 1.0), genpy.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name, "Given TRM is not a rotation matrix.")
160 
161  uqn = numpy.zeros((4))
162  uqn[0] = 1.00
163  [u,v,w] = permutation_uvw(TRM)
164 
165  p = 1.0 + TRM[u,u] - TRM[v,v] - TRM[w,w]
166 
167  if (p > gen.epsilon):
168  p = math.sqrt(p)
169  uqn[u+1] = p/2.0
170  uqn[v+1] = (TRM[v,u] + TRM[u,v])/(2*p)
171  uqn[w+1] = (TRM[w,u] + TRM[u,w])/(2*p)
172  uqn[0] = (TRM[w,v] - TRM[v,w])/(2*p)
173 
174  if uqn[0] < 0:
175  uqn = - uqn
176 
177  assert gen.equal(numpy.linalg.norm(uqn), 1.0), "Impossible !"
178  return uqn
179 
181  '''
182  Returns a vector (4 X 1) containing elements of the time derivation of the unit quaternion corresponding to transformation or rotation matrix TRM.
183  Matrix TRMD is the time derivative of the given transfer or rotation matrix TRM
184 
185  (TRM and TRMD can be 4*4 transformation or 3*3 rotation matrices)
186 
187  The last three elements of the output vector, represent the vectorial part
188  The first element, contains the real part of the unit quaternion speed.
189  '''
190  uqns = numpy.zeros((4))
191  [u,v,w] = permutation_uvw(TRM)
192 
193  p = math.sqrt(1+TRM[u,u]-TRM[v,v]-TRM[w,w])
194  pp = (TRMD[u,u] - TRMD[v,v] - TRMD[w,w])/(2*p)
195 
196  uqns[u+1] = pp/2
197  uqns[v+1] = (TRMD[v,u] + TRMD[u,v])/(2*p) - pp*(TRM[v,u] + TRM[u,v])/(2*p*p)
198  uqns[w+1] = (TRMD[w,u] + TRMD[u,w])/(2*p) - pp*(TRM[w,u] + TRM[u,w])/(2*p*p)
199  uqns[0] = (TRMD[w,v] - TRMD[v,w])/(2*p) - pp*(TRM[w,v] - TRM[v,w])/(2*p*p)
200  # to check if the quaternion was negative:
201 
202  if (p > 0.000001):
203  w = (TRM[w,v] - TRM[v,w])/(2*p)
204  else:
205  w = 1.0
206 
207  if w < 0:
208  uqns = - uqns
209 
210  return uqns
211 
213  '''
214  Returns a vector (3 X 1) containing elements of the normalized quaternion corresponding to transformation matrix TRM.
215  (TRM is the 4*4 transformation matrix)
216  A normalized quaternion here means a quaternion that its real part is 1.0
217  '''
218  nqn = numpy.zeros((3))
219  [u,v,w] = permutation_uvw(TRM)
220 
221  nqn[u] = (1+TRM[u,u]-TRM[v,v]-TRM[w,w])/(TRM[w,v]-TRM[v,w])
222  nqn[v] = (TRM[u,v]+TRM[v,u])/(TRM[w,v]-TRM[v,w])
223  nqn[w] = (TRM[u,w]+TRM[w,u])/(TRM[w,v]-TRM[v,w])
224 
225  return nqn
226 
227 
def __abs__
Operator function for the magnitude or norm of the quaternion.
Definition: quaternions.py:74
def __add__
Operator function for addition of two quaternions.
Definition: quaternions.py:36
def __invert__
Operator function for the conjugate of a quaternion.
Definition: quaternions.py:83
def __mul__
Operator function for multiplication of two quaternions.
Definition: quaternions.py:54
def __sub__
Operator function for subtraction of two quaternions.
Definition: quaternions.py:45
def __div__
Operator function for division of two quaternions.
Definition: quaternions.py:63
def __neg__
Operator function for the negative of a quaternion.
Definition: quaternions.py:78