Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
obm_cyclone.c
Go to the documentation of this file.
2#include<math.h>
3
4#if ANDI_NUM_ACT != 4
5 #error Cyclone expects 4 actuators
6#endif
7
8#if ANDI_OUTPUTS != 4
9 #error The cyclone model provides 4 outputs
10#endif
11
13 struct {
14 // X-axis force coefficients (f_ff_x)
15 float fx_motor_squared; // Motor thrust squared effect
16 float fx_speed_forward; // Forward speed effect
17
18 // Y-axis force coefficients (f_ff_y)
19 float fy_speed_lateral; // Lateral speed effect
20
21 // Z-axis force coefficients (f_ff_z)
22 float fz_motor_squared; // Motor thrust squared effect
23 float fz_speed_forward; // Forward speed effect
24 float fz_speed_vertical; // Vertical speed effect
25 float fz_elevon_speed; // Elevon-speed coupling
26 float fz_elevon_motor; // Elevon-motor coupling
27
28 // X-axis moment coefficients (m_ff_x)
29 float mx_elevon_motor_diff; // (ele_l * motor_l^2 - ele_r * motor_r^2)
30 float mx_elevon_speed_diff; // (ele_l - ele_r) * speed * v_ff(1)
31 float mx_angular_drag; // w_ff(1)^2
32 float mx_angular_coupling; // w_ff(2) * w_ff(3)
33
34 // Y-axis moment coefficients (m_ff_y)
35 float my_speed_forward; // speed * v_ff(1)
36 float my_speed_vertical; // speed * v_ff(3)
37 float my_motor_sum; // motor_l^2 + motor_r^2
38 float my_elevon_motor_sum; // ele_l * motor_l^2 + ele_r * motor_r^2
39 float my_elevon_speed_sum; // (ele_l + ele_r) * speed * v_ff(1)
40 float my_angular_sum; // w_ff(1) + w_ff(3)
41
42 // Z-axis moment coefficients (m_ff_z)
43 float mz_speed_lateral; // speed * v_ff(2)
44 float mz_motor_diff; // motor_l^2 - motor_r^2
45 float mz_speed_roll; // speed * w_ff(1)
46 float mz_angular_coupling; // w_ff(1) * w_ff(2)
47
48 // Fixme: Move to x-axis moment coefficients
49 };
50 float data[22];
51};
52
53// Model coefficinets
55 .fx_motor_squared = 0.00000735f,
56 .fx_speed_forward = -0.03f,
57
58 .fy_speed_lateral = -0.008f,
59
60 .fz_motor_squared = 0.0f,
61 .fz_speed_forward = 0.0f,
62 .fz_speed_vertical = -0.144f,
63 .fz_elevon_speed = 0.0f,
64 .fz_elevon_motor = 0.0f,
65
66 .mx_elevon_motor_diff = 1.9e-05f,
67 .mx_elevon_speed_diff = 0.344f,
68 .mx_angular_drag = -0.4940217f,
69 .mx_angular_coupling = -2.18f,
70
71 .my_speed_forward = 0.0f,
72 .my_speed_vertical = -0.0888f,
73 .my_motor_sum = 0.0f,
74 .my_elevon_motor_sum = -0.0000424f,
75 .my_elevon_speed_sum = 0.2525f,
76 .my_angular_sum = 1.262f,
77
78 .mz_speed_lateral = -0.00371f,
79 .mz_motor_diff = 0.000039f,
80 .mz_speed_roll = -0.0129f,
81 .mz_angular_coupling = -0.4827f,
82};
83
84union CeMatrix {
85 struct {
86 float ce_11;
87 float ce_12;
88 float ce_13;
89 float ce_14;
90 float ce_21;
91 float ce_22;
92 float ce_23;
93 float ce_24;
94 float ce_31;
95 float ce_32;
96 float ce_33;
97 float ce_34;
98 float ce_41;
99 float ce_42;
100 float ce_43;
101 float ce_44;
102
103 };
104 float data[16];
105};
106
107// Model coefficinets
109 .ce_11 = 0.0f, .ce_12 = 0.0f, .ce_13 = 3.9e-5f, .ce_14 = -3.9e-5f, // Roll
110 .ce_21 = -29.917439f, .ce_22 = -29.917439f, .ce_23 = 0.0f, .ce_24 = 0.0f, // Pitch
111 .ce_31 = -19.968481f, .ce_32 = 19.968481f, .ce_33 = 0.0f, .ce_34 = 0.0f, // Yaw
112 .ce_41 = 0.0f, .ce_42 = 0.0f, .ce_43 = 7e-6f, .ce_44 = 7e-6f, // Thrust
113};
114
115
116/* Function Definitions */
117static void cyclone_obm_forces(const float body_vel[3], const float u[4],
118 const float coeff[22], float F_obm_forces[3])
119{
120 float t2;
121 float t7;
122 t2 = u[2] + u[3];
123 t7 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
124 F_obm_forces[0] = coeff[3] * t2
125 + coeff[7] * (u[0] * u[2] + u[1] * u[3])
126 + coeff[5] * t7 * body_vel[0]
127 - coeff[4] * t7 * body_vel[2]
128 - coeff[6] * t7 * body_vel[2] * (u[0] + u[1]);
129 F_obm_forces[1] = coeff[2] * t7 * body_vel[1];
130 F_obm_forces[2] = -coeff[0] * t2 + coeff[1] * t7 * body_vel[2];
131}
132
133static void cyclone_obm_moments(const float rates[3],
134 const float body_vel[3], const float u[4],
135 const float coeff[22], float F_obm_moments[3])
136{
137 float t2;
138 float t3;
139 float t8;
140 t2 = u[0] * u[2];
141 t3 = u[1] * u[3];
142 t8 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
143 F_obm_moments[0] = coeff[19] * (u[2] - u[3])
144 + coeff[18] * t8 * body_vel[1]
145 - coeff[20] * t8 * rates[2]
146 - rates[1] * coeff[21] * rates[2];
147 F_obm_moments[1] = coeff[15] * (t2 + t3)
148 + coeff[14] * (u[2] + u[3])
149 + coeff[13] * t8 * body_vel[0]
150 - coeff[12] * t8 * body_vel[2]
151 - rates[0] * coeff[17] * rates[2]
152 - coeff[16] * t8 * body_vel[2] * (u[0] + u[1]);
153 F_obm_moments[2] = -coeff[8] * (t2 - t3)
154 + coeff[10] * fabsf(rates[2]) * rates[2]
155 - rates[0] * coeff[11] * rates[1]
156 + coeff[9] * t8 * body_vel[2] * (u[0] - u[1]);
157}
158
159
160static void cyclone_f_stb_u(const float body_vel[3],
161 const float u[4], const float coeff[22], float F_stb_u[16])
162{
163 float fv[16];
164 float t6;
165 float t7;
166 int i;
167 int i1;
168 int i2;
169 t6 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
170 t7 = coeff[9] * t6 * body_vel[2];
171 t6 = coeff[16] * t6 * body_vel[2];
172 fv[0] = 0.0F;
173 fv[1] = -t6 + u[2] * coeff[15];
174 fv[2] = t7 - u[2] * coeff[8];
175 fv[3] = 0.0F;
176 fv[4] = 0.0F;
177 fv[5] = -t6 + u[3] * coeff[15];
178 fv[6] = -t7 + u[3] * coeff[8];
179 fv[7] = 0.0F;
180 fv[8] = coeff[19];
181 fv[9] = coeff[14] + u[0] * coeff[15];
182 fv[10] = -coeff[8] * u[0];
183 fv[11] = coeff[0];
184 fv[12] = -coeff[19];
185 fv[13] = coeff[14] + u[1] * coeff[15];
186 fv[14] = u[1] * coeff[8];
187 fv[15] = coeff[0];
188 i = 0;
189 i1 = 0;
190 for (i2 = 0; i2 < 16; i2++) {
191 F_stb_u[i1 + (i << 2)] = fv[i2];
192 i++;
193 if (i > 3) {
194 i = 0;
195 i1++;
196 }
197 }
198}
199
200/* Function Definitions */
201void cyclone_f_stb_x(const float rates[3], const float ang_accel[3],
202 const float vel_body[3], const float accel_body[3], const float u[4],
203 const float coeff[22], float F_stb_x[4])
204{
205 float F_stb_x_tmp;
206 float b_F_stb_x_tmp;
207 float c_F_stb_x_tmp;
208 float d_F_stb_x_tmp;
209 float et1_tmp;
210 float t10;
211 float t12;
212 float t15;
213 float t8;
214 float t9;
215 t8 = vel_body[0] * vel_body[0];
216 t9 = vel_body[1] * vel_body[1];
217 t10 = vel_body[2] * vel_body[2];
218 t12 = u[0] - u[1];
219 t15 = sqrtf((t8 + t9) + t10);
220 et1_tmp = fmaxf(1.0E-8F, t15);
221 F_stb_x[0] = -(
222 -accel_body[1] * coeff[18] * t9
223 - accel_body[0] * coeff[18] * vel_body[0] * vel_body[1]
224 - accel_body[2] * coeff[18] * vel_body[1] * vel_body[2]
225 + accel_body[0] * coeff[20] * vel_body[0] * rates[2]
226 + accel_body[1] * coeff[20] * vel_body[1] * rates[2]
227 + accel_body[2] * coeff[20] * vel_body[2] * rates[2]
228 - accel_body[1] * coeff[18] * t15 * et1_tmp
229 + coeff[20] * t15 * ang_accel[2] * et1_tmp
230 + rates[1] * coeff[21] * ang_accel[2] * et1_tmp
231 + rates[2] * coeff[21] * ang_accel[1] * et1_tmp
232 ) / et1_tmp;
233
234 t9 = accel_body[2] * coeff[12];
235 F_stb_x_tmp = accel_body[2] * coeff[16];
236 b_F_stb_x_tmp = accel_body[0] * coeff[16];
237 c_F_stb_x_tmp = accel_body[1] * coeff[16];
238 d_F_stb_x_tmp = F_stb_x_tmp * u[0];
239 F_stb_x_tmp *= u[1];
240 F_stb_x[1] = -(
241 -accel_body[0] * coeff[13] * t8 + t9 * t10
242 + accel_body[0] * coeff[12] * vel_body[0] * vel_body[2]
243 - accel_body[1] * coeff[13] * vel_body[0] * vel_body[1]
244 + accel_body[1] * coeff[12] * vel_body[1] * vel_body[2]
245 - accel_body[1] * coeff[12] * vel_body[1] * vel_body[2]
246 - accel_body[2] * coeff[13] * vel_body[0] * vel_body[2]
247 - accel_body[0] * coeff[13] * t15 * et1_tmp
248 + t9 * t15 * et1_tmp
249 + rates[0] * coeff[17] * ang_accel[2] * et1_tmp
250 + rates[2] * coeff[17] * ang_accel[0] * et1_tmp
252 + F_stb_x_tmp * t10
253 + b_F_stb_x_tmp * u[0] * vel_body[0] * vel_body[2]
254 + c_F_stb_x_tmp * u[0] * vel_body[1] * vel_body[2]
255 + b_F_stb_x_tmp * u[1] * vel_body[0] * vel_body[2]
256 + c_F_stb_x_tmp * u[1] * vel_body[1] * vel_body[2]
259 ) / et1_tmp;
260 F_stb_x[2] = accel_body[2] * (coeff[9] * t12 * t15 + coeff[9] * t10 * t12 / et1_tmp)
261 - rates[0] * coeff[11] * ang_accel[1]
262 - rates[1] * coeff[11] * ang_accel[0]
263 + 2.0F * coeff[10] * fabsf(rates[2]) * ang_accel[2]
264 + accel_body[0] * coeff[9] * t12 * vel_body[0] * vel_body[2] / et1_tmp
265 + accel_body[1] * coeff[9] * t12 * vel_body[1] * vel_body[2] / et1_tmp;
266 F_stb_x[3] = 0.0F;
267}
268
269
270
271/* End of code generation (cyclone_f_stb_x.c) */
272
273struct FloatVect3 evaluate_obm_forces(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
274 const float actuator_state[ANDI_NUM_ACT])
275{
276 float vel_body_array[3];
277 (void)rates;
278
279 vel_body_array[0] = vel_body->x;
280 vel_body_array[1] = vel_body->y;
281 vel_body_array[2] = vel_body->z;
282
283 float forces_array[3];
285
286 struct FloatVect3 forces;
287 forces.x = forces_array[0];
288 forces.y = forces_array[1];
289 forces.z = forces_array[2];
290
291 return forces;
292}
293
294struct FloatVect3 evaluate_obm_moments(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
295 const float actuator_state[ANDI_NUM_ACT])
296{
297 float vel_body_array[3];
298 float rates_array[3];
299
300 vel_body_array[0] = vel_body->x;
301 vel_body_array[1] = vel_body->y;
302 vel_body_array[2] = vel_body->z;
303
304 rates_array[0] = rates->p;
305 rates_array[1] = rates->q;
306 rates_array[2] = rates->r;
307
308 float moments_array[3];
310 struct FloatVect3 moments;
312 moments.y = moments_array[1];
313 moments.z = moments_array[2];
314
315 return moments;
316}
317
318
320 const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
321{
322 float vel_body_array[3];
323 (void)rates;
324
325 vel_body_array[0] = vel_body->x;
326 vel_body_array[1] = vel_body->y;
327 vel_body_array[2] = vel_body->z;
328
329 // Bound min motor speed in actuator_state to prevent really low control effectiveness which may result in instabilities.
330 // This should make "free fall" more stable at the cost of some model inaccuracy at very low thrust.
331 // FIXME: Rethink this solution.
332 // FIXME: Apply this bounding directly on the elevon effectiveness terms in the final matrix instead of modifying actuator_state.
333 // FIXME: Would it be possible to dynamically identify or saturate the control effectiveness?
337 actuator_state_bounded[2] = fmaxf(actuator_state[2], 360000.0f);
338 actuator_state_bounded[3] = fmaxf(actuator_state[3], 360000.0f);
339
341
342 fu_mat = ce_mat_tmp.data; // FIXME: Temporary hack to use ce_mat instead of the real computed matrix
343}
344
345void evaluate_obm_f_stb_x(float nu_obm[ANDI_OUTPUTS], const struct FloatRates *rates,
346 const struct FloatVect3 *vel_body, const struct FloatVect3 *ang_accel, const struct FloatVect3 *accel_body,
347 const float actuator_state[ANDI_NUM_ACT])
348{
349 float rates_array[3];
350 float ang_accel_array[3];
351 float vel_body_array[3];
352 float accel_body_array[3];
353
354 rates_array[0] = rates->p;
355 rates_array[1] = rates->q;
356 rates_array[2] = rates->r;
357
358 ang_accel_array[0] = ang_accel->x;
359 ang_accel_array[1] = ang_accel->y;
360 ang_accel_array[2] = ang_accel->z;
361
362 vel_body_array[0] = vel_body->x;
363 vel_body_array[1] = vel_body->y;
364 vel_body_array[2] = vel_body->z;
365
369
370
372 nu_obm);
373}
374
376{
377 return obm_coefficients.fx_motor_squared * (actuator_state[2] + actuator_state[3]);
378}
float q
in rad/s
float p
in rad/s
float r
in rad/s
angular rates
float moments[MOMENT_DELAY]
Definition ins_flow.c:169
uint16_t foo
Definition main_demo5.c:58
union CycloneCoefficients obm_coefficients
Definition obm_cyclone.c:54
union CeMatrix ce_mat_tmp
static void cyclone_obm_forces(const float body_vel[3], const float u[4], const float coeff[22], float F_obm_forces[3])
float evaluate_obm_thrust_z(const float actuator_state[ANDI_NUM_ACT])
Compute total thrust produced by the current actuator state.
float data[16]
void cyclone_f_stb_x(const float rates[3], const float ang_accel[3], const float vel_body[3], const float accel_body[3], const float u[4], const float coeff[22], float F_stb_x[4])
static void cyclone_f_stb_u(const float body_vel[3], const float u[4], const float coeff[22], float F_stb_u[16])
struct FloatVect3 evaluate_obm_forces(const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate total force acting on the vehicle from the OBM.
struct FloatVect3 evaluate_obm_moments(const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate total moments acting on the vehicle from the OBM.
void evaluate_obm_f_stb_u(float fu_mat[ANDI_NUM_ACT *ANDI_OUTPUTS], const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate the state-dependent control effectiveness matrix F_u for stabilization.
void evaluate_obm_f_stb_x(float nu_obm[ANDI_OUTPUTS], const struct FloatRates *rates, const struct FloatVect3 *vel_body, const struct FloatVect3 *ang_accel, const struct FloatVect3 *accel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate the state-dependent contribution F_x * x_dot for stabilization.
static void cyclone_obm_moments(const float rates[3], const float body_vel[3], const float u[4], const float coeff[22], float F_obm_moments[3])
#define ANDI_NUM_ACT
#define ANDI_OUTPUTS
float actuator_state[ANDI_NUM_ACT]
float nu_obm[ANDI_OUTPUTS]
ANDI stabilization controller for tiltbody rotorcraft.