@@ -37,7 +37,6 @@ using namespace time_literals;
37
37
using namespace matrix ;
38
38
39
39
using math::constrain;
40
- using math::interpolate;
41
40
using math::radians;
42
41
43
42
FixedwingRateControl::FixedwingRateControl (bool vtol) :
@@ -54,6 +53,7 @@ FixedwingRateControl::FixedwingRateControl(bool vtol) :
54
53
parameters_update ();
55
54
56
55
_rate_ctrl_status_pub.advertise ();
56
+ _trim_slew.setSlewRate (Vector3f (0 .01f , 0 .01f , 0 .01f ));
57
57
}
58
58
59
59
FixedwingRateControl::~FixedwingRateControl ()
@@ -96,6 +96,12 @@ FixedwingRateControl::parameters_update()
96
96
return PX4_OK;
97
97
}
98
98
99
+ void
100
+ FixedwingRateControl::save_params ()
101
+ {
102
+ _trim.saveParams ();
103
+ }
104
+
99
105
void
100
106
FixedwingRateControl::vehicle_manual_poll ()
101
107
{
@@ -127,13 +133,14 @@ FixedwingRateControl::vehicle_manual_poll()
127
133
128
134
} else {
129
135
// Manual/direct control, filled in FW-frame. Note that setpoints will get transformed to body frame prior publishing.
136
+ const Vector3f trim = _trim_slew.getState ();
130
137
131
138
_vehicle_torque_setpoint.xyz [0 ] = math::constrain (_manual_control_setpoint.roll * _param_fw_man_r_sc.get () +
132
- _param_trim_roll. get ( ), -1 .f , 1 .f );
139
+ trim ( 0 ), -1 .f , 1 .f );
133
140
_vehicle_torque_setpoint.xyz [1 ] = math::constrain (-_manual_control_setpoint.pitch * _param_fw_man_p_sc.get () +
134
- _param_trim_pitch. get ( ), -1 .f , 1 .f );
141
+ trim ( 1 ), -1 .f , 1 .f );
135
142
_vehicle_torque_setpoint.xyz [2 ] = math::constrain (_manual_control_setpoint.yaw * _param_fw_man_y_sc.get () +
136
- _param_trim_yaw. get ( ), -1 .f , 1 .f );
143
+ trim ( 2 ), -1 .f , 1 .f );
137
144
138
145
_vehicle_thrust_setpoint.xyz [0 ] = math::constrain ((_manual_control_setpoint.throttle + 1 .f ) * .5f , 0 .f , 1 .f );
139
146
}
@@ -256,7 +263,14 @@ void FixedwingRateControl::Run()
256
263
const bool is_fixed_wing = _vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
257
264
_in_fw_or_transition_wo_tailsitter_transition = is_fixed_wing || is_in_transition_except_tailsitter;
258
265
259
- _vehicle_control_mode_sub.update (&_vcontrol_mode);
266
+ {
267
+ const bool armed_prev = _vcontrol_mode.flag_armed ;
268
+ _vehicle_control_mode_sub.update (&_vcontrol_mode);
269
+
270
+ if (!_vcontrol_mode.flag_armed && armed_prev) {
271
+ save_params ();
272
+ }
273
+ }
260
274
261
275
vehicle_land_detected_poll ();
262
276
@@ -321,78 +335,56 @@ void FixedwingRateControl::Run()
321
335
}
322
336
}
323
337
324
- /* bi-linear interpolation over airspeed for actuator trim scheduling */
325
- Vector3f trim (_param_trim_roll.get (), _param_trim_pitch.get (), _param_trim_yaw.get ());
326
-
327
- if (airspeed < _param_fw_airspd_trim.get ()) {
328
- trim (0 ) += interpolate (airspeed, _param_fw_airspd_min.get (), _param_fw_airspd_trim.get (),
329
- _param_fw_dtrim_r_vmin.get (),
330
- 0 .0f );
331
- trim (1 ) += interpolate (airspeed, _param_fw_airspd_min.get (), _param_fw_airspd_trim.get (),
332
- _param_fw_dtrim_p_vmin.get (),
333
- 0 .0f );
334
- trim (2 ) += interpolate (airspeed, _param_fw_airspd_min.get (), _param_fw_airspd_trim.get (),
335
- _param_fw_dtrim_y_vmin.get (),
336
- 0 .0f );
337
-
338
- } else {
339
- trim (0 ) += interpolate (airspeed, _param_fw_airspd_trim.get (), _param_fw_airspd_max.get (), 0 .0f ,
340
- _param_fw_dtrim_r_vmax.get ());
341
- trim (1 ) += interpolate (airspeed, _param_fw_airspd_trim.get (), _param_fw_airspd_max.get (), 0 .0f ,
342
- _param_fw_dtrim_p_vmax.get ());
343
- trim (2 ) += interpolate (airspeed, _param_fw_airspd_trim.get (), _param_fw_airspd_max.get (), 0 .0f ,
344
- _param_fw_dtrim_y_vmax.get ());
345
- }
338
+ _trim.setAirspeed (airspeed);
339
+ _trim_slew.update (_trim.getTrim (), dt);
346
340
347
- if (_vcontrol_mode.flag_control_rates_enabled ) {
348
- _rates_sp_sub.update (&_rates_sp);
341
+ _rates_sp_sub.update (&_rates_sp);
349
342
350
- Vector3f body_rates_setpoint = Vector3f (_rates_sp.roll , _rates_sp.pitch , _rates_sp.yaw );
343
+ Vector3f body_rates_setpoint = Vector3f (_rates_sp.roll , _rates_sp.pitch , _rates_sp.yaw );
351
344
352
- // Tailsitter: rotate setpoint from hover to fixed-wing frame (controller is in fixed-wing frame, interface in hover)
353
- if (_vehicle_status.is_vtol_tailsitter ) {
354
- body_rates_setpoint = Vector3f (-_rates_sp.yaw , _rates_sp.pitch , _rates_sp.roll );
355
- }
345
+ // Tailsitter: rotate setpoint from hover to fixed-wing frame (controller is in fixed-wing frame, interface in hover)
346
+ if (_vehicle_status.is_vtol_tailsitter ) {
347
+ body_rates_setpoint = Vector3f (-_rates_sp.yaw , _rates_sp.pitch , _rates_sp.roll );
348
+ }
356
349
357
- // Run attitude RATE controllers which need the desired attitudes from above, add trim.
358
- const Vector3f angular_acceleration_setpoint = _rate_control.update (rates, body_rates_setpoint, angular_accel, dt,
359
- _landed);
350
+ // Run attitude RATE controllers which need the desired attitudes from above, add trim.
351
+ const Vector3f angular_acceleration_setpoint = _rate_control.update (rates, body_rates_setpoint, angular_accel, dt,
352
+ _landed);
360
353
361
- const Vector3f gain_ff (_param_fw_rr_ff.get (), _param_fw_pr_ff.get (), _param_fw_yr_ff.get ());
362
- const Vector3f feedforward = gain_ff.emult (body_rates_setpoint) * _airspeed_scaling;
354
+ const Vector3f gain_ff (_param_fw_rr_ff.get (), _param_fw_pr_ff.get (), _param_fw_yr_ff.get ());
355
+ const Vector3f feedforward = gain_ff.emult (body_rates_setpoint) * _airspeed_scaling;
363
356
364
- Vector3f control_u = angular_acceleration_setpoint * _airspeed_scaling * _airspeed_scaling + feedforward;
357
+ Vector3f control_u = angular_acceleration_setpoint * _airspeed_scaling * _airspeed_scaling + feedforward;
365
358
366
- // Special case yaw in Acro: if the parameter FW_ACRO_YAW_CTL is not set then don't control yaw
367
- if (!_vcontrol_mode.flag_control_attitude_enabled && !_param_fw_acro_yaw_en.get ()) {
368
- control_u (2 ) = _manual_control_setpoint.yaw * _param_fw_man_y_sc.get ();
369
- _rate_control.resetIntegral (2 );
370
- }
359
+ // Special case yaw in Acro: if the parameter FW_ACRO_YAW_CTL is not set then don't control yaw
360
+ if (!_vcontrol_mode.flag_control_attitude_enabled && !_param_fw_acro_yaw_en.get ()) {
361
+ control_u (2 ) = _manual_control_setpoint.yaw * _param_fw_man_y_sc.get ();
362
+ _rate_control.resetIntegral (2 );
363
+ }
371
364
372
- if (control_u.isAllFinite ()) {
373
- matrix::constrain (control_u + trim , -1 .f , 1 .f ).copyTo (_vehicle_torque_setpoint.xyz );
365
+ if (control_u.isAllFinite ()) {
366
+ matrix::constrain (control_u + _trim_slew. getState () , -1 .f , 1 .f ).copyTo (_vehicle_torque_setpoint.xyz );
374
367
375
- } else {
376
- _rate_control.resetIntegral ();
377
- trim .copyTo (_vehicle_torque_setpoint.xyz );
378
- }
368
+ } else {
369
+ _rate_control.resetIntegral ();
370
+ _trim_slew. getState () .copyTo (_vehicle_torque_setpoint.xyz );
371
+ }
379
372
380
- /* throttle passed through if it is finite */
381
- _vehicle_thrust_setpoint.xyz [0 ] = PX4_ISFINITE (_rates_sp.thrust_body [0 ]) ? _rates_sp.thrust_body [0 ] : 0 .0f ;
373
+ /* throttle passed through if it is finite */
374
+ _vehicle_thrust_setpoint.xyz [0 ] = PX4_ISFINITE (_rates_sp.thrust_body [0 ]) ? _rates_sp.thrust_body [0 ] : 0 .0f ;
382
375
383
- /* scale effort by battery status */
384
- if (_param_fw_bat_scale_en.get () && _vehicle_thrust_setpoint.xyz [0 ] > 0 .1f ) {
376
+ /* scale effort by battery status */
377
+ if (_param_fw_bat_scale_en.get () && _vehicle_thrust_setpoint.xyz [0 ] > 0 .1f ) {
385
378
386
- if (_battery_status_sub.updated ()) {
387
- battery_status_s battery_status{};
379
+ if (_battery_status_sub.updated ()) {
380
+ battery_status_s battery_status{};
388
381
389
- if (_battery_status_sub.copy (&battery_status) && battery_status.connected && battery_status.scale > 0 .f ) {
390
- _battery_scale = battery_status.scale ;
391
- }
382
+ if (_battery_status_sub.copy (&battery_status) && battery_status.connected && battery_status.scale > 0 .f ) {
383
+ _battery_scale = battery_status.scale ;
392
384
}
393
-
394
- _vehicle_thrust_setpoint.xyz [0 ] *= _battery_scale;
395
385
}
386
+
387
+ _vehicle_thrust_setpoint.xyz [0 ] *= _battery_scale;
396
388
}
397
389
398
390
// publish rate controller status
@@ -405,6 +397,7 @@ void FixedwingRateControl::Run()
405
397
} else {
406
398
// full manual
407
399
_rate_control.resetIntegral ();
400
+ _trim.reset ();
408
401
}
409
402
410
403
// Add feed-forward from roll control output to yaw control output
@@ -432,6 +425,8 @@ void FixedwingRateControl::Run()
432
425
_vehicle_torque_setpoint.timestamp_sample = angular_velocity.timestamp_sample ;
433
426
_vehicle_torque_setpoint_pub.publish (_vehicle_torque_setpoint);
434
427
}
428
+
429
+ _trim.updateAutoTrim (Vector3f (_vehicle_torque_setpoint.xyz ), dt);
435
430
}
436
431
437
432
updateActuatorControlsStatus (dt);
0 commit comments