AerialVehicleControl.jl
cont_attitude_FOF_SO3_continuous.c
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) Marcus Greiff 2020
3 *
4 * @file cont_attitude_FOF_SO3_continuous.c
5 * @author Marcus Greiff
6 * @date June 2020
7 *******************************************************************************/
9 
11  con_state_qw_fof_t * controller,
12  matrix_double_t * y0m,
13  matrix_double_t * y1m,
14  matrix_double_t * y2m,
15  matrix_double_t * y3m
16 ){
17  int i;
18  matrix_double_t Wm, Ym;
19 
20  if ((y0m->numCols != 1) ||
21  (y1m->numCols != 1) ||
22  (y1m->numCols != 1) ||
23  (y1m->numCols != 1) ||
24  (y1m->numRows != 3) ||
25  (y1m->numRows != 3) ||
26  (y1m->numRows != 3) ||
27  (y1m->numRows != 3)) {
28  TRACE(5, ("Wrong input dimensions\n"));
29  return 0;
30  }
31 
32  matrix_define(&Wm, 3, 1, controller->measuredGyrorates);
33  matrix_define(&Ym, 3, 3, controller->measuredDirections);
34 
35  for (i = 0; i < 3; i++){
36  matrix_set(&Wm, i, 0, y0m->pData[i]);
37  matrix_set(&Ym, i, 0, y1m->pData[i]);
38  matrix_set(&Ym, i, 1, y2m->pData[i]);
39  matrix_set(&Ym, i, 2, y3m->pData[i]);
40  }
41  return 1;
42 }
43 
45  ref_state_qw_t * reference,
46  dyn_state_qw_t * state,
47  con_state_qw_fof_t * controller,
48  double dt
49 ){
50 
51  int i;
52 
53  matrix_double_t Qrm, Wrm, Arm;
54  matrix_double_t Qhatm, Whatm;
55  matrix_double_t Tm, Jm, invJm, gain_ki_m, gain_Kwm, gain_Cwm;
56 
57  matrix_double_t Rrm, Rhatm;
58  matrix_double_t Vm, Ym, Wm, Yrm, Yhatm;
59 
60  matrix_double_t Whatem, Wem, Wtildem;
61 
62  matrix_double_t DRm, DWm;
63 
64  matrix_double_t vecAm, vecBm, vecCm, vecDm;
65 
66  matrix_double_t tmp33m, tmp31Am, tmp31Bm;
67 
68  /* Define the reference trajectory terms */
69  matrix_define(&Qrm, 4, 1, reference->quaternion);
70  matrix_define(&Wrm, 3, 1, reference->omega);
71  matrix_define(&Arm, 3, 1, reference->alpha);
72 
73  /* Compute the estimator state (here stored in the state object) */
74  matrix_define(&Qhatm, 4, 1, state->quaternion);
75  matrix_define(&Whatm, 3, 1, state->omega);
76 
77  /* Extract the controller parameters */
78  matrix_define(&Tm, 3, 1, controller->torque);
79  matrix_define(&Jm, 3, 3, controller->inertia);
80  matrix_define(&invJm, 3, 3, controller->invinertia);
81  matrix_define(&gain_ki_m, 1, 3, controller->gain_ki);
82  matrix_define(&gain_Kwm, 3, 3, controller->gain_Kw);
83  matrix_define(&gain_Cwm, 3, 3, controller->gain_Cw);
84 
85  /* Define the directions and the measured directions */
86  matrix_define(&Vm, 3, 3, controller->globalDirections);
87  matrix_define(&Ym, 3, 3, controller->measuredDirections);
88  matrix_define(&Wm, 3, 1, controller->measuredGyrorates);
89 
90  /* Allocate the necessary memory */
91  matrix_allocate(&Rrm, 3, 3);
92  matrix_allocate(&Rhatm, 3, 3);
93  matrix_allocate(&Yrm, 3, 3);
94  matrix_allocate(&Yhatm, 3, 3);
95 
96  matrix_allocate(&DRm, 3, 1);
97  matrix_allocate(&DWm, 3, 1);
98 
99  matrix_allocate(&vecAm, 3, 1);
100  matrix_allocate(&vecBm, 3, 1);
101  matrix_allocate(&vecCm, 3, 1);
102  matrix_allocate(&vecDm, 3, 1);
103 
104  matrix_allocate(&tmp33m, 3, 3);
105  matrix_allocate(&tmp31Am, 3, 1);
106  matrix_allocate(&tmp31Bm, 3, 1);
107 
108  /* Convert quaternions to elements on SO(3) */
109  cont_quat_2_SO3(&Qrm, &Rrm);
110  cont_quat_2_SO3(&Qhatm, &Rhatm );
111 
112  /* Compute the directions rotated by the refernce and estimate rotations */
113  mat_trans(&Rrm, &tmp33m);
114  mat_mul(&tmp33m, &Vm, &Yrm);
115  mat_trans(&Rhatm, &tmp33m);
116  mat_mul(&tmp33m, &Vm, &Yhatm);
117 
118  /* Compute the error terms {whate = wr - what; we = wr - w; wtilde = what - w; } */
119  matrix_allocate(&Whatem, 3, 1);
120  matrix_allocate(&Wem, 3, 1);
121  matrix_allocate(&Wtildem, 3, 1);
122  mat_sub(&Wrm, &Whatm, &Whatem );
123  mat_sub(&Wrm, &Wm , &Wem );
124  mat_sub(&Whatm, &Wm , &Wtildem);
125 
126  /*****************************************************************************
127  * Compute the control signal torques in four distict components, as
128  *
129  * tau = +taur ... =A
130  * +S(J*whate)*wr... =B
131  * +Kw*whate... =C
132  * +k1*S(Rr'*v1)*(Rhat'*v1)...
133  * +k2*S(Rr'*v2)*(Rhat'*v2)... =D
134  * +k3*S(Rr'*v3)*(Rhat'*v3)
135  ****************************************************************************/
136 
137  /****** Computation of A ******/
138  /* vecA = J*dwr */
139  mat_mul(&Jm, &Arm, &vecAm);
140  /* tmpA = J*wr */
141  mat_mul(&Jm, &Wrm, &tmp31Am);
142  /* tmpB = S(J*wr)*wr */
143  cont_cross_product(&tmp31Am, &Wrm, &tmp31Bm);
144  /* vecA = vecA - S(J*wr)*wr */
145  mat_sub_inplace(&vecAm, &tmp31Bm);
146 
147  /****** Computation of B ******/
148  /* tmpA = J*whate */
149  mat_mul(&Jm, &Whatem, &tmp31Am);
150  /* vecB = S(J*whate)*wr */
151  cont_cross_product(&tmp31Am, &Wrm, &vecBm);
152 
153  /****** Computation of C ******/
154  /* vecC = Kw*whate) */
155  mat_mul(&gain_Kwm, &Whatem, &vecCm);
156 
157  /****** Computation of D ******/
158  assert(1 == attitude_FOF_SO3_continuous_cross_terms(&Yrm, &Yhatm, &gain_ki_m, &vecDm));
159 
160  /* Form the control signal torque as tau = vecA + vecB + vecC + vecD */
161  for ( i = 0; i < 3; i++ ) Tm.pData[i] = vecAm.pData[i] + vecBm.pData[i] + vecCm.pData[i] + vecDm.pData[i];
162 
163  /*****************************************************************************
164  * Compute the estimator rotation innovation terms, as
165  *
166  * DR = -cR * (+k1 * S(Rhat'*v1)*(Rr'*v1 + R'*v1)...
167  * +k2 * S(Rhat'*v2)*(Rr'*v2 + R'*v2)...
168  * +k3 * S(Rhat'*v3)*(Rr'*v3 + R'*v3))
169  *****************************************************************************/
170  mat_add(&Yrm, &Ym, &tmp33m);
171  assert(1 == attitude_FOF_SO3_continuous_cross_terms(&Yhatm, &tmp33m, &gain_ki_m, &DRm));
172  for (i = 0; i < 3; i++ ) DRm.pData[i] *= -controller->gain_cR;
173 
174  /*****************************************************************************
175  * Compute the estimator rotation innovation terms, as
176  *
177  * DW = -cw * J * S(wr)*we...
178  * -cw * Kw * we...
179  * -Cw * wtilde;
180  *****************************************************************************/
181  matrix_zero(&DWm);
182  /* tmpA = S(wr)*we */
183  cont_cross_product(&Wrm, &Wem, &tmp31Am);
184  /* DW = J*S(wr)*we */
185  mat_mul(&Jm, &tmp31Am, &DWm);
186  /* tmpA = Kw * we */
187  mat_mul(&gain_Kwm, &Wem, &tmp31Am);
188  /* DW = J*S(wr)*we + Kw * we */
189  mat_add_inplace(&DWm, &tmp31Am);
190  /* DW = -cw * (J*S(wr)*we + Kw * we) */
191  for (i = 0; i < 3; i++ ) DWm.pData[i] *= -controller->gain_cw;
192  /* tmpA = Cw * wtilde */
193  mat_mul(&gain_Cwm, &Wtildem, &tmp31Am);
194  /* DW = -cw * (J*S(wr)*we + Kw * we) - Cw * wtilde */
195  mat_sub_inplace(&DWm, &tmp31Am);
196 
197  /*****************************************************************************
198  * Simulate the observer one time-step using a first order euler method, with
199  *
200  * Rhatdot = Rhat*S(w + DR);
201  * whatdot = (J)\(S(J*w)*w + tau + DW);
202  *
203  * Although, the simulation of the attitude will be done on SU(2).
204  *****************************************************************************/
205  /* tmpB = J*w */
206  mat_mul(&Jm, &Wm, &tmp31Bm);
207  /* tmpA = S(J*w)*w */
208  cont_cross_product(&tmp31Bm, &Wm, &tmp31Am);
209  /* tmpA = S(J*w)*w + tau */
210  mat_add_inplace(&tmp31Am, &Tm);
211  /* tmpA = S(J*w)*w + tau + DW */
212  mat_add_inplace(&tmp31Am, &DWm);
213  /* tmpB = J\(S(J*w)*w + tau + DW) */
214  mat_mul(&invJm, &tmp31Am, &tmp31Bm);
215  /* tmpA = w + DR */
216  mat_add(&Wm, &DRm, &tmp31Am);
217  /* Simulate the dynamics one time-step and project the attitude onto SU(2) */
218  assert(1 == attitude_FOF_SO3_continuous_simulate_observer(&Qhatm, &Whatm, &tmp31Am, &tmp31Bm, dt));
219 
220  /* Free the allocated memory */
221  free(Rrm.pData);
222  free(Rhatm.pData);
223  free(Yrm.pData);
224  free(Yhatm.pData);
225 
226  free(DRm.pData);
227  free(DWm.pData);
228 
229  free(Whatem.pData);
230  free(Wem.pData);
231  free(Wtildem.pData);
232 
233  free(tmp33m.pData);
234  free(tmp31Am.pData);
235  free(tmp31Bm.pData);
236 
237  free(vecAm.pData);
238  free(vecBm.pData);
239  free(vecCm.pData);
240  free(vecDm.pData);
241 
242  return 1;
243 }
244 
246  matrix_double_t * Qm,
247  matrix_double_t * Wm,
248  matrix_double_t * deltaQm,
249  matrix_double_t * deltaWm,
250  double dt
251 ){
252 
253  int i;
254  matrix_double_t tmp31m, tmp41Am, tmp41Bm;
255 
256  if ((Qm->numRows != 4) ||
257  (Qm->numCols != 1) ||
258  (Wm->numRows != 3) ||
259  (Wm->numCols != 1) ||
260  (deltaQm->numRows != 3) ||
261  (deltaQm->numCols != 1) ||
262  (deltaWm->numRows != 3) ||
263  (deltaWm->numCols != 1) ||
264  (dt < 0)) {
265  TRACE(5, ("Bad inputs to the FOF attitude observer simulator\n"));
266  return 0;
267  }
268 
269  matrix_allocate(&tmp31m, 3, 1);
270  matrix_allocate(&tmp41Am, 4, 1);
271  matrix_allocate(&tmp41Bm, 4, 1);
272 
273  /* Simulate the attitude observer */
274  for (i = 0; i < 3; i++ ) tmp31m.pData[i] = dt * deltaQm->pData[i];
275  if(0 == cont_SU2_Exp(&tmp31m, &tmp41Am)) return 0;
276  if(0 == cont_SU2_product(Qm, &tmp41Am, &tmp41Bm)) return 0;
277  for (i = 0; i < 4; i++ ) Qm->pData[i] = tmp41Bm.pData[i];
278 
279  /* Normalize the resulting quaternion (should not be needed) given the
280  implemeted numerical integration scheme, but is done anyway */
281  cont_normalize(Qm);
282 
283  /* Simulate the rate observer */
284  for (i = 0; i < 3; i++ ) Wm->pData[i] += dt * deltaWm->pData[i];
285 
286  /* free allocated memory */
287  free(tmp31m.pData);
288  free(tmp41Am.pData);
289  free(tmp41Bm.pData);
290  return 1;
291 }
292 
294  matrix_double_t * YAm,
295  matrix_double_t * YBm,
296  matrix_double_t * gainm,
297  matrix_double_t * outm
298 ){
299  matrix_double_t tmp31Am, tmp31Bm, tmp31Cm;
300  int i, j;
301 
302  if ((YAm->numRows != 3) || (YBm->numRows != 3) || (gainm->numRows != 1)) {
303  TRACE(5, ("The directional matrices must have three rows, and the gains must have a single row\n"));
304  return 0;
305  }
306  if ((YAm->numCols < 3) || (YBm->numCols < 3)) {
307  TRACE(5, ("The directional matrices must have at least three columns\n"));
308  return 0;
309  }
310  if ((YAm->numCols != YBm->numCols) || (YAm->numCols != gainm->numCols)) {
311  TRACE(5, ("The directional matrices must have the same number of columns\n"));
312  return 0;
313  }
314 
315  /* Input error check */
316  matrix_allocate(&tmp31Am, 3, 1);
317  matrix_allocate(&tmp31Bm, 3, 1);
318  matrix_allocate(&tmp31Cm, 3, 1);
319 
320  matrix_zero(outm);
321  for ( i = 0; i < YAm->numCols; i++ ){
322  /* Extract vectors and muliply the second vector with the associated gain */
323  for ( j = 0; j < 3; j++ ){
324  matrix_set(&tmp31Am, j, 0, matrix_get(YAm, j, i));
325  matrix_set(&tmp31Bm, j, 0, gainm->pData[i]*matrix_get(YBm, j, i));
326  }
327  /* Take the cross product and add to the output */
328  cont_cross_product(&tmp31Am, &tmp31Bm, &tmp31Cm);
329  mat_add_inplace(outm, &tmp31Cm);
330  }
331 
332  free(tmp31Am.pData);
333  free(tmp31Bm.pData);
334  free(tmp31Cm.pData);
335 
336  return 1;
337 }
matrix_double_s::pData
double * pData
Definition: cont_types.h:59
con_state_qw_fof_s::measuredDirections
double measuredDirections[9]
Definition: cont_types.h:104
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
con_state_qw_fof_s::gain_Cw
double gain_Cw[9]
Definition: cont_types.h:96
ref_state_qw_s::alpha
double alpha[3]
Definition: cont_types.h:114
ref_state_qw_s::omega
double omega[3]
Definition: cont_types.h:113
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
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
con_state_qw_fof_s::gain_cR
double gain_cR
Definition: cont_types.h:98
update_attitude_FOF_SO3_continuous_measurements
int update_attitude_FOF_SO3_continuous_measurements(con_state_qw_fof_t *controller, matrix_double_t *y0m, matrix_double_t *y1m, matrix_double_t *y2m, matrix_double_t *y3m)
Help function used to update the measurements in the controller struct.
Definition: cont_attitude_FOF_SO3_continuous.c:10
matrix_double_s
Matrix object used for all matrix manipulation.
Definition: cont_types.h:50
dyn_state_qw_s::omega
double omega[3]
Definition: cont_types.h:61
attitude_FOF_SO3_continuous_simulate_observer
int attitude_FOF_SO3_continuous_simulate_observer(matrix_double_t *Qm, matrix_double_t *Wm, matrix_double_t *deltaQm, matrix_double_t *deltaWm, double dt)
Help function to simulate the attitude observer dynamics.
Definition: cont_attitude_FOF_SO3_continuous.c:245
mat_add_inplace
void mat_add_inplace(matrix_double_t *Amat, matrix_double_t *Bmat)
In-place matrix addition, A <– A + B, asserts that this is done correctly.
Definition: cont_matrix_math.c:249
con_state_qw_fof_s::gain_ki
double gain_ki[3]
Definition: cont_types.h:95
attitude_FOF_SO3_continuous_cross_terms
int attitude_FOF_SO3_continuous_cross_terms(matrix_double_t *YAm, matrix_double_t *YBm, matrix_double_t *gainm, matrix_double_t *outm)
Help function used to compute the innovation terms in the controller.
Definition: cont_attitude_FOF_SO3_continuous.c:293
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
ref_state_qw_s
Reference signal structure for the attitude FSF on S(3) or SU(2)
Definition: cont_types.h:111
matrix_double_s::numCols
int numCols
Definition: cont_types.h:58
update_attitude_FOF_SO3_continuous
int update_attitude_FOF_SO3_continuous(ref_state_qw_t *reference, dyn_state_qw_t *state, con_state_qw_fof_t *controller, double dt)
Update using the continuous filtered outpot feedback (FOF) on SO(3)
Definition: cont_attitude_FOF_SO3_continuous.c:44
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
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
matrix_define
void matrix_define(matrix_double_t *matrix, int numRows, int numCols, double *data)
Define a matrix to use already allocated memory.
Definition: cont_types.c:75
con_state_qw_fof_s
Complete state of the attitude FOF on SO(3) or SU(2)
Definition: cont_types.h:89
dyn_state_qw_s
Dynamical states, assumed known in the attitude FSF on SO(3) or SU(2)
Definition: cont_types.h:59
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
dyn_state_qw_s::quaternion
double quaternion[4]
Definition: cont_types.h:60
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
mat_sub
void mat_sub(matrix_double_t *Amat, matrix_double_t *Bmat, matrix_double_t *Cmat)
Matrix subtraction, C <– A - B, and asserts that this is done correctly.
Definition: cont_matrix_math.c:252
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
mat_add
void mat_add(matrix_double_t *Amat, matrix_double_t *Bmat, matrix_double_t *Cmat)
Matrix addition, C <– A + B, asserts that this is done correctly.
Definition: cont_matrix_math.c:246
con_state_qw_fof_s::measuredGyrorates
double measuredGyrorates[3]
Definition: cont_types.h:103
con_state_qw_fof_s::gain_cw
double gain_cw
Definition: cont_types.h:97
con_state_qw_fof_s::invinertia
double invinertia[9]
Definition: cont_types.h:93
con_state_qw_fof_s::globalDirections
double globalDirections[9]
Definition: cont_types.h:105
cont_attitude_FOF_SO3_continuous.h
con_state_qw_fof_s::torque
double torque[3]
Definition: cont_types.h:91
con_state_qw_fof_s::inertia
double inertia[9]
Definition: cont_types.h:92
cont_normalize
int cont_normalize(matrix_double_t *vec)
Normalizes the vector.
Definition: cont_math.c:378
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
con_state_qw_fof_s::gain_Kw
double gain_Kw[9]
Definition: cont_types.h:94
ref_state_qw_s::quaternion
double quaternion[4]
Definition: cont_types.h:112
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