PX4 Firmware
PX4 Autopilot Software http://px4.io
RateControl.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file RateControl.cpp
36  */
37 
38 #include <RateControl.hpp>
39 #include <px4_platform_common/defines.h>
40 
41 using namespace matrix;
42 
43 void RateControl::setGains(const Vector3f &P, const Vector3f &I, const Vector3f &D)
44 {
45  _gain_p = P;
46  _gain_i = I;
47  _gain_d = D;
48 }
49 
50 void RateControl::setDTermCutoff(const float loop_rate, const float cutoff, const bool force)
51 {
52  // only do expensive filter update if the cutoff changed
53  if (force || fabsf(_lp_filters_d.get_cutoff_freq() - cutoff) > 0.01f) {
54  _lp_filters_d.set_cutoff_frequency(loop_rate, cutoff);
55  _lp_filters_d.reset(_rate_prev);
56  }
57 }
58 
60 {
61  _mixer_saturation_positive[0] = status.flags.roll_pos;
62  _mixer_saturation_positive[1] = status.flags.pitch_pos;
63  _mixer_saturation_positive[2] = status.flags.yaw_pos;
64  _mixer_saturation_negative[0] = status.flags.roll_neg;
65  _mixer_saturation_negative[1] = status.flags.pitch_neg;
66  _mixer_saturation_negative[2] = status.flags.yaw_neg;
67 }
68 
69 Vector3f RateControl::update(const Vector3f &rate, const Vector3f &rate_sp, const float dt, const bool landed)
70 {
71  // angular rates error
72  Vector3f rate_error = rate_sp - rate;
73 
74  // prepare D-term based on low-pass filtered rates
75  const Vector3f rate_filtered(_lp_filters_d.apply(rate));
76  Vector3f rate_d;
77 
78  if (dt > FLT_EPSILON) {
79  rate_d = (rate_filtered - _rate_prev_filtered) / dt;
80  }
81 
82  // PID control with feed forward
83  const Vector3f torque = _gain_p.emult(rate_error) + _rate_int - _gain_d.emult(rate_d) + _gain_ff.emult(rate_sp);
84 
85  _rate_prev = rate;
86  _rate_prev_filtered = rate_filtered;
87 
88  // update integral only if we are not landed
89  if (!landed) {
90  updateIntegral(rate_error, dt);
91  }
92 
93  return torque;
94 }
95 
96 void RateControl::updateIntegral(Vector3f &rate_error, const float dt)
97 {
98  for (int i = 0; i < 3; i++) {
99  // prevent further positive control saturation
100  if (_mixer_saturation_positive[i]) {
101  rate_error(i) = math::min(rate_error(i), 0.f);
102  }
103 
104  // prevent further negative control saturation
105  if (_mixer_saturation_negative[i]) {
106  rate_error(i) = math::max(rate_error(i), 0.f);
107  }
108 
109  // I term factor: reduce the I gain with increasing rate error.
110  // This counteracts a non-linear effect where the integral builds up quickly upon a large setpoint
111  // change (noticeable in a bounce-back effect after a flip).
112  // The formula leads to a gradual decrease w/o steps, while only affecting the cases where it should:
113  // with the parameter set to 400 degrees, up to 100 deg rate error, i_factor is almost 1 (having no effect),
114  // and up to 200 deg error leads to <25% reduction of I.
115  float i_factor = rate_error(i) / math::radians(400.f);
116  i_factor = math::max(0.0f, 1.f - i_factor * i_factor);
117 
118  // Perform the integration using a first order method
119  float rate_i = _rate_int(i) + i_factor * _gain_i(i) * rate_error(i) * dt;
120 
121  // do not propagate the result if out of range or invalid
122  if (PX4_ISFINITE(rate_i)) {
123  _rate_int(i) = math::constrain(rate_i, -_lim_int(i), _lim_int(i));
124  }
125  }
126 }
127 
129 {
130  rate_ctrl_status.rollspeed_integ = _rate_int(0);
131  rate_ctrl_status.pitchspeed_integ = _rate_int(1);
132  rate_ctrl_status.yawspeed_integ = _rate_int(2);
133 }
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
static struct vehicle_status_s status
Definition: Commander.cpp:138
PID 3 axis angular rate / angular velocity control.
matrix::Vector3f update(const matrix::Vector3f &rate, const matrix::Vector3f &rate_sp, const float dt, const bool landed)
Run one control loop cycle calculation.
Definition: RateControl.cpp:69
#define FLT_EPSILON
void setSaturationStatus(const MultirotorMixer::saturation_status &status)
Set saturation status.
Definition: RateControl.cpp:59
void setGains(const matrix::Vector3f &P, const matrix::Vector3f &I, const matrix::Vector3f &D)
Set the rate control gains.
Definition: RateControl.cpp:43
void setDTermCutoff(const float loop_rate, const float cutoff, const bool force)
Set update frequency and low-pass filter cutoff that is applied to the derivative term...
Definition: RateControl.cpp:50
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
void getRateControlStatus(rate_ctrl_status_s &rate_ctrl_status)
Get status message of controller for logging/debugging.
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
float dt
Definition: px4io.c:73
void updateIntegral(matrix::Vector3f &rate_error, const float dt)
Definition: RateControl.cpp:96
P[0][0]
Definition: quatCovMat.c:44
struct MultirotorMixer::saturation_status::@66 flags
Matrix< Type, M, N > emult(const Matrix< Type, M, N > &other) const
Definition: Matrix.hpp:157