pid.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2013, Johannes Meyer, TU Darmstadt
3 // 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 are met:
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Flight Systems and Automatic Control group,
13 // TU Darmstadt, nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
30 #include <limits>
31 
33 
35  : p(std::numeric_limits<double>::quiet_NaN())
36  , i(0.0)
37  , d(std::numeric_limits<double>::quiet_NaN())
38  , input(std::numeric_limits<double>::quiet_NaN())
39  , dinput(0.0)
40  , dx(std::numeric_limits<double>::quiet_NaN())
41 {
42 }
43 
45  : enabled(true)
46  , time_constant(0.0)
47  , k_p(0.0)
48  , k_i(0.0)
49  , k_d(0.0)
50  , limit_i(std::numeric_limits<double>::quiet_NaN())
51  , limit_output(std::numeric_limits<double>::quiet_NaN())
52 {
53 }
54 
56 {}
57 
58 PID::PID(const parameters& params)
59  : parameters_(params)
60 {}
61 
63 {}
64 
65 void PID::init(const ros::NodeHandle &param_nh)
66 {
67  param_nh.getParam("enabled", parameters_.enabled);
68  param_nh.getParam("k_p", parameters_.k_p);
69  param_nh.getParam("k_i", parameters_.k_i);
70  param_nh.getParam("k_d", parameters_.k_d);
71  param_nh.getParam("limit_i", parameters_.limit_i);
72  param_nh.getParam("limit_output", parameters_.limit_output);
73  param_nh.getParam("time_constant", parameters_.time_constant);
74 }
75 
76 void PID::reset()
77 {
78  state_ = state();
79 }
80 
81 template <typename T> static inline T& checknan(T& value)
82 {
83  if (std::isnan(value)) value = T();
84  return value;
85 }
86 
87 double PID::update(double input, double x, double dx, const ros::Duration& dt)
88 {
89  if (!parameters_.enabled) return 0.0;
90  double dt_sec = dt.toSec();
91 
92  // low-pass filter input
93  if (std::isnan(state_.input)) state_.input = input;
94  if (dt_sec + parameters_.time_constant > 0.0) {
95  state_.dinput = (input - state_.input) / (dt_sec + parameters_.time_constant);
96  state_.input = (dt_sec * input + parameters_.time_constant * state_.input) / (dt_sec + parameters_.time_constant);
97  }
98 
99  return update(state_.input - x, dx, dt);
100 }
101 
102 double PID::update(double error, double dx, const ros::Duration& dt)
103 {
104  if (!parameters_.enabled) return 0.0;
105  if (std::isnan(error)) return 0.0;
106  double dt_sec = dt.toSec();
107 
108  // integral error
109  state_.i += error * dt_sec;
110  if (parameters_.limit_i > 0.0)
111  {
114  }
115 
116  // differential error
117  if (dt_sec > 0.0 && !std::isnan(state_.p) && !std::isnan(state_.dx)) {
118  state_.d = (error - state_.p) / dt_sec + state_.dx - dx;
119  } else {
120  state_.d = -dx;
121  }
122  state_.dx = dx;
123 
124  // proportional error
125  state_.p = error;
126 
127  // calculate output...
128  double output = parameters_.k_p * state_.p + parameters_.k_i * state_.i + parameters_.k_d * state_.d;
129  int antiwindup = 0;
130  if (parameters_.limit_output > 0.0)
131  {
132  if (output > parameters_.limit_output) { output = parameters_.limit_output; antiwindup = 1; }
133  if (output < -parameters_.limit_output) { output = -parameters_.limit_output; antiwindup = -1; }
134  }
135  if (antiwindup && (error * dt_sec * antiwindup > 0.0)) state_.i -= error * dt_sec;
136 
137  checknan(output);
138  return output;
139 }
140 
141 double PID::getFilteredControlError(double& filtered_error, double time_constant, const ros::Duration& dt)
142 {
143  double dt_sec = dt.toSec();
144  filtered_error = checknan(filtered_error);
145  if (dt_sec + time_constant > 0.0) {
146  filtered_error = (time_constant * filtered_error + dt_sec * state_.p) / (dt_sec + time_constant);
147  }
148  return filtered_error;
149 }
150 
151 } // namespace hector_quadrotor_controller
152 
d
struct hector_quadrotor_controller::PID::parameters parameters_
static T & checknan(T &value)
Definition: pid.cpp:81
void init(const ros::NodeHandle &param_nh)
Definition: pid.cpp:65
double update(double input, double x, double dx, const ros::Duration &dt)
Definition: pid.cpp:87
bool getParam(const std::string &key, std::string &s) const
struct hector_quadrotor_controller::PID::state state_
double getFilteredControlError(double &filtered_error, double time_constant, const ros::Duration &dt)
Definition: pid.cpp:141


hector_quadrotor_controller
Author(s): Johannes Meyer
autogenerated on Sun Jul 10 2016 04:30:48