forked from ArduPilot/ardupilot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tuning.cpp
348 lines (293 loc) · 11.7 KB
/
tuning.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#include "Plane.h"
/*
the vehicle class has its own var table for TUNE_PARAM so it can
have separate parameter docs for the list of available parameters
*/
const AP_Param::GroupInfo AP_Tuning_Plane::var_info[] = {
// @Param: PARAM
// @DisplayName: Transmitter tuning parameter or set of parameters
// @Description: This sets which parameter or set of parameters will be tuned. Values greater than 100 indicate a set of parameters rather than a single parameter. Parameters less than 50 are for QuadPlane vertical lift motors only.
// @Values: 0:None,1:RateRollPI,2:RateRollP,3:RateRollI,4:RateRollD,5:RatePitchPI,6:RatePitchP,7:RatePitchI,8:RatePitchD,9:RateYawPI,10:RateYawP,11:RateYawI,12:RateYawD,13:AngleRollP,14:AnglePitchP,15:AngleYawP,16:PosXYP,17:PosZP,18:VelXYP,19:VelXYI,20:VelZP,21:AccelZP,22:AccelZI,23:AccelZD,50:FixedWingRollP,51:FixedWingRollI,52:FixedWingRollD,53:FixedWingRollFF,54:FixedWingPitchP,55:FixedWingPitchI,56:FixedWingPitchD,57:FixedWingPitchFF,101:Set_RateRollPitch,102:Set_RateRoll,103:Set_RatePitch,104:Set_RateYaw,105:Set_AngleRollPitch,106:Set_VelXY,107:Set_AccelZ
// @User: Standard
AP_GROUPINFO("PARAM", 1, AP_Tuning_Plane, parmset, 0),
// the rest of the parameters are from AP_Tuning
AP_NESTEDGROUPINFO(AP_Tuning, 0),
AP_GROUPEND
};
/*
tables of tuning sets
*/
const uint8_t AP_Tuning_Plane::tuning_set_rate_roll_pitch[] = { TUNING_RATE_ROLL_D, TUNING_RATE_ROLL_PI,
TUNING_RATE_PITCH_D, TUNING_RATE_PITCH_PI};
const uint8_t AP_Tuning_Plane::tuning_set_rate_roll[] = { TUNING_RATE_ROLL_D, TUNING_RATE_ROLL_PI };
const uint8_t AP_Tuning_Plane::tuning_set_rate_pitch[] = { TUNING_RATE_PITCH_D, TUNING_RATE_PITCH_PI };
const uint8_t AP_Tuning_Plane::tuning_set_rate_yaw[] = { TUNING_RATE_YAW_P, TUNING_RATE_YAW_I, TUNING_RATE_YAW_D };
const uint8_t AP_Tuning_Plane::tuning_set_ang_roll_pitch[] = { TUNING_ANG_ROLL_P, TUNING_ANG_PITCH_P };
const uint8_t AP_Tuning_Plane::tuning_set_vxy[] = { TUNING_VXY_P, TUNING_VXY_I };
const uint8_t AP_Tuning_Plane::tuning_set_az[] = { TUNING_AZ_P, TUNING_AZ_I, TUNING_AZ_D };
// macro to prevent getting the array length wrong
#define TUNING_ARRAY(v) ARRAY_SIZE(v), v
// list of tuning sets
const AP_Tuning_Plane::tuning_set AP_Tuning_Plane::tuning_sets[] = {
{ TUNING_SET_RATE_ROLL_PITCH, TUNING_ARRAY(tuning_set_rate_roll_pitch) },
{ TUNING_SET_RATE_ROLL, TUNING_ARRAY(tuning_set_rate_roll) },
{ TUNING_SET_RATE_PITCH, TUNING_ARRAY(tuning_set_rate_pitch) },
{ TUNING_SET_RATE_YAW, TUNING_ARRAY(tuning_set_rate_yaw) },
{ TUNING_SET_ANG_ROLL_PITCH, TUNING_ARRAY(tuning_set_ang_roll_pitch) },
{ TUNING_SET_VXY, TUNING_ARRAY(tuning_set_vxy) },
{ TUNING_SET_AZ, TUNING_ARRAY(tuning_set_az) },
{ 0, 0, nullptr }
};
/*
table of tuning names
*/
const AP_Tuning_Plane::tuning_name AP_Tuning_Plane::tuning_names[] = {
{ TUNING_RATE_ROLL_PI, "RateRollPI" },
{ TUNING_RATE_ROLL_P, "RateRollP" },
{ TUNING_RATE_ROLL_I, "RateRollI" },
{ TUNING_RATE_ROLL_D, "RateRollD" },
{ TUNING_RATE_PITCH_PI,"RatePitchPI" },
{ TUNING_RATE_PITCH_P, "RatePitchP" },
{ TUNING_RATE_PITCH_I, "RatePitchI" },
{ TUNING_RATE_PITCH_D, "RatePitchD" },
{ TUNING_RATE_YAW_PI, "RateYawPI" },
{ TUNING_RATE_YAW_P, "RateYawP" },
{ TUNING_RATE_YAW_I, "RateYawI" },
{ TUNING_RATE_YAW_D, "RateYawD" },
{ TUNING_ANG_ROLL_P, "AngRollP" },
{ TUNING_ANG_PITCH_P, "AngPitchP" },
{ TUNING_ANG_YAW_P, "AngYawP" },
{ TUNING_PXY_P, "PXY_P" },
{ TUNING_PZ_P, "PZ_P" },
{ TUNING_VXY_P, "VXY_P" },
{ TUNING_VXY_I, "VXY_I" },
{ TUNING_VZ_P, "VZ_P" },
{ TUNING_AZ_P, "RateAZ_P" },
{ TUNING_AZ_I, "RateAZ_I" },
{ TUNING_AZ_D, "RateAZ_D" },
{ TUNING_RLL_P, "RollP" },
{ TUNING_RLL_I, "RollI" },
{ TUNING_RLL_D, "RollD" },
{ TUNING_RLL_FF, "RollFF" },
{ TUNING_PIT_P, "PitchP" },
{ TUNING_PIT_I, "PitchI" },
{ TUNING_PIT_D, "PitchD" },
{ TUNING_PIT_FF, "PitchFF" },
{ TUNING_NONE, nullptr }
};
/*
get a pointer to an AP_Float for a parameter, or nullptr on fail
*/
AP_Float *AP_Tuning_Plane::get_param_pointer(uint8_t parm)
{
if (parm < TUNING_FIXED_WING_BASE && !plane.quadplane.available()) {
// quadplane tuning options not available
return nullptr;
}
switch(parm) {
case TUNING_RATE_ROLL_PI:
// use P for initial value when tuning PI
return &plane.quadplane.attitude_control->get_rate_roll_pid().kP();
case TUNING_RATE_ROLL_P:
return &plane.quadplane.attitude_control->get_rate_roll_pid().kP();
case TUNING_RATE_ROLL_I:
return &plane.quadplane.attitude_control->get_rate_roll_pid().kI();
case TUNING_RATE_ROLL_D:
return &plane.quadplane.attitude_control->get_rate_roll_pid().kD();
case TUNING_RATE_PITCH_PI:
return &plane.quadplane.attitude_control->get_rate_pitch_pid().kP();
case TUNING_RATE_PITCH_P:
return &plane.quadplane.attitude_control->get_rate_pitch_pid().kP();
case TUNING_RATE_PITCH_I:
return &plane.quadplane.attitude_control->get_rate_pitch_pid().kI();
case TUNING_RATE_PITCH_D:
return &plane.quadplane.attitude_control->get_rate_pitch_pid().kD();
case TUNING_RATE_YAW_PI:
return &plane.quadplane.attitude_control->get_rate_yaw_pid().kP();
case TUNING_RATE_YAW_P:
return &plane.quadplane.attitude_control->get_rate_yaw_pid().kP();
case TUNING_RATE_YAW_I:
return &plane.quadplane.attitude_control->get_rate_yaw_pid().kI();
case TUNING_RATE_YAW_D:
return &plane.quadplane.attitude_control->get_rate_yaw_pid().kD();
case TUNING_ANG_ROLL_P:
return &plane.quadplane.attitude_control->get_angle_roll_p().kP();
case TUNING_ANG_PITCH_P:
return &plane.quadplane.attitude_control->get_angle_pitch_p().kP();
case TUNING_ANG_YAW_P:
return &plane.quadplane.attitude_control->get_angle_yaw_p().kP();
case TUNING_PXY_P:
return &plane.quadplane.pos_control->get_pos_xy_p().kP();
case TUNING_PZ_P:
return &plane.quadplane.pos_control->get_pos_z_p().kP();
case TUNING_VXY_P:
return &plane.quadplane.pos_control->get_vel_xy_pid().kP();
case TUNING_VXY_I:
return &plane.quadplane.pos_control->get_vel_xy_pid().kI();
case TUNING_VZ_P:
return &plane.quadplane.pos_control->get_vel_z_p().kP();
case TUNING_AZ_P:
return &plane.quadplane.pos_control->get_accel_z_pid().kP();
case TUNING_AZ_I:
return &plane.quadplane.pos_control->get_accel_z_pid().kI();
case TUNING_AZ_D:
return &plane.quadplane.pos_control->get_accel_z_pid().kD();
// fixed wing tuning parameters
case TUNING_RLL_P:
return &plane.rollController.kP();
case TUNING_RLL_I:
return &plane.rollController.kI();
case TUNING_RLL_D:
return &plane.rollController.kD();
case TUNING_RLL_FF:
return &plane.rollController.kFF();
case TUNING_PIT_P:
return &plane.pitchController.kP();
case TUNING_PIT_I:
return &plane.pitchController.kI();
case TUNING_PIT_D:
return &plane.pitchController.kD();
case TUNING_PIT_FF:
return &plane.pitchController.kFF();
}
return nullptr;
}
/*
save a parameter
*/
void AP_Tuning_Plane::save_value(uint8_t parm)
{
switch(parm) {
// special handling of dual-parameters
case TUNING_RATE_ROLL_PI:
save_value(TUNING_RATE_ROLL_P);
save_value(TUNING_RATE_ROLL_I);
break;
case TUNING_RATE_PITCH_PI:
save_value(TUNING_RATE_PITCH_P);
save_value(TUNING_RATE_PITCH_I);
break;
default:
AP_Float *f = get_param_pointer(parm);
if (f != nullptr) {
f->save();
}
break;
}
}
/*
set a parameter
*/
void AP_Tuning_Plane::set_value(uint8_t parm, float value)
{
switch(parm) {
// special handling of dual-parameters
case TUNING_RATE_ROLL_PI:
set_value(TUNING_RATE_ROLL_P, value);
set_value(TUNING_RATE_ROLL_I, value);
break;
case TUNING_RATE_PITCH_PI:
set_value(TUNING_RATE_PITCH_P, value);
set_value(TUNING_RATE_PITCH_I, value);
break;
default:
AP_Float *f = get_param_pointer(parm);
if (f != nullptr) {
uint64_t param_bit = (1ULL << parm);
if (!(param_bit & have_set)) {
// first time this param has been set by tuning. We
// need to see if a reversion value is available in
// FRAM, and if not then save one
float current_value = f->get();
if (!f->load()) {
// there is no value in FRAM, set one
f->set_and_save(current_value);
}
have_set |= param_bit;
}
f->set_and_notify(value);
}
break;
}
}
/*
reload a parameter
*/
void AP_Tuning_Plane::reload_value(uint8_t parm)
{
switch(parm) {
// special handling of dual-parameters
case TUNING_RATE_ROLL_PI:
reload_value(TUNING_RATE_ROLL_P);
reload_value(TUNING_RATE_ROLL_I);
break;
case TUNING_RATE_PITCH_PI:
reload_value(TUNING_RATE_PITCH_P);
reload_value(TUNING_RATE_PITCH_I);
break;
default:
AP_Float *f = get_param_pointer(parm);
if (f != nullptr) {
uint64_t param_bit = (1ULL << parm);
// only reload if we have set this parameter at some point
if (param_bit & have_set) {
f->load();
}
}
break;
}
}
/*
return current controller error
*/
float AP_Tuning_Plane::controller_error(uint8_t parm)
{
if (!plane.quadplane.available()) {
return 0;
}
// in general a good tune will have rmsP significantly greater
// than rmsD. Otherwise it is too easy to push D too high while
// tuning a quadplane and end up with D dominating
const float max_P_D_ratio = 3.0f;
if (plane.quadplane.motors->get_throttle() < 0.1f) {
// don't report stale errors if not running VTOL motors
return 0;
}
switch(parm) {
// special handling of dual-parameters
case TUNING_RATE_ROLL_PI:
case TUNING_RATE_ROLL_P:
case TUNING_RATE_ROLL_I:
return plane.quadplane.attitude_control->control_monitor_rms_output_roll();
case TUNING_RATE_ROLL_D: {
// special case for D term to keep it well below P
float rms_P = plane.quadplane.attitude_control->control_monitor_rms_output_roll_P();
float rms_D = plane.quadplane.attitude_control->control_monitor_rms_output_roll_D();
if (rms_P < rms_D * max_P_D_ratio) {
return max_P_D_ratio;
}
return rms_P+rms_D;
}
case TUNING_RATE_PITCH_PI:
case TUNING_RATE_PITCH_P:
case TUNING_RATE_PITCH_I:
return plane.quadplane.attitude_control->control_monitor_rms_output_pitch();
case TUNING_RATE_PITCH_D: {
// special case for D term to keep it well below P
float rms_P = plane.quadplane.attitude_control->control_monitor_rms_output_pitch_P();
float rms_D = plane.quadplane.attitude_control->control_monitor_rms_output_pitch_D();
if (rms_P < rms_D * max_P_D_ratio) {
return max_P_D_ratio;
}
return rms_P+rms_D;
}
case TUNING_RATE_YAW_PI:
case TUNING_RATE_YAW_P:
case TUNING_RATE_YAW_I:
case TUNING_RATE_YAW_D:
return plane.quadplane.attitude_control->control_monitor_rms_output_yaw();
default:
// no special handler
return 0;
}
}