AerialVehicleControl.jl
cont_math.c
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) Marcus Greiff 2020
3 *
4 * @file cont_math.c
5 * @author Marcus Greiff
6 * @date June 2020
7 *******************************************************************************/
8 #include "cont_math.h"
9 /* Maps pertaining to the SU2 manifold */
11  matrix_double_t * qin,
12  matrix_double_t * qout
13 ){
14  int i;
15  /* Input error check */
16  if((qin->numCols != 1) ||
17  (qin->numRows != 4) ||
18  (qout->numCols != 1) ||
19  (qout->numRows != 4)){
20  TRACE(5, ("Bad input dimensions\n"));
21  return 0;
22  }
23  qout->pData[0] = qin->pData[0];
24  for (i = 1; i < 4; i++) qout->pData[i] = -qin->pData[i];
25  return 1;
26 }
27 
29  matrix_double_t * q,
30  matrix_double_t * p,
31  matrix_double_t * out
32 ){
33  if((q->numCols != 1) ||
34  (q->numRows != 4) ||
35  (p->numCols != 1) ||
36  (p->numRows != 4) ||
37  (out->numCols != 1) ||
38  (out->numRows != 4)){
39  TRACE(5, ("Bad input dimensions\n"));
40  return 0;
41  }
42  out->pData[0] = p->pData[0]*q->pData[0] - p->pData[1]*q->pData[1];
43  out->pData[0] += - p->pData[2]*q->pData[2] - p->pData[3]*q->pData[3];
44  out->pData[1] = p->pData[0]*q->pData[1] + p->pData[1]*q->pData[0];
45  out->pData[1] += - p->pData[2]*q->pData[3] + p->pData[3]*q->pData[2];
46  out->pData[2] = p->pData[0]*q->pData[2] + p->pData[2]*q->pData[0];
47  out->pData[2] += p->pData[1]*q->pData[3] - p->pData[3]*q->pData[1];
48  out->pData[3] = p->pData[0]*q->pData[3] - p->pData[1]*q->pData[2];
49  out->pData[3] += p->pData[2]*q->pData[1] + p->pData[3]*q->pData[0];
50  return 1;
51 }
52 
54  matrix_double_t * in,
55  matrix_double_t * out
56 ){
57  int i;
58  if((in->numCols != 1) ||
59  (in->numRows != 4) ||
60  (out->numCols != 1) ||
61  (out->numRows != 3)){
62  TRACE(5, ("Bad input dimensions\n"));
63  return 0;
64  }
65  for (i = 0; i < 3; i++) out->pData[i] = in->pData[i+1];
66  return 1;
67 }
68 
70  matrix_double_t * in,
71  matrix_double_t * out
72 ){
73  int i;
74  if((in->numCols != 1) ||
75  (in->numRows != 3) ||
76  (out->numCols != 1) ||
77  (out->numRows != 4)){
78  TRACE(5, ("Bad input dimensions\n"));
79  return 0;
80  }
81  out->pData[0] = 0.0;
82  for (i = 0; i < 3; i++) out->pData[i+1] = in->pData[i];
83  return 1;
84 }
85 
87  matrix_double_t * in,
88  matrix_double_t * out
89 ){
90  int i;
91  double theta = 0.0;
92  double coeff_im;
93 
94  if((in->numCols != 1) ||
95  (in->numRows != 3) ||
96  (out->numCols != 1) ||
97  (out->numRows != 4)){
98  TRACE(5, ("Bad input dimensions\n"));
99  return 0;
100  }
101 
102  for (i = 0; i < 3; i++) theta += in->pData[i]*in->pData[i];
103  theta = sqrt(theta);
104  coeff_im = cont_sinc(theta / 2.0);
105  out->pData[0] = cos(theta / 2.0);
106  for (i = 0; i < 3; i++) out->pData[i+1] = coeff_im * in->pData[i] / 2.0;
107  return 1;
108 }
109 
111  double a,
112  double b,
113  double c,
114  matrix_double_t * out
115 ){
116  double cosad2, cosbd2, coscd2, sinad2, sinbd2, sincd2;
117  if((out->numCols != 1) ||
118  (out->numRows != 4)){
119  TRACE(5, ("Bad input dimensions\n"));
120  return 0;
121  }
122 
123  cosad2 = cos(a/2.0);
124  cosbd2 = cos(b/2.0);
125  coscd2 = cos(c/2.0);
126  sinad2 = sin(a/2.0);
127  sinbd2 = sin(b/2.0);
128  sincd2 = sin(c/2.0);
129 
130  out->pData[0] = cosad2*cosbd2*coscd2 - sinad2*sinbd2*sincd2;
131  out->pData[1] = cosbd2*coscd2*sinad2 + cosad2*sinbd2*sincd2;
132  out->pData[2] = cosad2*coscd2*sinbd2 - cosbd2*sinad2*sincd2;
133  out->pData[3] = cosad2*cosbd2*sincd2 + coscd2*sinad2*sinbd2;
134 
135  return 1;
136 }
137 
139  matrix_double_t * q1,
140  matrix_double_t * q2
141 ){
142  int i;
143  double out = 1.0;
144  /* Input error check */
145  if((q1->numCols != 1) ||
146  (q1->numRows != 4) ||
147  (q2->numCols != 1) ||
148  (q2->numRows != 4)){
149  TRACE(5, ("Bad input dimensions\n"));
150  return 0;
151  }
152  for (i = 0; i < 4; i++ ) out -= (q1->pData[i] * q2->pData[i]);
153  return out;
154 }
155 
156 /* Embedding relating SU(2) to SO(3) */
158  matrix_double_t * q,
159  matrix_double_t * R
160 ){
161  double a, b, c, d, asq, bsq, csq, dsq;
162 
163  /* Input error check */
164  if((q->numCols != 1) ||
165  (q->numRows != 4) ||
166  (R->numCols != 3) ||
167  (R->numRows != 3)){
168  TRACE(5, ("Bad input dimensions\n"));
169  return 0;
170  }
171  a = q->pData[0]; b = q->pData[1]; c = q->pData[2]; d = q->pData[3];
172  asq = a * a; bsq = b * b; csq = c * c; dsq = d * d;
173  matrix_set(R, 0, 0, asq+bsq-csq-dsq);
174  matrix_set(R, 1, 0, 2.0*(b*c+a*d));
175  matrix_set(R, 2, 0, 2.0*(b*d-a*c));
176  matrix_set(R, 0, 1, 2.0*(b*c-a*d));
177  matrix_set(R, 1, 1, asq-bsq+csq-dsq);
178  matrix_set(R, 2, 1, 2.0*(c*d+a*b));
179  matrix_set(R, 0, 2, 2.0*(b*d+a*c));
180  matrix_set(R, 1, 2, 2.0*(c*d-a*b));
181  matrix_set(R, 2, 2, asq-bsq-csq+dsq);
182  return 1;
183 }
184 
185 /* Maps pertaining to the SO3 manifold */
187  matrix_double_t * in,
188  matrix_double_t * out
189 ){
190  if((in->numCols != 1) ||
191  (in->numRows != 3) ||
192  (out->numCols != 3) ||
193  (out->numRows != 3)){
194  TRACE(5, ("Bad input dimensions\n"));
195  return 0;
196  }
197  matrix_zero(out);
198  matrix_set(out, 0, 1, -in->pData[2]);
199  matrix_set(out, 0, 2, +in->pData[1]);
200  matrix_set(out, 1, 0, +in->pData[2]);
201  matrix_set(out, 1, 2, -in->pData[0]);
202  matrix_set(out, 2, 0, -in->pData[1]);
203  matrix_set(out, 2, 1, +in->pData[0]);
204  return 1;
205 }
206 
208  matrix_double_t * in,
209  matrix_double_t * out
210 ){
211  if((in->numCols != 3) ||
212  (in->numRows != 3) ||
213  (out->numCols != 1) ||
214  (out->numRows != 3)){
215  TRACE(5, ("Bad input dimensions\n"));
216  return 0;
217  }
218  out->pData[0] = matrix_get(in, 2, 1);
219  out->pData[1] = matrix_get(in, 0, 2);
220  out->pData[2] = matrix_get(in, 1, 0);
221  return 1;
222 }
223 
225  matrix_double_t * in,
226  matrix_double_t * out
227 ){
228  int i;
229  matrix_double_t Am, Bm;
230  double coeff_a, coeff_b, theta = 0.0;
231 
232  if((in->numCols != 1) ||
233  (in->numRows != 3) ||
234  (out->numCols != 3) ||
235  (out->numRows != 3)){
236  TRACE(5, ("Bad input dimensions\n"));
237  return 0;
238  }
239 
240  matrix_allocate(&Am, 3, 3);
241  matrix_allocate(&Bm, 3, 3);
242 
243  for (i = 0; i < 3; i++ ) theta += pow(in->pData[i], 2.0);
244  theta = sqrt(theta);
245 
246  /* Compute coefficients using the sinc function */
247  coeff_a = cont_sinc(theta);
248  coeff_b = cont_sinc(theta / 2.0);
249  coeff_b = coeff_b*coeff_b / 2.0;
250 
251  /* Compute the skew symetric matrix and its power */
252  cont_SO3_hat(in, &Am);
253  mat_mul(&Am, &Am, &Bm);
254 
255  /* out = I + sinc(theta) * S(in) + sinc(theta/2)^2/2 * S(in) * S(in) */
256  matrix_identity(out);
257  for (i = 0; i < 9; i++ ) out->pData[i] += (coeff_a * Am.pData[i] + coeff_b * Bm.pData[i]);
258 
259  /* Free malloced memory */
260  free(Am.pData);
261  free(Bm.pData);
262  return 1;
263 }
264 
266  matrix_double_t * in,
267  matrix_double_t * out
268 ){
269  int i;
270  matrix_double_t RTm;
271  double coeff, theta = 0;
272 
273  if((in->numCols != 3) ||
274  (in->numRows != 3) ||
275  (out->numCols != 1) ||
276  (out->numRows != 3)){
277  TRACE(5, ("Bad input dimensions\n"));
278  return 0;
279  }
280  /* TODO this is currently not safe, as the sinc funciton may dip down to 0
281  yielding a division by zero. This can be fixed at a later time, currently
282  not done here in order to keep everything clean in the initial implementation*/
283  matrix_allocate(&RTm, 3, 3);
284  mat_trans(in, &RTm);
285  mat_sub_inplace(&RTm, in); /* RT = -(R - R'); */
286 
287  for (i = 0; i < 3; i++ ) theta += matrix_get(in, i, i);
288  theta /=2;
289  theta -=0.5;
290  theta = acos(theta);
291  coeff = 0.5 / cont_sinc(theta);
292 
293  cont_SO3_vee(&RTm, out);
294 
295  /* out = [R - R']^v / (2*sinc(theta)), theta = acos(trace(R) - 1) / 2 */
296  for (i = 0; i < 3; i++) out->pData[i] *= -coeff;
297  free(RTm.pData);
298 
299  return 1;
300 }
301 
303  matrix_double_t * R1,
304  matrix_double_t * R2
305 ){
306 
307  matrix_double_t R1T, R1TR2;
308  double psi;
309 
310  /* Input error check */
311  if((R1->numCols != 3) ||
312  (R1->numRows != 3) ||
313  (R2->numCols != 3) ||
314  (R2->numRows != 3)){
315  TRACE(5, ("Bad input dimensions\n"));
316  assert(1 == 0);
317  }
318 
319  matrix_allocate( &R1T, 3, 3);
320  matrix_allocate( &R1TR2, 3, 3);
321  mat_trans(R1, &R1T);
322  mat_mul(&R1T, R2, &R1TR2);
323 
324  /* Compute Psi = (1/2)*trace(I - R1'*R2) */
325  psi = (3.0 - R1TR2.pData[0] - R1TR2.pData[4] - R1TR2.pData[8]) / 2.0;
326 
327  free(R1T.pData);
328  free(R1TR2.pData);
329 
330  return psi;
331 }
332 
333 double cont_sinc(
334  double x
335 ){
336  if (x == 0.0) {
337  return 1.0;
338  } else {
339  return sin(x) / x;
340  }
341 }
342 
344  matrix_double_t * vecA,
345  matrix_double_t * vecB
346 ){
347  int i;
348  double output = 0.0;
349  if((vecA->numCols != 1) ||
350  (vecA->numRows != vecB->numRows) ||
351  (vecB->numCols != 1)){
352  TRACE(5, ("Bad input dimensions\n"));
353  assert(1 == 0);
354  }
355  for (i = 0; i < vecA->numRows; i++) output += (vecA->pData[i]*vecB->pData[i]);
356  return output;
357 }
358 
360  matrix_double_t * inAm,
361  matrix_double_t * inBm,
362  matrix_double_t * outm
363 ){
364  outm->pData[0] = inAm->pData[1]*inBm->pData[2] - inAm->pData[2]*inBm->pData[1];
365  outm->pData[1] = inAm->pData[2]*inBm->pData[0] - inAm->pData[0]*inBm->pData[2];
366  outm->pData[2] = inAm->pData[0]*inBm->pData[1] - inAm->pData[1]*inBm->pData[0];
367  return;
368 }
369 
371  double in
372 ){
373  if (in >= 0.0) return 1.0;
374  return -1.0;
375 }
376 
377 
379  int N, i;
380  double val = 0.0;
381 
382  if ((vec->numRows != 1) && (vec->numCols != 1)) return 0;
383  if (vec->numRows == 1){
384  if (vec->numCols < 1) return 0;
385  N = vec->numCols;
386  }
387  if (vec->numCols == 1){
388  if (vec->numRows < 1) return 0;
389  N = vec->numRows;
390  }
391 
392  for ( i = 0; i < N; i++) val += (vec->pData[i]*vec->pData[i]);
393  if (val <= 0.0) return 0;
394  val = sqrt(val);
395  for ( i = 0; i < N; i++) vec->pData[i] /= val;
396  return 1;
397 }
matrix_double_s::pData
double * pData
Definition: cont_types.h:59
cont_cross_product
void cont_cross_product(matrix_double_t *inAm, matrix_double_t *inBm, matrix_double_t *outm)
Cross product operation, To be migrated to the cont_math stack.
Definition: cont_math.c:359
cont_SU2_hat
int cont_SU2_hat(matrix_double_t *in, matrix_double_t *out)
The hat map on SU(2)
Definition: cont_math.c:69
cont_normalize
int cont_normalize(matrix_double_t *vec)
Normalizes the vector.
Definition: cont_math.c:378
matrix_allocate
void matrix_allocate(matrix_double_t *matrix, int numRows, int numCols)
Allocate memory for a matrix struct of given dimensions.
Definition: cont_types.c:65
cont_math.h
matrix_double_s::numRows
int numRows
Definition: cont_types.h:57
matrix_zero
void matrix_zero(matrix_double_t *matrix)
Set all antries of a matrix to zero.
Definition: cont_types.c:49
matrix_double_s
Matrix object used for all matrix manipulation.
Definition: cont_types.h:50
mat_trans
void mat_trans(matrix_double_t *Amat, matrix_double_t *ATmat)
Matrix transposition, A^T <– transpose(A), asserts that this is done correctly.
Definition: cont_matrix_math.c:261
matrix_identity
void matrix_identity(matrix_double_t *matrix)
Set a square matrix to the identity matrix.
Definition: cont_types.c:59
cont_SU2_product
int cont_SU2_product(matrix_double_t *q, matrix_double_t *p, matrix_double_t *out)
Product of two elements of SU(2)
Definition: cont_math.c:28
cont_sinc
double cont_sinc(double x)
Evaluates the sinc function as f(x) = sin(x)/x.
Definition: cont_math.c:333
matrix_double_s::numCols
int numCols
Definition: cont_types.h:58
cont_SO3_Log
int cont_SO3_Log(matrix_double_t *in, matrix_double_t *out)
The Log map on SO3.
Definition: cont_math.c:265
matrix_set
void matrix_set(matrix_double_t *mat, int row, int column, double value)
Set an entry of a matrix (irrespective of the used memory layout)
Definition: cont_types.c:40
cont_SO3_vee
int cont_SO3_vee(matrix_double_t *in, matrix_double_t *out)
The hat operator on SO3.
Definition: cont_math.c:207
mat_mul
void mat_mul(matrix_double_t *Amat, matrix_double_t *Bmat, matrix_double_t *Cmat)
and asserts that this is done correctly
Definition: cont_matrix_math.c:258
cont_SU2_triple
int cont_SU2_triple(double a, double b, double c, matrix_double_t *out)
Computes a triple product on SU(2)
Definition: cont_math.c:110
cont_SO3_distance
double cont_SO3_distance(matrix_double_t *R1, matrix_double_t *R2)
The distance Phi(R1, R2) defined on SO3.
Definition: cont_math.c:302
mat_sub_inplace
void mat_sub_inplace(matrix_double_t *Amat, matrix_double_t *Bmat)
In-place subtraction addition, A <– A - B, asserts that this is done correctly.
Definition: cont_matrix_math.c:255
cont_SO3_hat
int cont_SO3_hat(matrix_double_t *in, matrix_double_t *out)
The hat operator on SO3.
Definition: cont_math.c:186
cont_quat_2_SO3
int cont_quat_2_SO3(matrix_double_t *q, matrix_double_t *R)
Embedding relating SU(2) to SO(3)
Definition: cont_math.c:157
cont_SU2_conjugate
int cont_SU2_conjugate(matrix_double_t *qin, matrix_double_t *qout)
Conjugate an element of SU(2)
Definition: cont_math.c:10
cont_sign_func
double cont_sign_func(double in)
Takes the sign of the input, returning +1 if the input is zero.
Definition: cont_math.c:370
cont_dot_product
double cont_dot_product(matrix_double_t *vecA, matrix_double_t *vecB)
Evaluates the dot product of two vectors.
Definition: cont_math.c:343
cont_SU2_vee
int cont_SU2_vee(matrix_double_t *in, matrix_double_t *out)
The vee map on SU(2)
Definition: cont_math.c:53
cont_SU2_distance
double cont_SU2_distance(matrix_double_t *q1, matrix_double_t *q2)
Evaluate distance Gamma(q1, q2) in [0,2] defined on SU2.
Definition: cont_math.c:138
cont_SO3_Exp
int cont_SO3_Exp(matrix_double_t *in, matrix_double_t *out)
The Exp map on SO3.
Definition: cont_math.c:224
cont_SU2_Exp
int cont_SU2_Exp(matrix_double_t *in, matrix_double_t *out)
The Exp map on SU(2)
Definition: cont_math.c:86
matrix_get
double matrix_get(matrix_double_t *mat, int row, int column)
Get an entry of a matrix (irrespective of the used memory layout)
Definition: cont_types.c:32