|
51 | 51 | #include "manualcontrolcommand.h"
|
52 | 52 | #include "pios_thread.h"
|
53 | 53 | #include "pios_queue.h"
|
| 54 | +#include "pios_sensors.h" |
54 | 55 | #include "misc_math.h"
|
55 | 56 |
|
56 | 57 | // Private constants
|
@@ -97,6 +98,29 @@ static MixerSettingsMixer1TypeOptions types_mixer[MAX_MIX_ACTUATORS];
|
97 | 98 |
|
98 | 99 | static float motor_mixer[MAX_MIX_ACTUATORS * MIXERSETTINGS_MIXER1VECTOR_NUMELEM];
|
99 | 100 | static float motor_mixer_inv[MAX_MIX_ACTUATORS * MIXERSETTINGS_MIXER1VECTOR_NUMELEM];
|
| 101 | +static bool inverse_mixer_computed = false; |
| 102 | + |
| 103 | +#define SMITHP_MAX_DELAY 64 |
| 104 | + |
| 105 | +struct smith_predictor { |
| 106 | + |
| 107 | + uint32_t samples; |
| 108 | + uint32_t idx; |
| 109 | + |
| 110 | + /* This is gonna be a ring buffer. */ |
| 111 | + float *data; |
| 112 | + |
| 113 | + float iir_alpha; |
| 114 | + float iir[MAX_MIX_ACTUATORS]; |
| 115 | + |
| 116 | + float mix; |
| 117 | +}; |
| 118 | + |
| 119 | +static struct smith_predictor* smithp_init(float delay, float iir, float mix); |
| 120 | +static void smithp_push_vect(struct smith_predictor *m, float *motor_vect); |
| 121 | +static void smithp_compensate(struct smith_predictor *m, float *motor_vect); |
| 122 | + |
| 123 | +struct smith_predictor *smithp; |
100 | 124 |
|
101 | 125 | /* These are various settings objects used throughout the actuator code */
|
102 | 126 | static ActuatorSettingsData actuatorSettings;
|
@@ -699,6 +723,14 @@ static void actuator_settings_update()
|
699 | 723 | desired_3d_mask |= (1 << i);
|
700 | 724 | }
|
701 | 725 | }
|
| 726 | + |
| 727 | + if (!smithp && actuatorSettings.SmithPredictorDelay > 0.1f) { |
| 728 | + float dT = 1.0f / (float)PIOS_SENSORS_GetSampleRate(PIOS_SENSOR_GYRO) * 1000.0f; |
| 729 | + int delay = (int)(actuatorSettings.SmithPredictorDelay / dT + 0.5f); |
| 730 | + if (delay > 0) { |
| 731 | + smithp = smithp_init(delay, actuatorSettings.SmithPredictorIIR, actuatorSettings.SmithPredictorMix); |
| 732 | + } |
| 733 | + } |
702 | 734 | }
|
703 | 735 |
|
704 | 736 | /**
|
@@ -754,17 +786,13 @@ static void actuator_task(void* parameters)
|
754 | 786 | SystemSettingsAirframeTypeGet(&airframe_type);
|
755 | 787 |
|
756 | 788 | compute_mixer();
|
757 |
| -<<<<<<< HEAD |
758 |
| -======= |
759 | 789 |
|
760 | 790 | /* If we can't calculate a proper inverse mixer,
|
761 | 791 | * set failsafe.
|
762 | 792 | */
|
763 | 793 | if (compute_inverse_mixer()) {
|
764 |
| - set_failsafe(); |
765 |
| - continue; |
| 794 | + inverse_mixer_computed = true; |
766 | 795 | }
|
767 |
| ->>>>>>> mlyle/mpl-actmodel |
768 | 796 |
|
769 | 797 | MixerSettingsThrottleCurve2Get(curve2);
|
770 | 798 | MixerSettingsCurve2SourceGet(&curve2_src);
|
@@ -838,6 +866,8 @@ static void actuator_task(void* parameters)
|
838 | 866 | normalize_input_data(this_systime, &desired_vect, &armed,
|
839 | 867 | &spin_while_armed, &stabilize_now);
|
840 | 868 |
|
| 869 | + smithp_compensate(smithp, desired_vect); |
| 870 | + |
841 | 871 | /* Multiply the actuators x desired matrix by the
|
842 | 872 | * desired x 1 column vector. */
|
843 | 873 | matrix_mul_check(motor_mixer, desired_vect, motor_vect,
|
@@ -870,6 +900,8 @@ static void actuator_task(void* parameters)
|
870 | 900 | dT, armed, spin_while_armed, stabilize_now,
|
871 | 901 | &maxpoweradd_bucket);
|
872 | 902 |
|
| 903 | + smithp_push_vect(smithp, motor_vect); |
| 904 | + |
873 | 905 | /* If we got this far, everything is OK. */
|
874 | 906 | AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR);
|
875 | 907 | }
|
@@ -1076,6 +1108,73 @@ static void set_failsafe()
|
1076 | 1108 | ActuatorCommandChannelSet(Channel);
|
1077 | 1109 | }
|
1078 | 1110 |
|
| 1111 | +static struct smith_predictor* smithp_init(float delay, float iir, float mix) |
| 1112 | +{ |
| 1113 | + struct smith_predictor *m = PIOS_malloc_no_dma(sizeof(*m)); |
| 1114 | + if (!m) |
| 1115 | + return NULL; |
| 1116 | + memset(m, 0, sizeof(*m)); |
| 1117 | + |
| 1118 | + if (delay > SMITHP_MAX_DELAY) delay = SMITHP_MAX_DELAY; |
| 1119 | + |
| 1120 | + m->samples = delay; |
| 1121 | + m->iir_alpha = iir; |
| 1122 | + m->mix = mix; |
| 1123 | + |
| 1124 | + m->data = PIOS_malloc_no_dma(delay * MAX_MIX_ACTUATORS * sizeof(*m->data)); |
| 1125 | + if (!m->data) |
| 1126 | + return NULL; |
| 1127 | + memset(m->data, 0, sizeof(*m->data) * delay * MAX_MIX_ACTUATORS); |
| 1128 | + |
| 1129 | + return m; |
| 1130 | +} |
| 1131 | + |
| 1132 | +/* |
| 1133 | + Call order for it to work should be: |
| 1134 | + - Compensate |
| 1135 | + - Push vect |
| 1136 | +*/ |
| 1137 | + |
| 1138 | +static void smithp_push_vect(struct smith_predictor *m, float *motor_vect) |
| 1139 | +{ |
| 1140 | + if (!m) return; |
| 1141 | + |
| 1142 | + uint32_t p = (m->idx % m->samples) * MAX_MIX_ACTUATORS; |
| 1143 | + |
| 1144 | + /* Write motor vector to position. */ |
| 1145 | + for (int i = 0; i < MAX_MIX_ACTUATORS; i++) { |
| 1146 | + float v = motor_vect[i]; |
| 1147 | + m->data[p++] = v != v ? 0 : v; |
| 1148 | + } |
| 1149 | + |
| 1150 | + /* Moves pointer to oldest data point (via modulo) for _compensate. */ |
| 1151 | + m->idx++; |
| 1152 | +} |
| 1153 | + |
| 1154 | +static void smithp_compensate(struct smith_predictor *m, float *desired_vect) |
| 1155 | +{ |
| 1156 | + if (!m || !inverse_mixer_computed) return; |
| 1157 | + |
| 1158 | + uint32_t p = (m->idx % m->samples) * MAX_MIX_ACTUATORS; |
| 1159 | + |
| 1160 | + float inv[MIXERSETTINGS_MIXER1VECTOR_NUMELEM]; |
| 1161 | + |
| 1162 | + for (int i = 0; i < MAX_MIX_ACTUATORS; i++) { |
| 1163 | + /* Do IIR on delayed data*/ |
| 1164 | + m->iir[i] = m->iir[i] * m->iir_alpha + (1 - m->iir_alpha) * m->data[p++]; |
| 1165 | + } |
| 1166 | + |
| 1167 | + /* Do inverse stuff. */ |
| 1168 | + matrix_mul_check(motor_mixer_inv, m->iir, inv, |
| 1169 | + MIXERSETTINGS_MIXER1VECTOR_NUMELEM, |
| 1170 | + MAX_MIX_ACTUATORS, |
| 1171 | + 1); |
| 1172 | + |
| 1173 | + for (int i = 0; i < MIXERSETTINGS_MIXER1VECTOR_NUMELEM; i++) { |
| 1174 | + desired_vect[i] += m->mix * (desired_vect[i] - inv[i]); |
| 1175 | + } |
| 1176 | +} |
| 1177 | + |
1079 | 1178 | /**
|
1080 | 1179 | * @}
|
1081 | 1180 | * @}
|
|
0 commit comments