Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <hector_quadrotor_controller/pid.h>
00030 #include <limits>
00031
00032 namespace hector_quadrotor_controller {
00033
00034 PID::state::state()
00035 : p(std::numeric_limits<double>::quiet_NaN())
00036 , i(0.0)
00037 , d(std::numeric_limits<double>::quiet_NaN())
00038 , input(std::numeric_limits<double>::quiet_NaN())
00039 , dinput(0.0)
00040 , dx(std::numeric_limits<double>::quiet_NaN())
00041 {
00042 }
00043
00044 PID::parameters::parameters()
00045 : enabled(true)
00046 , time_constant(0.0)
00047 , k_p(0.0)
00048 , k_i(0.0)
00049 , k_d(0.0)
00050 , limit_i(std::numeric_limits<double>::quiet_NaN())
00051 , limit_output(std::numeric_limits<double>::quiet_NaN())
00052 {
00053 }
00054
00055 PID::PID()
00056 {}
00057
00058 PID::PID(const parameters& params)
00059 : parameters_(params)
00060 {}
00061
00062 PID::~PID()
00063 {}
00064
00065 void PID::init(const ros::NodeHandle ¶m_nh)
00066 {
00067 param_nh.getParam("enabled", parameters_.enabled);
00068 param_nh.getParam("k_p", parameters_.k_p);
00069 param_nh.getParam("k_i", parameters_.k_i);
00070 param_nh.getParam("k_d", parameters_.k_d);
00071 param_nh.getParam("limit_i", parameters_.limit_i);
00072 param_nh.getParam("limit_output", parameters_.limit_output);
00073 param_nh.getParam("time_constant", parameters_.time_constant);
00074 }
00075
00076 void PID::reset()
00077 {
00078 state_ = state();
00079 }
00080
00081 template <typename T> static inline T& checknan(T& value)
00082 {
00083 if (std::isnan(value)) value = T();
00084 return value;
00085 }
00086
00087 double PID::update(double input, double x, double dx, const ros::Duration& dt)
00088 {
00089 if (!parameters_.enabled) return 0.0;
00090 double dt_sec = dt.toSec();
00091
00092
00093 if (std::isnan(state_.input)) state_.input = input;
00094 if (dt_sec + parameters_.time_constant > 0.0) {
00095 state_.dinput = (input - state_.input) / (dt_sec + parameters_.time_constant);
00096 state_.input = (dt_sec * input + parameters_.time_constant * state_.input) / (dt_sec + parameters_.time_constant);
00097 }
00098
00099 return update(state_.input - x, dx, dt);
00100 }
00101
00102 double PID::update(double error, double dx, const ros::Duration& dt)
00103 {
00104 if (!parameters_.enabled) return 0.0;
00105 if (std::isnan(error)) return 0.0;
00106 double dt_sec = dt.toSec();
00107
00108
00109 state_.i += error * dt_sec;
00110 if (parameters_.limit_i > 0.0)
00111 {
00112 if (state_.i > parameters_.limit_i) state_.i = parameters_.limit_i;
00113 if (state_.i < -parameters_.limit_i) state_.i = -parameters_.limit_i;
00114 }
00115
00116
00117 if (dt_sec > 0.0 && !std::isnan(state_.p) && !std::isnan(state_.dx)) {
00118 state_.d = (error - state_.p) / dt_sec + state_.dx - dx;
00119 } else {
00120 state_.d = -dx;
00121 }
00122 state_.dx = dx;
00123
00124
00125 state_.p = error;
00126
00127
00128 double output = parameters_.k_p * state_.p + parameters_.k_i * state_.i + parameters_.k_d * state_.d;
00129 int antiwindup = 0;
00130 if (parameters_.limit_output > 0.0)
00131 {
00132 if (output > parameters_.limit_output) { output = parameters_.limit_output; antiwindup = 1; }
00133 if (output < -parameters_.limit_output) { output = -parameters_.limit_output; antiwindup = -1; }
00134 }
00135 if (antiwindup && (error * dt_sec * antiwindup > 0.0)) state_.i -= error * dt_sec;
00136
00137 checknan(output);
00138 return output;
00139 }
00140
00141 double PID::getFilteredControlError(double& filtered_error, double time_constant, const ros::Duration& dt)
00142 {
00143 double dt_sec = dt.toSec();
00144 filtered_error = checknan(filtered_error);
00145 if (dt_sec + time_constant > 0.0) {
00146 filtered_error = (time_constant * filtered_error + dt_sec * state_.p) / (dt_sec + time_constant);
00147 }
00148 return filtered_error;
00149 }
00150
00151 }
00152