Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
eff_scheduling_rot_wing.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Dennis van Wijngaarden <D.C.vanWijngaarden@tudelft.nl>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
27 
28 #include "generated/airframe.h"
29 #include "state.h"
30 
32 
34 #include "modules/core/abi.h"
35 
36 #ifndef SERVO_ROTATION_MECH_IDX
37 #error ctrl_eff_sched_rot_wing requires a servo named ROTATION_MECH_IDX
38 #endif
39 
40 #ifndef ROT_WING_EFF_SCHED_IXX_BODY
41 #error "NO ROT_WING_EFF_SCHED_IXX_BODY defined"
42 #endif
43 
44 #ifndef ROT_WING_EFF_SCHED_IYY_BODY
45 #error "NO ROT_WING_EFF_SCHED_IYY_BODY defined"
46 #endif
47 
48 #ifndef ROT_WING_EFF_SCHED_IZZ
49 #error "NO ROT_WING_EFF_SCHED_IZZ defined"
50 #endif
51 
52 #ifndef ROT_WING_EFF_SCHED_IXX_WING
53 #error "NO ROT_WING_EFF_SCHED_IXX_WING defined"
54 #endif
55 
56 #ifndef ROT_WING_EFF_SCHED_IYY_WING
57 #error "NO ROT_WING_EFF_SCHED_IYY_WING defined"
58 #endif
59 
60 #ifndef ROT_WING_EFF_SCHED_M
61 #error "NO ROT_WING_EFF_SCHED_M defined"
62 #endif
63 
64 #ifndef ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_PITCH
65 #error "NO ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_PITCH defined"
66 #endif
67 
68 #ifndef ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_ROLL
69 #error "NO ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_ROLL defined"
70 #endif
71 
72 #ifndef ROT_WING_EFF_SCHED_HOVER_ROLL_PITCH_COEF
73 #error "NO ROT_WING_EFF_SCHED_HOVER_ROLL_PITCH_COEF defined"
74 #endif
75 
76 #ifndef ROT_WING_EFF_SCHED_HOVER_ROLL_ROLL_COEF
77 #error "NO ROT_WING_EFF_SCHED_HOVER_ROLL_ROLL_COEF defined"
78 #endif
79 
80 #ifndef ROT_WING_EFF_SCHED_K_ELEVATOR
81 #error "NO ROT_WING_EFF_SCHED_K_ELEVATOR defined"
82 #endif
83 
84 #ifndef ROT_WING_EFF_SCHED_K_RUDDER
85 #error "NO ROT_WING_EFF_SCHED_K_RUDDER defined"
86 #endif
87 
88 #ifndef ROT_WING_EFF_SCHED_K_AILERON
89 #error "NO ROT_WING_EFF_SCHED_K_AILERON defined"
90 #endif
91 
92 #ifndef ROT_WING_EFF_SCHED_K_FLAPERON
93 #error "NO ROT_WING_EFF_SCHED_K_FLAPERON defined"
94 #endif
95 
96 #ifndef ROT_WING_EFF_SCHED_K_PUSHER
97 #error "NO ROT_WING_EFF_SCHED_K_PUSHER defined"
98 #endif
99 
100 #ifndef ROT_WING_EFF_SCHED_K_ELEVATOR_DEFLECTION
101 #error "NO ROT_WING_EFF_SCHED_K_ELEVATOR_DEFLECTION defined"
102 #endif
103 
104 #ifndef ROT_WING_EFF_SCHED_D_RUDDER_D_PPRZ
105 #error "NO ROT_WING_EFF_SCHED_D_RUDDER_D_PPRZ defined"
106 #endif
107 
108 #ifndef ROT_WING_EFF_SCHED_K_RPM_PPRZ_PUSHER
109 #error "NO ROT_WING_EFF_SCHED_K_RPM_PPRZ_PUSHER defined"
110 #endif
111 
112 #ifndef ROT_WING_EFF_SCHED_K_LIFT_WING
113 #error "NO ROT_WING_EFF_SCHED_K_LIFT_WING defined"
114 #endif
115 
116 #ifndef ROT_WING_EFF_SCHED_K_LIFT_FUSELAGE
117 #error "NO ROT_WING_EFF_SCHED_K_LIFT_FUSELAGE defined"
118 #endif
119 
120 #ifndef ROT_WING_EFF_SCHED_K_LIFT_TAIL
121 #error "NO ROT_WING_EFF_SCHED_K_LIFT_TAIL defined"
122 #endif
123 
125  .Ixx_body = ROT_WING_EFF_SCHED_IXX_BODY,
126  .Iyy_body = ROT_WING_EFF_SCHED_IYY_BODY,
127  .Izz = ROT_WING_EFF_SCHED_IZZ,
128  .Ixx_wing = ROT_WING_EFF_SCHED_IXX_WING,
129  .Iyy_wing = ROT_WING_EFF_SCHED_IYY_WING,
130  .m = ROT_WING_EFF_SCHED_M,
131  .DMdpprz_hover_roll = ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_ROLL,
132  .hover_roll_pitch_coef = ROT_WING_EFF_SCHED_HOVER_ROLL_PITCH_COEF,
133  .hover_roll_roll_coef = ROT_WING_EFF_SCHED_HOVER_ROLL_ROLL_COEF,
134  .k_elevator = ROT_WING_EFF_SCHED_K_ELEVATOR,
135  .k_rudder = ROT_WING_EFF_SCHED_K_RUDDER,
136  .k_aileron = ROT_WING_EFF_SCHED_K_AILERON,
137  .k_flaperon = ROT_WING_EFF_SCHED_K_FLAPERON,
138  .k_pusher = ROT_WING_EFF_SCHED_K_PUSHER,
139  .k_elevator_deflection = ROT_WING_EFF_SCHED_K_ELEVATOR_DEFLECTION,
140  .d_rudder_d_pprz = ROT_WING_EFF_SCHED_D_RUDDER_D_PPRZ,
141  .k_rpm_pprz_pusher = ROT_WING_EFF_SCHED_K_RPM_PPRZ_PUSHER,
142  .k_lift_wing = ROT_WING_EFF_SCHED_K_LIFT_WING,
143  .k_lift_fuselage = ROT_WING_EFF_SCHED_K_LIFT_FUSELAGE,
144  .k_lift_tail = ROT_WING_EFF_SCHED_K_LIFT_TAIL
145 };
146 
148 
150 inline void eff_scheduling_rot_wing_update_MMOI(void);
151 inline void eff_scheduling_rot_wing_update_cmd(void);
160 
161 inline float guidance_indi_get_liftd(float pitch UNUSED, float theta UNUSED);
163 
164 
167 #ifndef WING_ROTATION_CAN_ROT_WING_ID
168 #define WING_ROTATION_CAN_ROT_WING_ID ABI_BROADCAST
169 #endif
170 PRINT_CONFIG_VAR(WING_ROTATION_CAN_ROT_WING_ID)
172 
173 static void wing_position_cb(uint8_t sender_id UNUSED, struct act_feedback_t *pos_msg, uint8_t num_act)
174 {
175  for (int i=0; i<num_act; i++){
176  if (pos_msg[i].set.position && (pos_msg[i].idx == SERVO_ROTATION_MECH_IDX))
177  {
178  // Get wing rotation angle from sensor
179  eff_sched_var.wing_rotation_rad = 0.5 * M_PI - pos_msg[i].position;
180 
181  // Bound wing rotation angle
182  Bound(eff_sched_var.wing_rotation_rad, 0, 0.5 * M_PI);
183  }
184  }
185 }
186 
188 {
189  // Initialize variables to quad values
192  eff_sched_var.wing_rotation_rad = 0; // ABI input
194  eff_sched_var.cosr = 1;
195  eff_sched_var.sinr = 0;
196  eff_sched_var.cosr2 = 1;
197  eff_sched_var.sinr2 = 0;
198  eff_sched_var.sinr3 = 0;
199 
200  // Set moment derivative variables
201  eff_sched_var.pitch_motor_dMdpprz = ROT_WING_EFF_SCHED_DM_DPPRZ_HOVER_PITCH;
202  eff_sched_var.roll_motor_dMdpprz = (eff_sched_p.DMdpprz_hover_roll[0] + (MAX_PPRZ/2.) * eff_sched_p.DMdpprz_hover_roll[1]) / 10000.; // Dmdpprz hover roll for hover thrust
203 
208 
211 
212  // Get wing angle
214 }
215 
217 {
218  // your periodic code here.
219  // freq = 10.0 Hz
224 
225  // Update the effectiveness values
233 }
234 
236 {
237  // Calculate sin and cosines of rotation
239 
242 
245 
247 
248 }
249 
251 {
254 
255  // Bound inertia
256  Bound(eff_sched_var.Ixx, 0.01, 100.);
257  Bound(eff_sched_var.Iyy, 0.01, 100.);
258 }
259 
261 {
262  // These indexes depend on the INDI sequence, not the actuator IDX
265  eff_sched_var.cmd_pusher_scaled = actuator_state_filt_vect[8] * 0.000853229; // Scaled with 8181 / 9600 / 1000
266  eff_sched_var.cmd_T_mean_scaled = (actuator_state_filt_vect[0] + actuator_state_filt_vect[1] + actuator_state_filt_vect[2] + actuator_state_filt_vect[3]) / 4. * 0.000853229; // Scaled with 8181 / 9600 / 1000
267 }
268 
270 {
272  Bound(eff_sched_var.airspeed, 0. , 30.);
274  Bound(eff_sched_var.airspeed2, 0. , 900.);
275 }
276 
278 {
279  // Pitch motor effectiveness
280 
281  float pitch_motor_q_eff = eff_sched_var.pitch_motor_dMdpprz / eff_sched_var.Iyy;
282 
283  // Roll motor effectiveness
284  float dM_dpprz_right = (eff_sched_p.DMdpprz_hover_roll[0] + actuator_state_filt_vect[1] * eff_sched_p.DMdpprz_hover_roll[1]) / 10000.;
285  float dM_dpprz_left = (eff_sched_p.DMdpprz_hover_roll[0] + actuator_state_filt_vect[3] * eff_sched_p.DMdpprz_hover_roll[1]) / 10000.;
286 
287  // Bound dM_dpprz to half and 2 times the hover effectiveness
288  Bound(dM_dpprz_right, eff_sched_var.roll_motor_dMdpprz * 0.5, eff_sched_var.roll_motor_dMdpprz * 2.0);
289  Bound(dM_dpprz_left, eff_sched_var.roll_motor_dMdpprz * 0.5, eff_sched_var.roll_motor_dMdpprz * 2.0);
290 
292  Bound(roll_motor_p_eff_right, -1, -0.00001);
293 
295  float roll_motor_airspeed_compensation = eff_sched_p.hover_roll_roll_coef[1] * eff_sched_var.airspeed * eff_sched_var.cosr / eff_sched_var.Ixx;
296  roll_motor_p_eff_left += roll_motor_airspeed_compensation;
297  Bound(roll_motor_p_eff_left, 0.00001, 1);
298 
300  Bound(roll_motor_q_eff, 0, 1);
301 
302  // Update front pitch motor q effectiveness
303  g1g2[1][0] = pitch_motor_q_eff; // pitch effectiveness front motor
304 
305  // Update back motor q effectiveness
306  g1g2[1][2] = -pitch_motor_q_eff; // pitch effectiveness back motor
307 
308  // Update right motor p and q effectiveness
309  g1g2[0][1] = roll_motor_p_eff_right; // roll effectiveness right motor (no airspeed compensation)
310  g1g2[1][1] = roll_motor_q_eff; // pitch effectiveness right motor
311 
312  // Update left motor p and q effectiveness
313  g1g2[0][3] = roll_motor_p_eff_left; // roll effectiveness left motor
314  g1g2[1][3] = -roll_motor_q_eff; // pitch effectiveness left motor
315 }
316 
318 {
320 
321  float dMyde = (eff_sched_p.k_elevator[0] * de * eff_sched_var.airspeed2 +
324 
325  float dMydpprz = dMyde * eff_sched_p.k_elevator_deflection[1];
326 
327  // Convert moment to effectiveness
328  float eff_y_elev = dMydpprz / eff_sched_var.Iyy;
329 
330  Bound(eff_y_elev, 0.00001, 0.1);
331 
332  g1g2[1][5] = eff_y_elev;
333 }
334 
336 {
340 
341  // Convert moment to effectiveness
342 
343  float dMzdpprz = dMzdr * eff_sched_p.d_rudder_d_pprz;
344 
345  // Convert moment to effectiveness
346  float eff_z_rudder = dMzdpprz / eff_sched_p.Izz;
347 
348  Bound(eff_z_rudder, 0.000001, 0.1);
349 
350  g1g2[2][4] = eff_z_rudder;
351 }
352 
354 {
355  float dMxdpprz = (eff_sched_p.k_aileron * eff_sched_var.airspeed2 * eff_sched_var.sinr3) / 1000000.;
356  float eff_x_aileron = dMxdpprz / eff_sched_var.Ixx;
357  Bound(eff_x_aileron, 0, 0.005)
358  g1g2[0][6] = eff_x_aileron;
359 }
360 
362 {
363  float dMxdpprz = (eff_sched_p.k_flaperon * eff_sched_var.airspeed2 * eff_sched_var.sinr3) / 1000000.;
364  float eff_x_flap_aileron = dMxdpprz / eff_sched_var.Ixx;
365  Bound(eff_x_flap_aileron, 0, 0.005)
366  g1g2[0][7] = eff_x_flap_aileron;
367 }
368 
370 {
372 
373  float dFxdrpmP = eff_sched_p.k_pusher[0]*rpmP + eff_sched_p.k_pusher[1] * eff_sched_var.airspeed;
375 
376  float eff_pusher = (dFxdrpmP * drpmPdpprz / eff_sched_p.m) / 10000.;
377 
378  Bound(eff_pusher, 0.00030, 0.0015);
379  g1g2[4][8] = eff_pusher;
380 }
381 
383 
385 {
387  float lift_d_fuselage = eff_sched_p.k_lift_fuselage * eff_sched_var.airspeed2 / eff_sched_p.m;
389 
390  float lift_d = lift_d_wing + lift_d_fuselage + lift_d_tail;
392  lift_d = 0.0;
393  }
394  Bound(lift_d, -130., 0.);
396 }
397 
398 // Override standard LIFT_D function
399 float guidance_indi_get_liftd(float pitch UNUSED, float theta UNUSED) {
401 }
402 
404 {
405  // Calculate the min and max increments
406  for (uint8_t i = 0; i < INDI_NUM_ACT; i++) {
409  u_pref_stab_indi[i] = act_pref[i];
410  if (i == 5) {
411  u_pref_stab_indi[i] = actuator_state_filt_vect[i]; // Set change in prefered state to 0 for elevator
412  u_min_stab_indi[i] = 0; // cmd 0 is lowest position for elevator
413  }
414  }
415 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
uint8_t last_wp UNUSED
if(GpsFixValid() &&e_identification_started)
void eff_scheduling_rot_wing_update_wing_angle(void)
void eff_scheduling_rot_wing_init(void)
void stabilization_indi_set_wls_settings(void)
Function that sets the du_min, du_max and du_pref if function not elsewhere defined.
void eff_scheduling_rot_wing_update_elevator_effectiveness(void)
void eff_scheduling_rot_wing_periodic(void)
struct rot_wing_eff_sched_param_t eff_sched_p
void eff_scheduling_rot_wing_schedule_liftd(void)
struct rot_wing_eff_sched_var_t eff_sched_var
void eff_scheduling_rot_wing_update_pusher_effectiveness(void)
float guidance_indi_get_liftd(float pitch UNUSED, float theta UNUSED)
#define WING_ROTATION_CAN_ROT_WING_ID
ABI binding wing position data.
void eff_scheduling_rot_wing_update_aileron_effectiveness(void)
static abi_event wing_position_ev
void eff_scheduling_rot_wing_update_hover_motor_effectiveness(void)
void eff_scheduling_rot_wing_update_cmd(void)
void eff_scheduling_rot_wing_update_rudder_effectiveness(void)
static void wing_position_cb(uint8_t sender_id UNUSED, struct act_feedback_t *pos_msg, uint8_t num_act)
void eff_scheduling_rot_wing_update_flaperon_effectiveness(void)
float eff_scheduling_rot_wing_lift_d
void eff_scheduling_rot_wing_update_MMOI(void)
void eff_scheduling_rot_wing_update_airspeed(void)
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition: state.h:1407
Hardware independent API for actuators (servos, motor controllers).
#define MAX_PPRZ
Definition: paparazzi.h:8
float act_pref[INDI_NUM_ACT]
float u_min_stab_indi[INDI_NUM_ACT]
bool act_is_servo[INDI_NUM_ACT]
float u_max_stab_indi[INDI_NUM_ACT]
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
float u_pref_stab_indi[INDI_NUM_ACT]
float actuator_state_filt_vect[INDI_NUM_ACT]
API to get/set the generic vehicle states.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98