dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
stabilization.c
Go to the documentation of this file.
1 
23 /*
24  * This program is free software; you can redistribute it and/or modify
25  * it under the terms of the GNU General Public License as published by
26  * the Free Software Foundation; either version 3 of the License, or
27  * (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful, but
30  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32  * for more details.
33  *
34  * You should have received a copy of the GNU General Public License along
35  * with this program; if not, see <http://www.gnu.org/licenses/>
36  *
37  * Additional note on redistribution: The copyright and license notices above
38  * must be maintained in each individual source file that is a derivative work
39  * of this source file; otherwise redistribution is prohibited.
40  */
41 
42 #include "openpilot.h"
43 #include "stabilization.h"
44 #include "pios_thread.h"
45 #include "pios_queue.h"
46 
47 #include "accels.h"
48 #include "actuatordesired.h"
49 #include "attitudeactual.h"
50 #include "cameradesired.h"
51 #include "flightstatus.h"
52 #include "gyros.h"
53 #include "ratedesired.h"
54 #include "systemident.h"
55 #include "stabilizationdesired.h"
56 #include "stabilizationsettings.h"
57 #include "subtrim.h"
58 #include "subtrimsettings.h"
59 #include "systemsettings.h"
60 #include "manualcontrolcommand.h"
61 #include "vbarsettings.h"
62 #include "lqgsettings.h"
63 #include "rtkfestimate.h"
64 #include "lqgsolution.h"
65 #include "systemalarms.h"
66 
67 #include "altitudeholdsettings.h"
68 #include "altitudeholdstate.h"
69 #include "positionactual.h"
70 #include "velocityactual.h"
71 
72 // Math libraries
73 #include "coordinate_conversions.h"
74 #include "physical_constants.h"
75 #include "pid.h"
76 #include "misc_math.h"
77 #include "smoothcontrol.h"
78 #include "lqg.h"
79 
80 // Sensors subsystem which runs in this task
81 #include "sensors.h"
82 
83 // Includes for various stabilization algorithms
84 #include "virtualflybar.h"
85 
86 // MAX_AXES expected to be present and equal to 3
87 DONT_BUILD_IF((MAX_AXES+0 != 3), stabAxisWrongCount);
88 
89 // Private constants
90 #define MAX_QUEUE_SIZE 1
91 
92 #if defined(PIOS_STABILIZATION_STACK_SIZE)
93 #define STACK_SIZE_BYTES PIOS_STABILIZATION_STACK_SIZE
94 #else
95 #define STACK_SIZE_BYTES 1200
96 #endif
97 
98 #define TASK_PRIORITY PIOS_THREAD_PRIO_HIGHEST
99 #define FAILSAFE_TIMEOUT_MS 30
100 #define COORDINATED_FLIGHT_MIN_ROLL_THRESHOLD 3.0f
101 #define COORDINATED_FLIGHT_MAX_YAW_THRESHOLD 0.05f
102 
104 // This value is also used for the expo plot in GCS (config/stabilization/advanced).
105 // Please adapt changes here also to the init of the plots in /ground/gcs/src/plugins/config/configstabilizationwidget.cpp
106 #define HORIZON_MODE_MAX_BLEND 0.85f
107 
109 #define THROTTLE_EPSILON 0.000001f
110 
111 enum {
112  PID_GROUP_RATE, // Rate controller settings
116  PID_GROUP_ATT, // Attitude controller settings
120  PID_GROUP_VBAR, // Virtual flybar settings
126 };
127 
128 // Check if the axis enumeration maps properly to the things above.
129 DONT_BUILD_IF((PID_RATE_ROLL+0 != ROLL)||(PID_ATT_ROLL != PID_GROUP_ATT+ROLL), stabAxisPidEnumMapping1);
130 DONT_BUILD_IF((PID_RATE_PITCH+0 != PITCH)||(PID_ATT_PITCH != PID_GROUP_ATT+PITCH), stabAxisPidEnumMapping2);
131 DONT_BUILD_IF((PID_RATE_YAW+0 != YAW)||(PID_ATT_YAW != PID_GROUP_ATT+YAW), stabAxisPidEnumMapping3);
132 
133 DONT_BUILD_IF(STABILIZATIONSETTINGS_MAXLEVELANGLE_ROLL != ROLL + 0,
134  LevelAngleConstantRoll);
135 DONT_BUILD_IF(STABILIZATIONSETTINGS_MAXLEVELANGLE_PITCH != PITCH + 0,
136  LevelAngleConstantPitch);
137 DONT_BUILD_IF(STABILIZATIONSETTINGS_MAXLEVELANGLE_YAW != YAW + 0,
138  LevelAngleConstantYaw);
139 
140 // Private variables
141 static struct pios_thread *taskHandle;
142 
143 #if defined(TARGET_MAY_HAVE_BARO)
144 static AltitudeHoldSettingsData altitudeHoldSettings;
145 #endif
146 
147 static StabilizationSettingsData settings;
148 static VbarSettingsData vbar_settings;
149 
150 static SubTrimData subTrim;
151 
153 
154 static float axis_lock_accum[MAX_AXES] = {0,0,0};
155 static uint8_t max_axis_lock = 0;
156 static uint8_t max_axislock_rate = 0;
157 static float weak_leveling_kp = 0;
158 static uint8_t weak_leveling_max = 0;
160 static float max_rate_alpha = 0.8f;
161 float vbar_decay = 0.991f;
162 
163 #if defined(TARGET_MAY_HAVE_BARO)
164 static struct pid vertspeed_pid;
165 
166 static uint8_t altitude_hold_expo;
167 static float altitude_hold_maxclimbrate;
168 static float altitude_hold_maxdescentrate;
169 #endif
170 
171 static struct pid pids[PID_MAX];
173 #if defined(STABILIZATION_LQG)
174 static lqg_t lqg[MAX_AXES];
175 #endif
176 
177 #ifndef NO_CONTROL_DEADBANDS
178 struct pid_deadband *deadbands = NULL;
179 #endif
180 
181 // Private functions
182 static void stabilizationTask(void* parameters);
183 static void zero_pids(void);
184 static void calculate_pids(float dT);
185 static void update_settings(float dT);
186 
187 #ifndef NO_CONTROL_DEADBANDS
188 #define get_deadband(axis) (deadbands ? (deadbands + axis) : NULL)
189 #else
190 #define get_deadband(axis) NULL
191 #endif
192 
193 static float get_throttle(ActuatorDesiredData *actuator_desired, SystemSettingsAirframeTypeOptions *airframe_type)
194 {
195  if (*airframe_type == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP) {
196  float heli_throttle;
197  ManualControlCommandThrottleGet( &heli_throttle );
198 
199  if (heli_throttle < 0) {
200  return 0;
201  }
202 
203  return heli_throttle;
204  }
205 
206  /* Look at actuator_desired so that it respects the value from
207  * low power stabilization (comes from StabilizationDesired)
208  */
209  return actuator_desired->Thrust;
210 }
211 
216 {
217  // Watchdog must be registered before starting task
219 
220  // Start main task
221  taskHandle = PIOS_Thread_Create(stabilizationTask, "Stabilization", STACK_SIZE_BYTES, NULL, TASK_PRIORITY);
222  TaskMonitorAdd(TASKINFO_RUNNING_STABILIZATION, taskHandle);
223 
224  return 0;
225 }
226 
231 {
232  // Initialize variables
233  if (StabilizationSettingsInitialize() == -1
234  || ActuatorDesiredInitialize() == -1
235  || SubTrimInitialize() == -1
236  || SubTrimSettingsInitialize() == -1
237  || ManualControlCommandInitialize() == -1
238  || VbarSettingsInitialize() == -1) {
239  return -1;
240  }
241 
242 #if defined(STABILIZATION_LQG)
243  if (LQGSettingsInitialize() == -1 ||
244  SystemIdentInitialize() == -1 ||
245  RTKFEstimateInitialize() == -1 ||
246  LQGSolutionInitialize() == -1) {
247  return -1;
248  }
249 #endif
250 
251 #if defined(RATEDESIRED_DIAGNOSTICS)
252  if (RateDesiredInitialize() == -1) {
253  return -1;
254  }
255 #endif
256 
257 #if defined(TARGET_MAY_HAVE_BARO)
258  if (AltitudeHoldStateInitialize() == -1
259  || AltitudeHoldSettingsInitialize() == -1) {
260  return -1;
261  }
262 #endif
263 
264  if (sensors_init() != 0) {
265  return -1;
266  }
267 
268  return 0;
269 }
270 
271 bool stabilization_failsafe_checks(StabilizationDesiredData *stab_desired,
272  ActuatorDesiredData *actuator_desired,
273  SystemSettingsAirframeTypeOptions airframe_type,
274  float *input, uint8_t *mode)
275 {
276  bool failsafed = false;
277  float *rate = &stab_desired->Roll;
278  for(int i = 0; i < MAX_AXES; i++)
279  {
280  mode[i] = stab_desired->StabilizationMode[i];
281  input[i] = rate[i];
282 
283  if (mode[i] == STABILIZATIONDESIRED_STABILIZATIONMODE_FAILSAFE) {
284  failsafed = true;
285  // Everything except planes should drop straight down
286  if ((airframe_type != SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING) &&
287  (airframe_type != SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON) &&
288  (airframe_type != SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL)) {
289  actuator_desired->Thrust = 0.0f;
290  switch (i) {
291  case 0: /* Roll */
292  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
293  input[i] = 0;
294  break;
295  case 1:
296  default:
297  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
298  input[i] = 0;
299  break;
300  case 2:
301  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_RATE;
302  input[i] = 0;
303  break;
304  }
305  }
306  else
307  {
308  actuator_desired->Thrust = 0.0f;
309 
310  switch (i) {
311  case 0: /* Roll */
312  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
313  input[i] = -10;
314  break;
315  case 1:
316  default:
317  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
318  input[i] = 0;
319  break;
320  case 2:
321  mode[i] = STABILIZATIONDESIRED_STABILIZATIONMODE_RATE;
322  input[i] = -5;
323  break;
324  }
325  }
326  }
327  }
328  return failsafed;
329 }
330 
331 static void calculate_attitude_errors(uint8_t *axis_mode, float *raw_input,
332  AttitudeActualData *attitudeActual,
333  float *local_attitude_error, float *horizon_rate_fraction)
334 {
335  float trimmed_setpoint[YAW+1];
336  float *cur_attitude = &attitudeActual->Roll;
337 
338  // Mux in level trim values, and saturate the trimmed attitude setpoint.
339  trimmed_setpoint[ROLL] = bound_min_max(
340  raw_input[ROLL] + subTrim.Roll,
341  -settings.MaxLevelAngle[ROLL] + subTrim.Roll,
342  settings.MaxLevelAngle[ROLL] + subTrim.Roll);
343  trimmed_setpoint[PITCH] = bound_min_max(
344  raw_input[PITCH] + subTrim.Pitch,
345  -settings.MaxLevelAngle[PITCH] + subTrim.Roll,
346  settings.MaxLevelAngle[PITCH] + subTrim.Roll);
347  trimmed_setpoint[YAW] = raw_input[YAW];
348 
349  // For horizon mode we need to compute the desire attitude from an unscaled value and apply the
350  // trim offset. Also track the stick with the most deflection to choose rate blending.
351  *horizon_rate_fraction = 0.0f;
352 
353  if (axis_mode[ROLL] == STABILIZATIONDESIRED_STABILIZATIONMODE_HORIZON) {
354  trimmed_setpoint[ROLL] = bound_min_max(
355  raw_input[ROLL] * settings.MaxLevelAngle[ROLL]
356  + subTrim.Roll,
357  -settings.MaxLevelAngle[ROLL] + subTrim.Roll,
358  settings.MaxLevelAngle[ROLL] + subTrim.Roll);
359  *horizon_rate_fraction = fabsf(raw_input[ROLL]);
360  }
361  if (axis_mode[PITCH] == STABILIZATIONDESIRED_STABILIZATIONMODE_HORIZON) {
362  trimmed_setpoint[PITCH] = bound_min_max(
363  raw_input[PITCH] * settings.MaxLevelAngle[PITCH]
364  + subTrim.Pitch,
365  -settings.MaxLevelAngle[PITCH] + subTrim.Roll,
366  settings.MaxLevelAngle[PITCH] + subTrim.Roll);
367  *horizon_rate_fraction =
368  MAX(*horizon_rate_fraction, fabsf(raw_input[PITCH]));
369  }
370  if (axis_mode[YAW] == STABILIZATIONDESIRED_STABILIZATIONMODE_HORIZON) {
371  trimmed_setpoint[YAW] =
372  raw_input[YAW] * settings.MaxLevelAngle[YAW];
373  *horizon_rate_fraction =
374  MAX(*horizon_rate_fraction, fabsf(raw_input[YAW]));
375  }
376 
377  // For weak leveling mode the attitude setpoint is the trim value (drifts back towards "0")
378  if (axis_mode[ROLL] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) {
379  trimmed_setpoint[ROLL] = subTrim.Roll;
380  }
381  if (axis_mode[PITCH] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) {
382  trimmed_setpoint[PITCH] = subTrim.Pitch;
383  }
384  if (axis_mode[YAW] == STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) {
385  trimmed_setpoint[YAW] = 0;
386  }
387 
388  for (int i = ROLL; i <= YAW; i++) {
389  switch (axis_mode[i]) {
390  case STABILIZATIONDESIRED_STABILIZATIONMODE_HORIZON:
391  case STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING:
392  case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
393  case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDELQG:
394  case STABILIZATIONDESIRED_STABILIZATIONMODE_SYSTEMIDENT:
395  break;
396  default:
397  /* If the axis isn't in an attitude mode,
398  * make sure there's no error on it.
399  */
400  trimmed_setpoint[i] = cur_attitude[i];
401  }
402  }
403 
404  /* We want the rotation that will rotate from our attitude to
405  * desired_quat. so that's attitude ^ -1 * desired_quat
406  */
407 
408  float desired_quat[4], atti_inverse[4], vehicle_reprojected[4];
409 
410  RPY2Quaternion(trimmed_setpoint, desired_quat);
411 
412  quat_copy(&attitudeActual->q1, atti_inverse);
413  quat_inverse(atti_inverse);
414 
415  quat_mult(atti_inverse, desired_quat, vehicle_reprojected);
416 
417  Quaternion2RPY(vehicle_reprojected, local_attitude_error);
418 
419  // Note we divide by the maximum limit here so the fraction ranges from 0 to 1 depending on
420  // how much is requested.
421  *horizon_rate_fraction = bound_sym(*horizon_rate_fraction, HORIZON_MODE_MAX_BLEND) / HORIZON_MODE_MAX_BLEND;
422 
423  // Wrap yaw error to [-180,180]
424  local_attitude_error[YAW] = circular_modulus_deg(local_attitude_error[YAW]);
425 }
426 
427 #if defined(STABILIZATION_LQG)
428 static void initialize_lqg_controllers(float dT)
429 {
430  if (SystemIdentHandle()) {
431  SystemIdentData sysIdent;
432  SystemIdentGet(&sysIdent);
433 
434  LQGSettingsData lqgSettings;
435  LQGSettingsGet(&lqgSettings);
436 
437  for (int i = 0; i < MAX_AXES; i++) {
438  if (lqg[i]) {
439  /* Update Q matrix. */
440  lqr_t lqr = lqg_get_lqr(lqg[i]);
441  lqr_update(lqr,
442  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWQ1 : LQGSETTINGS_LQREGULATOR_Q1],
443  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWQ2 : LQGSETTINGS_LQREGULATOR_Q2],
444  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWR : LQGSETTINGS_LQREGULATOR_R]
445  );
446  } else {
447  /* Initial setup. */
448  float beta = sysIdent.Beta[i];
449  float tau = (sysIdent.Tau[0] + sysIdent.Tau[1]) * 0.5f;
450 
451  if (tau > 0.001f && beta >= 6) {
452  rtkf_t rtkf = rtkf_create(beta, tau, dT,
453  lqgSettings.RTKF[i == YAW ? LQGSETTINGS_RTKF_YAWR : LQGSETTINGS_RTKF_R],
454  lqgSettings.RTKF[LQGSETTINGS_RTKF_Q1],
455  lqgSettings.RTKF[LQGSETTINGS_RTKF_Q2],
456  lqgSettings.RTKF[LQGSETTINGS_RTKF_Q3],
457  lqgSettings.RTKF[LQGSETTINGS_RTKF_BIASLIMIT]
458  );
459  lqr_t lqr = lqr_create(beta, tau, dT,
460  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWQ1 : LQGSETTINGS_LQREGULATOR_Q1],
461  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWQ2 : LQGSETTINGS_LQREGULATOR_Q2],
462  lqgSettings.LQRegulator[i == YAW ? LQGSETTINGS_LQREGULATOR_YAWR : LQGSETTINGS_LQREGULATOR_R]
463  );
464  lqg[i] = lqg_create(rtkf, lqr);
465  }
466  }
467  }
468  }
469 }
470 
471 static void dump_lqg_solution(lqg_t lqg, int axis)
472 {
473  if (lqg_solver_status(lqg) == LQG_SOLVER_DONE) {
474  LQGSolutionData lqgsol;
475  LQGSolutionGet(&lqgsol);
476 
477  lqr_t lqr = lqg_get_lqr(lqg);
478  float K[2];
479  lqr_get_gains(lqr, K);
480 
481  switch(axis) {
482  case ROLL:
483  lqgsol.RollK[0] = K[0];
484  lqgsol.RollK[1] = K[1];
485  break;
486  case PITCH:
487  lqgsol.PitchK[0] = K[0];
488  lqgsol.PitchK[1] = K[1];
489  break;
490  case YAW:
491  lqgsol.YawK[0] = K[0];
492  lqgsol.YawK[1] = K[1];
493  break;
494  }
495 
496  LQGSolutionSet(&lqgsol);
497  }
498 }
499 #endif
500 
502 
503 static float calculate_thrust(StabilizationDesiredThrustModeOptions mode,
504  FlightStatusData *flightStatus,
505  SystemSettingsAirframeTypeOptions airframe_type,
506  float desired_thrust)
507 {
508  uint32_t this_systime = PIOS_Thread_Systime();
509  static uint32_t last_nonzero_thrust_time = 0;
510  static bool last_thrust_pos = true;
511 
512  if (airframe_type == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP) {
513  /* Don't do anything-- neuter armed state checking
514  * and hangtime logic on helicp to allow collective
515  * to move freely. Safety properties come from
516  * throttle getting nailed to 0 in failsafe/disarm.
517  */
518  } else if (flightStatus->Armed != FLIGHTSTATUS_ARMED_ARMED) {
519  last_thrust_pos = true;
520  last_nonzero_thrust_time = 0;
521 
522  return 0.0f;
523  }
524 
525  float force_disable_hangtime = false;
526 
527 #ifdef TARGET_MAY_HAVE_BARO
528  bool do_alt_control = false;
529  bool do_vertspeed_control = false;
530 
531  static bool prev_vertspeed_control;
532 
533  static float prev_thrust;
534 
535  static float alt_desired;
536  float vertspeed_desired = 0;
537 
538  switch (mode) {
539  case STABILIZATIONDESIRED_THRUSTMODE_ALTITUDEWITHSTICKSCALING:
540  do_vertspeed_control = true;
541 
542  /* scale stick, decide control mode */
543  if (desired_thrust == 0) {
544  /* Use manualcontrol deadbands */
545  do_alt_control = true;
546  } else if (desired_thrust > 0) {
547  vertspeed_desired = -expo3(desired_thrust,
548  altitude_hold_expo) *
549  altitude_hold_maxclimbrate;
550  } else {
551  vertspeed_desired = -expo3(desired_thrust,
552  altitude_hold_expo) *
553  altitude_hold_maxdescentrate;
554  }
555 
556  break;
557 
558  case STABILIZATIONDESIRED_THRUSTMODE_ALTITUDE:
559  do_alt_control = true;
560  do_vertspeed_control = true;
561 
562  alt_desired = desired_thrust;
563 
564  break;
565 
566  case STABILIZATIONDESIRED_THRUSTMODE_VERTICALSPEED:
567  do_vertspeed_control = true;
568  vertspeed_desired = desired_thrust;
569  break;
570 
571  case STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODETHRUSTREVERSED:
572  desired_thrust = -desired_thrust;
573  /* Fall through to set flag. */
574 
575  case STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODE:
576  force_disable_hangtime = true;
577  break;
578 
579  default:
580  break;
581  }
582 
583  float position_z;
584  PositionActualDownGet(&position_z);
585 
586  if (do_alt_control) {
587  float altitude_error;
588 
589  altitude_error = alt_desired - position_z;
590 
591  vertspeed_desired = altitudeHoldSettings.PositionKp * altitude_error;
592  } else {
593  alt_desired = position_z;
594  }
595 
596  if (do_vertspeed_control) {
597  if (!prev_vertspeed_control) {
598  /* set integral on mode entry */
599  vertspeed_pid.iAccumulator =
600  bound_min_max(prev_thrust, 0, 1);
601  }
602 
603  float velocity_z;
604 
605  VelocityActualDownGet(&velocity_z);
606 
607  const float min_throttle = 0.00001f;
608 
609  /* TODO: This can wind up when one is in an unusual attitude.
610  */
611  float throttle_desired = pid_apply_antiwindup(&vertspeed_pid,
612  // negate because "down" vel vs "up" thrust
613  -(vertspeed_desired - velocity_z),
614  min_throttle, 1.0f, // don't use reverse thrust
615  0 // don't use slope-antiwindup
616  );
617 
618  AltitudeHoldStateData altitudeHoldState;
619  altitudeHoldState.VelocityDesired = vertspeed_desired;
620  altitudeHoldState.Integral = vertspeed_pid.iAccumulator;
621  altitudeHoldState.AngleGain = 1.0f;
622 
623  if (altitudeHoldSettings.AttitudeComp > 0) {
624  // Thrust desired is at this point the amount desired
625  // in the up direction, we can account for the
626  // attitude if desired
627  AttitudeActualData attitudeActual;
628  AttitudeActualGet(&attitudeActual);
629 
630  // Project a unit vector pointing up into the body
631  // frame and get the z component
632  float fraction = attitudeActual.q1 * attitudeActual.q1 -
633  attitudeActual.q2 * attitudeActual.q2 -
634  attitudeActual.q3 * attitudeActual.q3 +
635  attitudeActual.q4 * attitudeActual.q4;
636 
637  // Add ability to scale up the amount of
638  // compensation to achieve level forward flight
639  fraction = powf(fraction, (float)altitudeHoldSettings.AttitudeComp / 100.0f);
640 
641  // Dividing by the fraction remaining in the vertical
642  // projection will attempt to compensate for tilt.
643  // If the fraction is starting to go negative we are
644  // inverted and should shut off throttle (but keep
645  // stabilization).
646  if (fraction > 0.1f) {
647  throttle_desired = bound_min_max(
648  throttle_desired / fraction,
649  min_throttle, 1);
650  } else {
651  // XXX chop throttle if stick low
652  throttle_desired = min_throttle;
653  }
654 
655  altitudeHoldState.AngleGain = 1.0f / fraction;
656  }
657 
658  altitudeHoldState.Thrust = throttle_desired;
659  AltitudeHoldStateSet(&altitudeHoldState);
660 
661  desired_thrust = throttle_desired;
662  } else {
663  prev_thrust = desired_thrust;
664  }
665 
666  prev_vertspeed_control = do_vertspeed_control;
667 #else
668  switch (mode) {
669  case STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODETHRUSTREVERSED:
670  desired_thrust = -desired_thrust;
671  /* Fall through to set flag. */
672 
673  case STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODE:
674  force_disable_hangtime = true;
675  break;
676 
677  default:
678  break;
679  }
680 #endif
681 
682  if (fabsf(desired_thrust) > THROTTLE_EPSILON) {
683  if (settings.LowPowerStabilizationMaxTime) {
684  last_nonzero_thrust_time = this_systime;
685  last_thrust_pos = desired_thrust >= 0;
686  }
687  } else if (last_nonzero_thrust_time) {
688  if (((this_systime - last_nonzero_thrust_time) < 1000.0f * settings.LowPowerStabilizationMaxTime) &&
689  !force_disable_hangtime) {
690  /* Choose a barely-nonzero value to trigger
691  * low-power stabilization in actuator.
692  */
693  if (last_thrust_pos) {
694  return THROTTLE_EPSILON;
695  } else {
696  return -THROTTLE_EPSILON;
697  }
698  } else {
699  last_nonzero_thrust_time = 0;
700 
701  return 0.0f;
702  }
703  } else {
704  return 0.0f;
705  }
706 
707  return desired_thrust;
708 
709 }
710 
714 static void stabilizationTask(void* parameters)
715 {
716  uint32_t timeval = PIOS_DELAY_GetRaw();
717 
718  ActuatorDesiredData actuatorDesired;
719  StabilizationDesiredData stabDesired;
720  RateDesiredData rateDesired;
721  AttitudeActualData attitudeActual;
722  GyrosData gyrosData;
723  FlightStatusData flightStatus;
724  SystemSettingsAirframeTypeOptions airframe_type;
725 
726  volatile bool settings_updated = true;
727  volatile bool flightstatus_updated = true;
728  volatile bool lqgsettings_updated = true;
729 
730  float *actuatorDesiredAxis = &actuatorDesired.Roll;
731  float *rateDesiredAxis = &rateDesired.Roll;
732  smoothcontrol_initialize(&rc_smoothing);
733 
734  // Connect callbacks
735  FlightStatusConnectCallbackCtx(UAVObjCbSetFlag, &flightstatus_updated);
736  SystemSettingsConnectCallbackCtx(UAVObjCbSetFlag, &settings_updated);
737  StabilizationSettingsConnectCallbackCtx(UAVObjCbSetFlag, &settings_updated);
738  VbarSettingsConnectCallbackCtx(UAVObjCbSetFlag, &settings_updated);
739  SubTrimSettingsConnectCallbackCtx(UAVObjCbSetFlag, &settings_updated);
740 #ifdef TARGET_MAY_HAVE_BARO
741  AltitudeHoldSettingsConnectCallbackCtx(UAVObjCbSetFlag, &settings_updated);
742 #else
743  /*
744  * Sanity check uses this to know whether althold mode is permitted,
745  * so we'd better not have a baro if the target doesn't "support"
746  * one.
747  */
749 #endif
750  LQGSettingsConnectCallbackCtx(UAVObjCbSetFlag, &lqgsettings_updated);
751 
752  smoothcontrol_initialize(&rc_smoothing);
753  ManualControlCommandConnectCallbackCtx(UAVObjCbSetFlag, smoothcontrol_get_ringer(rc_smoothing));
754 
755  uint32_t iteration = 0;
756  float dT_measured = 0;
757 
758  uint8_t ident_shift = 5;
759 
760  float dT_expected = 0.001; // assume 1KHz if we don't know.
761 
762  uint16_t samp_rate = PIOS_SENSORS_GetSampleRate(PIOS_SENSOR_GYRO);
763 
764  if (samp_rate) {
765  dT_expected = 1.0f / samp_rate;
766  }
767 
768  smoothcontrol_update_dT(rc_smoothing, dT_expected);
769 
770  if (dT_expected < 0.0004f) {
771  // For future 3.2KHz-- 640ms period
772  ident_shift = 8;
773  } else if (dT_expected < 0.0008f) {
774  // 2KHz - 512ms period
775  // 1.6KHz - 640ms period
776  ident_shift = 7;
777  } else if (dT_expected < 0.0014f) {
778  // 1.2KHz - 427ms
779  // 1KHz - 512ms period
780  // 800Hz - 640ms period
781  // 750Hz - 683ms period
782  ident_shift = 6;
783  } else {
784  // 700Hz - 365ms period
785  // 500Hz - 512ms period
786  // 333Hz - 768ms period
787  ident_shift = 5;
788  }
789 
790  ident_wiggle_points = (1 << (ident_shift + 3));
791  uint32_t ident_mask = ident_wiggle_points - 1;
792 
793  zero_pids();
794 
795  // Main task loop
796  while(1) {
797  iteration++;
798 
800 
801  if (settings_updated) {
802  update_settings(dT_expected);
803 
804  SystemSettingsAirframeTypeGet(&airframe_type);
805 
806  // Default 350ms.
807  // 175ms to 39.3% of response
808  // 350ms to 63.2% of response
809  // 700ms to 86.4% of response
810  max_rate_alpha = expf(-dT_expected / settings.AcroDynamicTau);
811 
812  // Compute time constant for vbar decay term
813  if (vbar_settings.VbarTau < 0.001f) {
814  vbar_decay = 0;
815  } else {
816  vbar_decay = expf(-dT_expected / vbar_settings.VbarTau);
817  }
818 
819  settings_updated = false;
820  }
821 
822  // Wait until the AttitudeRaw object is updated, if a timeout
823  // then alarm. We don't update, and Actuator will notice and
824  // actuator-failsafe.
825  if (sensors_step() != true)
826  {
827  AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION,
828  SYSTEMALARMS_ALARM_CRITICAL);
829  continue;
830  }
831 
832  static bool frequency_wrong = false;
833 
834  float dT = PIOS_DELAY_DiffuS(timeval) * 1.0e-6f;
835  timeval = PIOS_DELAY_GetRaw();
836 
837  if (iteration < 100) {
838  dT_measured = 0;
839  } else if (iteration < 2100) {
840  dT_measured += dT;
841  } else if (iteration == 2100) {
842  dT_measured /= 2000;
843 
844  /* Other modules-- attitude, etc, -- rely on us having
845  * done this test and set an alarm here. Do not remove
846  * without verifying those places
847  */
848  if ((dT_measured > dT_expected * 1.15f) ||
849  (dT_measured < dT_expected * 0.85f)) {
850  frequency_wrong = true;
851 #ifdef FLIGHT_POSIX
853  printf("Stabilization: frequency wrong. dT_measured=%f, expected=%f\n",
854  dT_measured, dT_expected);
855  } else {
856  frequency_wrong = false;
857  }
858 #endif
859  }
860  }
861 
862  bool error = frequency_wrong;
863 
864  if (flightstatus_updated) {
865  FlightStatusGet(&flightStatus);
866  flightstatus_updated = false;
867  }
868 
869  if (lqgsettings_updated) {
870 #if defined(STABILIZATION_LQG)
871  /* Set up LQG controllers. */
872  initialize_lqg_controllers(dT_expected);
873 #endif
874  lqgsettings_updated = false;
875  }
876 
877  StabilizationDesiredGet(&stabDesired);
878  AttitudeActualGet(&attitudeActual);
879  GyrosGet(&gyrosData);
880 
881  // Handle altitude control loop if applicable and
882  // hangtime / arming checks.
883  actuatorDesired.Thrust = calculate_thrust(
884  stabDesired.ThrustMode, &flightStatus,
885  airframe_type, stabDesired.Thrust);
886 
887  actuatorDesired.FlipOverThrustMode =
888  (stabDesired.ThrustMode == STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODE) ||
889  (stabDesired.ThrustMode == STABILIZATIONDESIRED_THRUSTMODE_FLIPOVERMODETHRUSTREVERSED);
890 
891  // Re-project axes if necessary prior to running stabilization algorithms.
892  uint8_t reprojection = stabDesired.ReprojectionMode;
893  static uint8_t previous_reprojection = 255;
894 
895  if (reprojection == STABILIZATIONDESIRED_REPROJECTIONMODE_CAMERAANGLE) {
896  float camera_tilt_angle = settings.CameraTilt;
897  if (camera_tilt_angle) {
898  float roll = stabDesired.Roll;
899  float yaw = stabDesired.Yaw;
900  // The roll input should be the cosine of the camera angle multiplied by the roll,
901  // added to the sine of camera angle multiplied by yaw.
902  stabDesired.Roll = (cosf(DEG2RAD * camera_tilt_angle) * roll +
903  (sinf(DEG2RAD * camera_tilt_angle) * yaw));
904  // Yaw is similar but uses the negative sine of the camera angle, multiplied by roll,
905  // added to the cosine of the camera angle, times the yaw
906  stabDesired.Yaw = (-1 * sinf(DEG2RAD * camera_tilt_angle) * roll) +
907  (cosf(DEG2RAD * camera_tilt_angle) * yaw);
908  }
909  } else if (reprojection == STABILIZATIONDESIRED_REPROJECTIONMODE_HEADFREE) {
910  static float reference_yaw;
911 
912  if (previous_reprojection != reprojection) {
913  reference_yaw = attitudeActual.Yaw;
914  }
915 
916  float rotation_angle = attitudeActual.Yaw - reference_yaw;
917  float roll = stabDesired.Roll;
918  float pitch = stabDesired.Pitch;
919 
920  stabDesired.Roll = cosf(DEG2RAD * rotation_angle) * roll
921  + sinf(DEG2RAD * rotation_angle) * pitch;
922  stabDesired.Pitch = cosf(DEG2RAD * rotation_angle) * pitch
923  + sinf(DEG2RAD * rotation_angle) * -roll;
924  }
925 
926  previous_reprojection = reprojection;
927 
928 #if defined(RATEDESIRED_DIAGNOSTICS)
929  RateDesiredGet(&rateDesired);
930 #endif
931  // raw_input will contain desired stabilization or the failsafe overrides.
932  float raw_input[MAX_AXES];
933  uint8_t axis_mode[MAX_AXES];
934 
935  bool failsafed = stabilization_failsafe_checks(&stabDesired, &actuatorDesired, airframe_type,
936  raw_input, axis_mode);
937 
938  // A flag to track which stabilization mode each axis is in
939  static uint8_t previous_mode[MAX_AXES] = {255,255,255};
940 
941  // Do this before attitude error calc, so it benefits from it.
942  for(int i = 0; i < 3; i++) {
943  if (axis_mode[i] != previous_mode[i] || failsafed) {
944  // Reset integrator and don't smooth for this cycle after a mode switch.
945  // Otherwise we might interpolate between different stick scales.
946  // Also, kill it during failsafe.
947  smoothcontrol_reinit(rc_smoothing, i, raw_input[i]);
948  } else {
949  smoothcontrol_run(rc_smoothing, i, &raw_input[i]);
950  }
951  }
952 
953  float horizon_rate_fraction;
954  float local_attitude_error[MAX_AXES];
955  calculate_attitude_errors(axis_mode, raw_input,
956  &attitudeActual,
957  local_attitude_error, &horizon_rate_fraction);
958 
959  float *gyro_filtered = &gyrosData.x;
960 
961  /* Maintain a second-order, lower cutof freq variant for
962  * dynamic flight modes.
963  */
964 
965  static float max_rate_filtered[MAX_AXES];
966 
967  actuatorDesired.SystemIdentCycle = 0xffff;
968 
969  uint16_t max_safe_rate = PIOS_SENSORS_GetMaxGyro() * 0.9f;
970 
971 #if defined(STABILIZATION_LQG)
972  bool lqg_in_use = false;
973 
974  for (int i = 0; i < MAX_AXES; i++) {
975  /* Solve for LQG, if it's configured for an axis. */
976  if (lqg[i]) {
977  int status = lqg_solver_status(lqg[i]);
978  SystemAlarmsConfigErrorOptions err;
979  SystemAlarmsConfigErrorGet(&err);
980  switch(status) {
981  case LQG_SOLVER_RUNNING:
982  lqg_run_covariance(lqg[i], 1);
983  dump_lqg_solution(lqg[i], i);
984  /* Drop to failed, because we want to set the LQG config error during that time, anyway,
985  to prevent arming. */
986  case LQG_SOLVER_FAILED:
987  /* Values don't converge in time, probably bogus. Light up the Christmas three. */
988  if (err != SYSTEMALARMS_CONFIGERROR_LQG) {
989  err = SYSTEMALARMS_CONFIGERROR_LQG;
990  SystemAlarmsConfigErrorSet(&err);
991  AlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, SYSTEMALARMS_ALARM_ERROR);
992  }
993  break;
994  case LQG_SOLVER_DONE:
995  /* Clear the error, everything's ready to go. */
996  if (err == SYSTEMALARMS_CONFIGERROR_LQG) {
997  err = SYSTEMALARMS_CONFIGERROR_NONE;
998  SystemAlarmsConfigErrorSet(&err);
999  AlarmsClear(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION);
1000  }
1001  break;
1002  default:
1003  PIOS_Assert(0);
1004  }
1005  }
1006  }
1007 #endif
1008 
1009  //Run the selected stabilization algorithm on each axis:
1010  for (uint8_t i = 0; i < MAX_AXES; i++) {
1011  // Check whether this axis mode needs to be reinitialized
1012  bool reinit = (axis_mode[i] != previous_mode[i]);
1013 
1014  previous_mode[i] = axis_mode[i];
1015 
1016  // Apply the selected control law
1017  switch(axis_mode[i]) {
1018  case STABILIZATIONDESIRED_STABILIZATIONMODE_FAILSAFE:
1019  PIOS_Assert(0); /* Shouldn't happen, per above */
1020  break;
1021 
1022  case STABILIZATIONDESIRED_STABILIZATIONMODE_LQG:
1023 #if defined(STABILIZATION_LQG)
1024  if (lqg[i] && (lqg_solver_status(lqg[i]) == LQG_SOLVER_DONE)) {
1025  if (reinit) {
1026  lqg_set_x0(lqg[i], gyro_filtered[i]);
1027  }
1028  lqg_in_use = true;
1029 
1030  /* Store to rate desired variable for storing to UAVO */
1031  rateDesiredAxis[i] = bound_sym(raw_input[i], settings.ManualRate[i]);
1032 
1033  /* Compute the inner loop */
1034  actuatorDesiredAxis[i] = lqg_controller(lqg[i], gyro_filtered[i], rateDesiredAxis[i]);
1035  /* The LQG controller bounds data already, but whatever. */
1036  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i], 1.0f);
1037  break;
1038  }
1039 #endif
1040  /* Fall through to rate, if LQR gains haven't been solved yet, or if
1041  LQG wasn't initialized. */
1042 
1043  case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
1044  if(reinit) {
1046  }
1047 
1048  // Store to rate desired variable for storing to UAVO
1049  rateDesiredAxis[i] = bound_sym(raw_input[i], settings.ManualRate[i]);
1050 
1051  // Compute the inner loop
1052  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1053 
1054  break;
1055 
1056  case STABILIZATIONDESIRED_STABILIZATIONMODE_ACRODYNE:
1057  if(reinit) {
1059  max_rate_filtered[i] = settings.ManualRate[i];
1060  }
1061 
1062  raw_input[i] = bound_sym(raw_input[i], 1.0f);
1063 
1064  float curve_cmd = expoM(raw_input[i],
1065  settings.RateExpo[i],
1066  settings.RateExponent[i]*0.1f);
1067 
1068  const float break_point = settings.AcroDynamicTransition[i]/100.0f;
1069 
1070  uint16_t calc_max_rate = settings.ManualRate[i];
1071 
1072  float abs_cmd = fabsf(raw_input[i]);
1073 
1074  uint16_t acro_dynrate = settings.AcroDynamicRate[i];
1075 
1076  if (!acro_dynrate) {
1077  acro_dynrate = settings.ManualRate[i] + settings.ManualRate[i] / 2;
1078  }
1079 
1080  if (acro_dynrate > max_safe_rate) {
1081  acro_dynrate = max_safe_rate;
1082  }
1083 
1084  // Could precompute much of this...
1085  if (abs_cmd > break_point) {
1086  calc_max_rate = (settings.ManualRate[i] * (abs_cmd - 1.0f) * (2 * break_point - abs_cmd - 1.0f) + acro_dynrate * powf(break_point - abs_cmd, 2.0f)) / powf(break_point - 1.0f, 2.0f);
1087  }
1088 
1089  calc_max_rate = MIN(calc_max_rate,
1090  acro_dynrate);
1091 
1092  max_rate_filtered[i] = max_rate_filtered[i] * max_rate_alpha + calc_max_rate * (1 - max_rate_alpha);
1093 
1094  // Store to rate desired variable for storing to UAVO
1095  rateDesiredAxis[i] = bound_sym(curve_cmd * max_rate_filtered[i], max_rate_filtered[i]);
1096 
1097  // Compute the inner loop
1098  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1099 
1100  break;
1101 
1102  case STABILIZATIONDESIRED_STABILIZATIONMODE_ACROPLUS:
1103  // this implementation is based on the Openpilot/Librepilot Acro+ flightmode
1104  // and our previous MWRate flightmodes
1105  if(reinit) {
1107  }
1108 
1109  raw_input[i] = bound_sym(raw_input[i], 1.0f);
1110 
1111  // The factor for gyro suppression / mixing raw stick input into the output; scaled by raw stick input
1112  float factor = fabsf(raw_input[i]) * settings.AcroInsanityFactor / 100.0f;
1113 
1114  // Store to rate desired variable for storing to UAVO
1115  rateDesiredAxis[i] = bound_sym(raw_input[i] * settings.ManualRate[i], settings.ManualRate[i]);
1116 
1117  // Zero integral for aggressive maneuvers
1118  if ((i < 2 && fabsf(gyro_filtered[i]) > settings.AcroZeroIntegralGyro) ||
1119  (i == 0 && fabsf(raw_input[i]) > settings.AcroZeroIntegralStick / 100.0f)) {
1121  }
1122 
1123  // Compute the inner loop
1124  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1125  actuatorDesiredAxis[i] = factor * raw_input[i] + (1.0f - factor) * actuatorDesiredAxis[i];
1126  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i], 1.0f);
1127 
1128  break;
1129 
1130  case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDELQG:
1131 #if defined(STABILIZATION_LQG)
1132  if (lqg[i] && (lqg_solver_status(lqg[i]) == LQG_SOLVER_DONE)) {
1133  if (reinit) {
1135  lqg_set_x0(lqg[i], gyro_filtered[i]);
1136  }
1137  lqg_in_use = true;
1138 
1139  /* Store to rate desired variable for storing to UAVO */
1140  // Compute the outer loop
1141  rateDesiredAxis[i] = pid_apply(&pids[PID_GROUP_ATT + i], local_attitude_error[i]);
1142  rateDesiredAxis[i] = bound_sym(rateDesiredAxis[i], settings.MaximumRate[i]);
1143 
1144  /* Compute the inner loop */
1145  actuatorDesiredAxis[i] = lqg_controller(lqg[i], gyro_filtered[i], rateDesiredAxis[i]);
1146  /* The LQG controller bounds data already, but whatever. */
1147  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i], 1.0f);
1148  break;
1149  }
1150 #endif
1151  /* Fall through to attitude, if LQR gains haven't been solved yet, or if
1152  LQG wasn't initialized. */
1153 
1154 
1155  case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
1156  if(reinit) {
1159  }
1160 
1161  // Compute the outer loop
1162  rateDesiredAxis[i] = pid_apply(&pids[PID_GROUP_ATT + i], local_attitude_error[i]);
1163  rateDesiredAxis[i] = bound_sym(rateDesiredAxis[i], settings.MaximumRate[i]);
1164 
1165  // Compute the inner loop
1166  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1167  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i],1.0f);
1168 
1169  break;
1170 
1171  case STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR:
1172  // Store for debugging output
1173  rateDesiredAxis[i] = bound_sym(raw_input[i], 1.0f);
1174 
1175  // Run a virtual flybar stabilization algorithm on this axis
1176  stabilization_virtual_flybar(gyro_filtered[i], rateDesiredAxis[i], &actuatorDesiredAxis[i], dT_expected, reinit, i, &pids[PID_GROUP_VBAR + i], &vbar_settings);
1177 
1178  break;
1179 
1180  case STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING:
1181  {
1182  if (reinit) {
1184  }
1185 
1186  float weak_leveling = local_attitude_error[i] * weak_leveling_kp;
1187  weak_leveling = bound_sym(weak_leveling, weak_leveling_max);
1188 
1189  // Compute desired rate as input biased towards leveling
1190  rateDesiredAxis[i] = bound_sym(raw_input[i] + weak_leveling, settings.ManualRate[i]);
1191  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1192 
1193  break;
1194  }
1195  case STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK:
1196  if (reinit) {
1198  }
1199 
1200  if (fabsf(raw_input[i]) > max_axislock_rate) {
1201  // While getting strong commands act like rate mode
1202  rateDesiredAxis[i] = bound_sym(raw_input[i], settings.ManualRate[i]);
1203 
1204  // Reset accumulator
1205  axis_lock_accum[i] = 0;
1206  } else {
1207  // For weaker commands or no command simply lock (almost) on no gyro change
1208  axis_lock_accum[i] += (raw_input[i] - gyro_filtered[i]) * dT_expected;
1209  axis_lock_accum[i] = bound_sym(axis_lock_accum[i], max_axis_lock);
1210 
1211  // Compute the inner loop
1212  float tmpRateDesired = pid_apply(&pids[PID_GROUP_ATT + i], axis_lock_accum[i]);
1213  rateDesiredAxis[i] = bound_sym(tmpRateDesired, settings.MaximumRate[i]);
1214  }
1215 
1216  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1217 
1218  break;
1219 
1220  case STABILIZATIONDESIRED_STABILIZATIONMODE_HORIZON:
1221  if(reinit) {
1223  }
1224 
1225  // Do not allow outer loop integral to wind up in this mode since the controller
1226  // is often disengaged.
1228 
1229  // Compute the outer loop for the attitude control
1230  float rateDesiredAttitude = pid_apply(&pids[PID_GROUP_ATT + i], local_attitude_error[i]);
1231  // Compute the desire rate for a rate control
1232  float rateDesiredRate = bound_sym(raw_input[i], 1.0f) * settings.ManualRate[i];
1233 
1234  // Blend from one rate to another. The maximum of all stick positions is used for the
1235  // amount so that when one axis goes completely to rate the other one does too. This
1236  // prevents doing flips while one axis tries to stay in attitude mode.
1237  // XXX the bounding here is not right!
1238  rateDesiredAxis[i] = rateDesiredAttitude * (1.0f - horizon_rate_fraction) + rateDesiredRate * horizon_rate_fraction;
1239  rateDesiredAxis[i] = bound_sym(rateDesiredAxis[i], settings.ManualRate[i]);
1240 
1241  // Compute the inner loop
1242  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1243  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i],1.0f);
1244 
1245  break;
1246  case STABILIZATIONDESIRED_STABILIZATIONMODE_SYSTEMIDENT:
1247  case STABILIZATIONDESIRED_STABILIZATIONMODE_SYSTEMIDENTRATE:
1248  ;
1249  static bool measuring;
1250  static uint32_t enter_time;
1251 
1252  static uint32_t measure_remaining;
1253 
1254  // Takes 1250ms + the time to reach
1255  // the '0th measurement'
1256  // (could be the ~600ms period time)
1257  const uint32_t PREPARE_TIME = 1250000;
1258 
1259  if (reinit) {
1262 
1263  if (i == 0) {
1264  enter_time = timeval;
1265 
1266  measuring = false;
1267  }
1268  }
1269 
1270  if ((i == 0) &&
1271  (!measuring) &&
1272  ((timeval - enter_time) > PREPARE_TIME)) {
1273  if (!(iteration & ident_mask)) {
1274  measuring = true;
1275  measure_remaining = 60 / dT_expected;
1276  // Round down to an integer
1277  // number of ident cycles.
1278  measure_remaining &= ~ident_mask;
1279  }
1280  }
1281 
1282  if (flightStatus.Armed != FLIGHTSTATUS_ARMED_ARMED) {
1283  measuring = false;
1284  }
1285 
1286  if (axis_mode[i] == STABILIZATIONDESIRED_STABILIZATIONMODE_SYSTEMIDENT) {
1287  // Compute the outer loop
1288  rateDesiredAxis[i] = pid_apply(&pids[PID_GROUP_ATT + i], local_attitude_error[i]);
1289  rateDesiredAxis[i] = bound_sym(rateDesiredAxis[i], settings.MaximumRate[i]);
1290 
1291  // Compute the inner loop
1292  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1293  } else {
1294  // Get the desired rate. yaw is always in rate mode in system ident.
1295  rateDesiredAxis[i] = bound_sym(raw_input[i], settings.ManualRate[i]);
1296 
1297  // Compute the inner loop only for yaw
1298  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1299  }
1300 
1301  const float scale = settings.AutotuneActuationEffort[i];
1302 
1303  uint32_t ident_iteration =
1304  iteration >> ident_shift;
1305 
1306  if (measuring && measure_remaining) {
1307  if (i == 2) {
1308  // Only adjust the
1309  // counter on one axis
1310  measure_remaining--;
1311  }
1312 
1313  actuatorDesired.SystemIdentCycle = (iteration & ident_mask);
1314 
1315  switch (ident_iteration & 0x07) {
1316  case 0:
1317  if (i == 2) {
1318  actuatorDesiredAxis[i] += scale;
1319  }
1320  break;
1321  case 1:
1322  if (i == 0) {
1323  actuatorDesiredAxis[i] += scale;
1324  }
1325  break;
1326  case 2:
1327  if (i == 2) {
1328  actuatorDesiredAxis[i] -= scale;
1329  }
1330  break;
1331  case 3:
1332  if (i == 0) {
1333  actuatorDesiredAxis[i] -= scale;
1334  }
1335  break;
1336  case 4:
1337  if (i == 2) {
1338  actuatorDesiredAxis[i] += scale;
1339  }
1340  break;
1341  case 5:
1342  if (i == 1) {
1343  actuatorDesiredAxis[i] += scale;
1344  }
1345  break;
1346  case 6:
1347  if (i == 2) {
1348  actuatorDesiredAxis[i] -= scale;
1349  }
1350  break;
1351  case 7:
1352  if (i == 1) {
1353  actuatorDesiredAxis[i] -= scale;
1354  }
1355  break;
1356  }
1357 
1358  actuatorDesiredAxis[i] = bound_sym(actuatorDesiredAxis[i],1.0f);
1359  }
1360 
1361  break;
1362 
1363  case STABILIZATIONDESIRED_STABILIZATIONMODE_COORDINATEDFLIGHT:
1364  switch (i) {
1365  case YAW:
1366  if (reinit) {
1369  axis_lock_accum[YAW] = 0;
1370  }
1371 
1372  //If we are not in roll attitude mode, trigger an error
1373  if (axis_mode[ROLL] != STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE)
1374  {
1375  error = true;
1376  break ;
1377  }
1378 
1379  if (fabsf(stabDesired.Yaw) < COORDINATED_FLIGHT_MAX_YAW_THRESHOLD) { //If yaw is within the deadband...
1380  if (fabsf(stabDesired.Roll) > COORDINATED_FLIGHT_MIN_ROLL_THRESHOLD) { // We're requesting more roll than the threshold
1381  float accelsDataY;
1382  AccelsyGet(&accelsDataY);
1383 
1384  //Reset integral if we have changed roll to opposite direction from rudder. This implies that we have changed desired turning direction.
1385  if ((stabDesired.Roll > 0 && actuatorDesiredAxis[YAW] < 0) ||
1386  (stabDesired.Roll < 0 && actuatorDesiredAxis[YAW] > 0)){
1388  }
1389 
1390  // Coordinate flight can simply be seen as ensuring that there is no lateral acceleration in the
1391  // body frame. As such, we use the (noisy) accelerometer data as our measurement. Ideally, at
1392  // some point in the future we will estimate acceleration and then we can use the estimated value
1393  // instead of the measured value.
1394  float errorSlip = -accelsDataY;
1395 
1396  float command = pid_apply(&pids[PID_COORDINATED_FLIGHT_YAW], errorSlip);
1397  actuatorDesiredAxis[YAW] = bound_sym(command ,1.0);
1398 
1399  // Reset axis-lock integrals
1401  axis_lock_accum[YAW] = 0;
1402  } else if (fabsf(stabDesired.Roll) <= COORDINATED_FLIGHT_MIN_ROLL_THRESHOLD) { // We're requesting less roll than the threshold
1403  // Axis lock on no gyro change
1404  axis_lock_accum[YAW] += (0 - gyro_filtered[YAW]) * dT_expected;
1405 
1406  rateDesiredAxis[YAW] = pid_apply(&pids[PID_ATT_YAW], axis_lock_accum[YAW]);
1407  rateDesiredAxis[YAW] = bound_sym(rateDesiredAxis[YAW], settings.MaximumRate[YAW]);
1408 
1409  actuatorDesiredAxis[YAW] = pid_apply_setpoint(&pids[PID_RATE_YAW], NULL, rateDesiredAxis[YAW], gyro_filtered[YAW]);
1410  actuatorDesiredAxis[YAW] = bound_sym(actuatorDesiredAxis[YAW],1.0f);
1411 
1412  // Reset coordinated-flight integral
1414  }
1415  } else { //... yaw is outside the deadband. Pass the manual input directly to the actuator.
1416  actuatorDesiredAxis[YAW] = bound_sym(raw_input[YAW], 1.0);
1417 
1418  // Reset all integrals
1421  axis_lock_accum[YAW] = 0;
1422  }
1423  break;
1424  case ROLL:
1425  case PITCH:
1426  default:
1427  //Coordinated Flight has no effect in these modes. Trigger a configuration error.
1428  error = true;
1429  break;
1430  }
1431 
1432  break;
1433 
1434  case STABILIZATIONDESIRED_STABILIZATIONMODE_POI:
1435  // The sanity check enforces this is only selectable for Yaw
1436  // for a gimbal you can select pitch too.
1437  if(reinit) {
1440  }
1441 
1442  float angle_error = 0;
1443  float angle;
1444  if (CameraDesiredHandle()) {
1445  switch(i) {
1446  case PITCH:
1447  CameraDesiredDeclinationGet(&angle);
1448  angle_error = circular_modulus_deg(angle - attitudeActual.Pitch);
1449  break;
1450  case ROLL:
1451  {
1452  uint8_t roll_fraction = 0;
1453 
1454  // For ROLL POI mode we track the FC roll angle (scaled) to
1455  // allow keeping some motion
1456  CameraDesiredRollGet(&angle);
1457  angle *= roll_fraction / 100.0f;
1458  angle_error = circular_modulus_deg(angle - attitudeActual.Roll);
1459  }
1460  break;
1461  case YAW:
1462  CameraDesiredBearingGet(&angle);
1463  angle_error = circular_modulus_deg(angle - attitudeActual.Yaw);
1464  break;
1465  }
1466  } else
1467  error = true;
1468 
1469  // Compute the outer loop
1470  rateDesiredAxis[i] = pid_apply(&pids[PID_GROUP_ATT + i], angle_error);
1471  rateDesiredAxis[i] = bound_sym(rateDesiredAxis[i], settings.PoiMaximumRate[i]);
1472 
1473  // Compute the inner loop
1474  actuatorDesiredAxis[i] = pid_apply_setpoint_antiwindup(&pids[PID_GROUP_RATE + i], get_deadband(i), rateDesiredAxis[i], gyro_filtered[i], -1.0f, 1.0f, 1.0f);
1475 
1476  break;
1477  case STABILIZATIONDESIRED_STABILIZATIONMODE_DISABLED:
1478  actuatorDesiredAxis[i] = 0.0;
1479  break;
1480  case STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL:
1481  actuatorDesiredAxis[i] = bound_sym(raw_input[i],1.0f);
1482  break;
1483  default:
1484  error = true;
1485  break;
1486  }
1487  }
1488 
1489 #if defined(STABILIZATION_LQG)
1490  /* If there's a LQG controller running, dump the RTKF state for logging. */
1491  if (lqg_in_use && (lqg[0] || lqg[1] || lqg[2])) {
1492  RTKFEstimateData est = { 0 };
1493  if (lqg[0]) {
1494  lqg_get_rtkf_state(lqg[0],
1495  &est.Rate[RTKFESTIMATE_RATE_ROLL], &est.Torque[RTKFESTIMATE_TORQUE_ROLL], &est.Bias[RTKFESTIMATE_BIAS_ROLL]);
1496  }
1497  if (lqg[1]) {
1498  lqg_get_rtkf_state(lqg[1],
1499  &est.Rate[RTKFESTIMATE_RATE_PITCH], &est.Torque[RTKFESTIMATE_TORQUE_PITCH], &est.Bias[RTKFESTIMATE_BIAS_PITCH]);
1500  }
1501  if (lqg[2]) {
1502  lqg_get_rtkf_state(lqg[2],
1503  &est.Rate[RTKFESTIMATE_RATE_YAW], &est.Torque[RTKFESTIMATE_TORQUE_YAW], &est.Bias[RTKFESTIMATE_BIAS_YAW]);
1504  }
1505  RTKFEstimateSet(&est);
1506  }
1507 #endif
1508 
1509  // Run the smoothing over the throttle stick.
1510  if (actuatorDesired.Thrust > THROTTLE_EPSILON || actuatorDesired.Thrust < -THROTTLE_EPSILON){
1511  smoothcontrol_run_thrust(rc_smoothing, &actuatorDesired.Thrust);
1512  } else {
1513  /* Between the epsilons, we're at zero thrust. Reset smoothcontrol and leave ActuatorDesired be. */
1514  smoothcontrol_reinit_thrust(rc_smoothing, 0);
1515  }
1516 
1517  // Register loop.
1518  smoothcontrol_next(rc_smoothing);
1519 
1520  if (vbar_settings.VbarPiroComp == VBARSETTINGS_VBARPIROCOMP_TRUE)
1521  stabilization_virtual_flybar_pirocomp(gyro_filtered[YAW], dT_expected);
1522 
1523 #if defined(RATEDESIRED_DIAGNOSTICS)
1524  RateDesiredSet(&rateDesired);
1525 #endif
1526 
1527  // Save dT
1528  actuatorDesired.UpdateTime = dT * 1000;
1529 
1530  ActuatorDesiredSet(&actuatorDesired);
1531 
1532  if(flightStatus.Armed != FLIGHTSTATUS_ARMED_ARMED ||
1533  (lowThrottleZeroIntegral && get_throttle(&actuatorDesired, &airframe_type) == 0))
1534  {
1535  // Force all axes to reinitialize when engaged
1536  for(uint8_t i=0; i< MAX_AXES; i++)
1537  previous_mode[i] = 255;
1538  }
1539 
1540  // Clear or set alarms. Done like this to prevent toggling each cycle
1541  // and hammering system alarms
1542  if (error)
1543  AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_ERROR);
1544  else
1545  AlarmsClear(SYSTEMALARMS_ALARM_STABILIZATION);
1546  }
1547 }
1548 
1549 
1553 static void zero_pids(void)
1554 {
1555  for(uint32_t i = 0; i < PID_MAX; i++)
1556  pid_zero(&pids[i]);
1557 
1558 
1559  for(uint8_t i = 0; i < 3; i++)
1560  axis_lock_accum[i] = 0.0f;
1561 }
1562 
1563 static uint8_t remap_smoothing_mode(uint8_t m)
1564 {
1565  // Kind of stupid to do this, but pulling in an UAVO into "library" code feels
1566  // like a layer break.
1567  switch(m)
1568  {
1569  default:
1570  case STABILIZATIONSETTINGS_MANUALCONTROLSMOOTHING_NONE:
1571  return SMOOTHCONTROL_NONE;
1572  case STABILIZATIONSETTINGS_MANUALCONTROLSMOOTHING_NORMAL:
1573  return SMOOTHCONTROL_NORMAL;
1574  case STABILIZATIONSETTINGS_MANUALCONTROLSMOOTHING_LINEAR:
1575  return SMOOTHCONTROL_LINEAR;
1576  }
1577 }
1578 
1579 static void calculate_pids(float dT)
1580 {
1581  // Set the roll rate PID constants
1583  settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KP],
1584  settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KI],
1585  settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KD],
1586  settings.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_ILIMIT],
1587  dT);
1588 
1589  // Set the pitch rate PID constants
1591  settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KP],
1592  settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KI],
1593  settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KD],
1594  settings.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_ILIMIT],
1595  dT);
1596 
1597  // Set the yaw rate PID constants
1599  settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KP],
1600  settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KI],
1601  settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KD],
1602  settings.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_ILIMIT],
1603  dT);
1604 
1605  // Set the roll attitude PI constants
1607  settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KP],
1608  settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_KI], 0,
1609  settings.RollPI[STABILIZATIONSETTINGS_ROLLPI_ILIMIT],
1610  dT);
1611 
1612  // Set the pitch attitude PI constants
1614  settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KP],
1615  settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_KI], 0,
1616  settings.PitchPI[STABILIZATIONSETTINGS_PITCHPI_ILIMIT],
1617  dT);
1618 
1619  // Set the yaw attitude PI constants
1621  settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KP],
1622  settings.YawPI[STABILIZATIONSETTINGS_YAWPI_KI], 0,
1623  settings.YawPI[STABILIZATIONSETTINGS_YAWPI_ILIMIT],
1624  dT);
1625 
1626  // Set the vbar roll settings
1628  vbar_settings.VbarRollPID[VBARSETTINGS_VBARROLLPID_KP],
1629  vbar_settings.VbarRollPID[VBARSETTINGS_VBARROLLPID_KI],
1630  vbar_settings.VbarRollPID[VBARSETTINGS_VBARROLLPID_KD],
1631  0,
1632  dT);
1633 
1634  // Set the vbar pitch settings
1636  vbar_settings.VbarPitchPID[VBARSETTINGS_VBARPITCHPID_KP],
1637  vbar_settings.VbarPitchPID[VBARSETTINGS_VBARPITCHPID_KI],
1638  vbar_settings.VbarPitchPID[VBARSETTINGS_VBARPITCHPID_KD],
1639  0,
1640  dT);
1641 
1642  // Set the vbar yaw settings
1644  vbar_settings.VbarYawPID[VBARSETTINGS_VBARYAWPID_KP],
1645  vbar_settings.VbarYawPID[VBARSETTINGS_VBARYAWPID_KI],
1646  vbar_settings.VbarYawPID[VBARSETTINGS_VBARYAWPID_KD],
1647  0,
1648  dT);
1649 
1650  // Set the coordinated flight settings
1652  settings.CoordinatedFlightYawPI[STABILIZATIONSETTINGS_COORDINATEDFLIGHTYAWPI_KP],
1653  settings.CoordinatedFlightYawPI[STABILIZATIONSETTINGS_COORDINATEDFLIGHTYAWPI_KI],
1654  0, /* No derivative term */
1655  settings.CoordinatedFlightYawPI[STABILIZATIONSETTINGS_COORDINATEDFLIGHTYAWPI_ILIMIT],
1656  dT);
1657 
1658  // Set up the derivative term
1659  pid_configure_derivative(settings.DerivativeCutoff, settings.DerivativeGamma);
1660 
1661 #ifndef NO_CONTROL_DEADBANDS
1662  if(deadbands ||
1663  settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_ROLL] ||
1664  settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_PITCH] ||
1665  settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_YAW])
1666  {
1667  if(!deadbands) deadbands = PIOS_malloc(sizeof(struct pid_deadband) * MAX_AXES);
1668 
1669  pid_configure_deadband(deadbands + PID_RATE_ROLL, (float)settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_ROLL],
1670  0.01f * (float)settings.DeadbandSlope[STABILIZATIONSETTINGS_DEADBANDSLOPE_ROLL]);
1671  pid_configure_deadband(deadbands + PID_RATE_PITCH, (float)settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_PITCH],
1672  0.01f * (float)settings.DeadbandSlope[STABILIZATIONSETTINGS_DEADBANDSLOPE_PITCH]);
1673  pid_configure_deadband(deadbands + PID_RATE_YAW, (float)settings.DeadbandWidth[STABILIZATIONSETTINGS_DEADBANDWIDTH_YAW],
1674  0.01f * (float)settings.DeadbandSlope[STABILIZATIONSETTINGS_DEADBANDSLOPE_YAW]);
1675  }
1676 #endif
1677 }
1678 
1679 static void calculate_vert_pids(float dT)
1680 {
1681 #if defined(TARGET_MAY_HAVE_BARO)
1682  AltitudeHoldSettingsGet(&altitudeHoldSettings);
1683 
1684  pid_configure(&vertspeed_pid, altitudeHoldSettings.VelocityKp,
1685  altitudeHoldSettings.VelocityKi, 0.0f, 1.0f,
1686  dT);
1687 #endif
1688 }
1689 
1690 static void update_settings(float dT)
1691 {
1692  SubTrimSettingsData subTrimSettings;
1693 
1694  SubTrimGet(&subTrim);
1695  SubTrimSettingsGet(&subTrimSettings);
1696 
1697  // Set the trim angles
1698  subTrim.Roll = subTrimSettings.Roll;
1699  subTrim.Pitch = subTrimSettings.Pitch;
1700 
1701  SubTrimSet(&subTrim);
1702 
1703  StabilizationSettingsGet(&settings);
1704  VbarSettingsGet(&vbar_settings);
1705 
1706  calculate_pids(dT);
1707  calculate_vert_pids(dT);
1708 
1709  // Maximum deviation to accumulate for axis lock
1710  max_axis_lock = settings.MaxAxisLock;
1711  max_axislock_rate = settings.MaxAxisLockRate;
1712 
1713  // Settings for weak leveling
1714  weak_leveling_kp = settings.WeakLevelingKp;
1715  weak_leveling_max = settings.MaxWeakLevelingRate;
1716 
1717  // Whether to zero the PID integrals while thrust is low
1718  lowThrottleZeroIntegral = settings.LowThrottleZeroIntegral == STABILIZATIONSETTINGS_LOWTHROTTLEZEROINTEGRAL_TRUE;
1719 
1720 #if defined(TARGET_MAY_HAVE_BARO)
1721  uint8_t altitude_hold_maxclimbrate10;
1722  uint8_t altitude_hold_maxdescentrate10;
1723  AltitudeHoldSettingsMaxClimbRateGet(&altitude_hold_maxclimbrate10);
1724  AltitudeHoldSettingsMaxDescentRateGet(&altitude_hold_maxdescentrate10);
1725 
1726  // Scale altitude hold rate
1727  altitude_hold_maxclimbrate = altitude_hold_maxclimbrate10 * 0.1f;
1728  altitude_hold_maxdescentrate = altitude_hold_maxdescentrate10 * 0.1f;
1729 
1730  AltitudeHoldSettingsExpoGet(&altitude_hold_expo);
1731 #endif
1732 
1733  uint8_t s_mode = remap_smoothing_mode(settings.ManualControlSmoothing[STABILIZATIONSETTINGS_MANUALCONTROLSMOOTHING_AXES]);
1734  uint8_t duty_cycle = settings.ManualControlSmoothingDutyCycle;
1735  smoothcontrol_set_mode(rc_smoothing, ROLL, s_mode, duty_cycle);
1736  smoothcontrol_set_mode(rc_smoothing, PITCH, s_mode, duty_cycle);
1737  smoothcontrol_set_mode(rc_smoothing, YAW, s_mode, duty_cycle);
1739  settings.ManualControlSmoothing[STABILIZATIONSETTINGS_MANUALCONTROLSMOOTHING_THRUST]
1740  ), duty_cycle);
1741 
1742 }
1743 
float pid_apply_setpoint_antiwindup(struct pid *pid, struct pid_deadband *deadband, const float setpoint, const float measured, float min_bound, float max_bound, float aw_bound)
Definition: pid.c:187
static uint8_t weak_leveling_max
static float get_throttle(ActuatorDesiredData *actuator_desired, SystemSettingsAirframeTypeOptions *airframe_type)
#define TASK_PRIORITY
Definition: stabilization.c:98
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
float vbar_decay
uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
Subtract raw time from now and convert to us.
Definition: pios_delay.c:159
void smoothcontrol_set_mode(smoothcontrol_state state, uint8_t axis_num, uint8_t mode, uint8_t duty_cycle)
Definition: smoothcontrol.c:96
LQG Control algorithm.
static StabilizationSettingsData settings
static void update_settings(float dT)
float expoM(float x, int32_t g, float exponent)
Definition: misc_math.c:116
bool stabilization_failsafe_checks(StabilizationDesiredData *stab_desired, ActuatorDesiredData *actuator_desired, SystemSettingsAirframeTypeOptions airframe_type, float *input, uint8_t *mode)
void RPY2Quaternion(const float rpy[3], float q[4])
static uint8_t remap_smoothing_mode(uint8_t m)
int stabilization_virtual_flybar(float gyro, float command, float *output, float dT, bool reinit, uint32_t axis, struct pid *pid, VbarSettingsData *settings)
Definition: virtualflybar.c:44
void quat_copy(const float q[4], float qnew[4])
Duplicate a quaternion.
int32_t PIOS_SENSORS_GetMaxGyro()
Get the maximum gyro rate in deg/s.
Definition: pios_sensors.c:167
#define get_deadband(axis)
struct _msp_pid_item pitch
Definition: msp_messages.h:97
static float max_rate_alpha
static bool lowThrottleZeroIntegral
lqg_t lqg_create(rtkf_t rtkf, lqr_t lqr)
Definition: lqg.c:535
static float scale(float val, float inMin, float inMax, float outMin, float outMax)
Definition: txpid.c:444
#define LQG_SOLVER_RUNNING
Definition: lqg.h:37
void lqr_get_gains(lqr_t lqr, float K[2])
Definition: lqg.c:487
bool PIOS_WDG_RegisterFlag(uint16_t flag_requested)
Register a module against the watchdog.
Definition: pios_wdg.c:86
struct _msp_pid_item roll
Definition: msp_messages.h:96
float iAccumulator
Definition: pid.h:50
bool PIOS_WDG_UpdateFlag(uint16_t flag)
Function called by modules to indicate they are still running.
Definition: pios_wdg.c:102
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
void UAVObjCbSetFlag(const UAVObjEvent *objEv, void *ctx, void *obj, int len)
lqr_t lqg_get_lqr(lqg_t lqg)
Definition: lqg.c:576
int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity)
Definition: alarms.c:97
void quat_mult(const float q1[4], const float q2[4], float qout[4])
Multiply two quaternions into a third.
static VbarSettingsData vbar_settings
volatile bool settings_updated
void lqg_set_x0(lqg_t lqg, float x0)
Definition: lqg.c:557
static struct pid pids[PID_MAX]
uint32_t PIOS_SENSORS_GetSampleRate(enum pios_sensor_type type)
Get the sample rate of a sensor (Hz)
Definition: pios_sensors.c:181
void smoothcontrol_update_dT(smoothcontrol_state state, float dT)
#define COORDINATED_FLIGHT_MIN_ROLL_THRESHOLD
static void calculate_attitude_errors(uint8_t *axis_mode, float *raw_input, AttitudeActualData *attitudeActual, float *local_attitude_error, float *horizon_rate_fraction)
uint16_t min_throttle
Definition: msp_messages.h:97
void pid_configure(struct pid *pid, float p, float i, float d, float iLim, float dT)
Definition: pid.c:280
void lqr_update(lqr_t lqr, float q1, float q2, float r)
Definition: lqg.c:477
static void zero_pids(void)
void pid_configure_deadband(struct pid_deadband *deadband, float width, float slope)
Definition: pid.c:298
int32_t StabilizationStart()
int16_t status
Definition: main.c:61
static SubTrimData subTrim
float circular_modulus_deg(float err)
Circular modulus.
Definition: misc_math.c:62
bool PIOS_SENSORS_IsRegistered(enum pios_sensor_type type)
Checks if a sensor type is registered with the PIOS_SENSORS interface.
Definition: pios_sensors.c:88
Definition: lqg.c:495
void smoothcontrol_reinit_thrust(smoothcontrol_state state, float new_signal)
Definition: smoothcontrol.c:90
void smoothcontrol_next(smoothcontrol_state state)
void smoothcontrol_initialize(smoothcontrol_state *state)
struct pid_deadband * deadbands
#define MAX(a, b)
Definition: misc_math.h:40
static float weak_leveling_kp
#define HORIZON_MODE_MAX_BLEND
Set the stick position that maximally transitions to rate.
static uint8_t max_axislock_rate
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
#define STACK_SIZE_BYTES
Definition: stabilization.c:95
DONT_BUILD_IF((MAX_AXES+0!=3), stabAxisWrongCount)
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
Definition: taskmonitor.c:67
uint8_t i
Definition: msp_messages.h:97
struct _msp_pid_item yaw
Definition: msp_messages.h:98
bool sensors_step()
Definition: sensors.c:213
float bound_min_max(float val, float min, float max)
Bound input value between min and max.
Definition: misc_math.c:38
float bound_sym(float val, float range)
Bound input value within range (plus or minus)
Definition: misc_math.c:50
enum channel_mode mode
Definition: pios_servo.c:58
void lqg_run_covariance(lqg_t lqg, int iter)
Definition: lqg.c:581
void lqg_get_rtkf_state(lqg_t lqg, float *rate, float *torque, float *bias)
Definition: lqg.c:550
#define LQG_SOLVER_FAILED
Definition: lqg.h:36
void pid_zero(struct pid *pid)
Definition: pid.c:252
int stabilization_virtual_flybar_pirocomp(float z_gyro, float dT)
Definition: virtualflybar.c:79
uint16_t ident_wiggle_points
#define PIOS_WDG_STABILIZATION
Definition: pios_wdg.h:36
float pid_apply(struct pid *pid, const float err)
Methods to use the pid structures.
Definition: pid.c:48
accX *accY *accZ * break
Header for Coordinate conversions library in coordinate_conversions.c.
static uint8_t max_axis_lock
uint8_t rate
Definition: msp_messages.h:99
static SystemSettingsAirframeTypeOptions airframe_type
Definition: actuator.c:103
tuple f
Definition: px_mkfw.py:81
#define LQG_SOLVER_DONE
Definition: lqg.h:38
lqr_t lqr_create(float beta, float tau, float Ts, float q1, float q2, float r)
Definition: lqg.c:460
#define MIN(a, b)
Definition: misc_math.h:41
Attitude stabilization module.
rtkf_t rtkf_create(float beta, float tau, float Ts, float R, float q1, float q2, float q3, float biaslim)
Definition: lqg.c:274
bool * smoothcontrol_get_ringer(smoothcontrol_state state)
Includes PiOS and core architecture components.
int32_t AlarmsClear(SystemAlarmsAlarmElem alarm)
Definition: alarms.c:171
void quat_inverse(float q[4])
Compute the inverse of a quaternion.
static void calculate_vert_pids(float dT)
static void stabilizationTask(void *parameters)
int printf(const char *format,...)
MODULE_HIPRI_INITCALL(StabilizationInitialize, StabilizationStart)
Definition: lqg.c:370
void smoothcontrol_run_thrust(smoothcontrol_state state, float *new_signal)
static float calculate_thrust(StabilizationDesiredThrustModeOptions mode, FlightStatusData *flightStatus, SystemSettingsAirframeTypeOptions airframe_type, float desired_thrust)
int32_t StabilizationInitialize()
float pid_apply_setpoint(struct pid *pid, struct pid_deadband *deadband, const float setpoint, const float measured)
Definition: pid.c:141
float pid_apply_antiwindup(struct pid *pid, const float err, float min_bound, float max_bound, float aw_bound)
Definition: pid.c:86
static void calculate_pids(float dT)
float lqg_controller(lqg_t lqg, float signal, float setpoint)
Definition: lqg.c:516
int32_t sensors_init(void)
Definition: sensors.c:143
void pid_configure_derivative(float cutoff, float g)
Configure the common terms that alter ther derivative.
Definition: pid.c:267
float K[NUMX][NUMV]
Definition: insgps14state.c:68
#define COORDINATED_FLIGHT_MAX_YAW_THRESHOLD
Attitude stabilization module.
Definition: pid.h:42
static float dT_expected
Definition: attitude.c:161
#define PIOS_Assert(test)
Definition: pios_debug.h:52
void smoothcontrol_run(smoothcontrol_state state, uint8_t axis_num, float *new_signal)
void error(int)
Definition: main.c:130
#define THROTTLE_EPSILON
Minimum sane positive value for throttle.
static AltitudeHoldSettingsData altitudeHoldSettings
void Quaternion2RPY(const float q[4], float rpy[3])
float expo3(float x, int32_t g)
Approximation an exponential scale curve.
Definition: misc_math.c:111
static float axis_lock_accum[MAX_AXES]
Definition: camerastab.c:69
PID Control algorithms.
void smoothcontrol_reinit(smoothcontrol_state state, uint8_t axis_num, float new_signal)
Definition: smoothcontrol.c:79
bool PIOS_Thread_FakeClock_IsActive(void)
Definition: pios_thread.c:207
int lqg_solver_status(lqg_t lqg)
Definition: lqg.c:564
uint32_t PIOS_DELAY_GetRaw()
Get the raw delay timer, useful for timing.
Definition: pios_delay.c:153
static smoothcontrol_state rc_smoothing
static struct pios_thread * taskHandle