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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <robot_controllers/pid.h>
00042 #include <cmath>
00043
00044 namespace robot_controllers
00045 {
00046
00047 PID::PID(double p, double i, double d, double i_max, double i_min) :
00048 p_gain_(p),
00049 i_gain_(i),
00050 d_gain_(d),
00051 i_max_(i_max),
00052 i_min_(i_min)
00053 {
00054 reset();
00055 checkGains();
00056 }
00057
00058 PID::PID() :
00059 p_gain_(0.0),
00060 i_gain_(0.0),
00061 d_gain_(0.0),
00062 i_max_(0.0),
00063 i_min_(0.0)
00064 {
00065 reset();
00066 }
00067
00068 bool PID::init(const ros::NodeHandle &nh)
00069 {
00070 if (!nh.getParam("p", p_gain_))
00071 {
00072
00073 ROS_ERROR("No P gain sepcified. Parameter namespace %s", nh.getNamespace().c_str());
00074 return false;
00075 }
00076
00077 nh.param("i", i_gain_, 0.0);
00078 nh.param("d", d_gain_, 0.0);
00079
00080 double i_clamp;
00081 nh.param("i_clamp", i_clamp, 0.0);
00082 i_max_ = std::abs(i_clamp);
00083 i_min_ = -std::abs(i_clamp);
00084
00085
00086 nh.getParam("i_min", i_min_);
00087 nh.getParam("i_max", i_max_);
00088
00089 return checkGains();
00090 }
00091
00092 bool PID::checkGains()
00093 {
00094 bool pass = true;
00095 if (!std::isfinite(p_gain_))
00096 {
00097 ROS_WARN("Proportional gain is not finite");
00098 p_gain_ = 0.0;
00099 pass = false;
00100 }
00101 if (!std::isfinite(i_gain_))
00102 {
00103 ROS_WARN("Integral gain is not finite");
00104 i_gain_ = 0.0;
00105 pass = false;
00106 }
00107 if (!std::isfinite(d_gain_))
00108 {
00109 ROS_WARN("Derivative gain is not finite");
00110 d_gain_ = 0.0;
00111 pass = false;
00112 }
00113 if (!std::isfinite(i_max_) || !std::isfinite(i_min_))
00114 {
00115 ROS_WARN("Integral wind-up limit is not finite");
00116 i_max_ = 0.0;
00117 i_min_ = 0.0;
00118 pass = false;
00119 }
00120 if (i_max_ < i_min_)
00121 {
00122 ROS_WARN("Integral max windup value is smaller than minimum value");
00123 double tmp = i_max_;
00124 i_max_ = i_min_;
00125 i_min_ = tmp;
00126 pass = false;
00127 }
00128 if ((i_min_==0) && (i_max_==0) && (i_gain_ != 0))
00129 {
00130
00131 ROS_WARN("Integral gain is non-zero, but integral wind-up limit is zero");
00132 }
00133 if ( ((i_min_ != 0) || (i_max_ != 0)) && (i_gain_ == 0) )
00134 {
00135 ROS_WARN("Integral gain is zero, but wind-yup limit is zero");
00136 }
00137 return pass;
00138 }
00139
00140 void PID::reset()
00141 {
00142 i_term_ = 0.0;
00143 error_last_ = 0.0;
00144 }
00145
00146 double PID::update(double error, double dt)
00147 {
00148 double error_dot;
00149 if (dt <= 0.0)
00150 {
00151 ROS_ERROR_THROTTLE(1.0, "PID::update : dt value is less than or equal to zero");
00152
00153
00154 error_dot = 0.0;
00155 }
00156 else
00157 {
00158 error_dot = (error-error_last_)/dt;
00159 }
00160 error_last_ = error;
00161 return update(error, error_dot, dt);
00162 }
00163
00164 double PID::update(double error, double error_dot, double dt)
00165 {
00166 if (!std::isfinite(error) || !std::isfinite(error_dot) || !std::isfinite(dt))
00167 {
00168 ROS_ERROR_THROTTLE(1.0, "PID::update : input value is NaN or infinity");
00169 return 0.0;
00170 }
00171
00172 if (dt <= 0.0)
00173 {
00174 ROS_ERROR_THROTTLE(1.0, "PID::update : dt value is less than or equal to zero");
00175 dt = 0.0;
00176 }
00177
00178 double p_term = p_gain_*error;
00179
00180 i_term_ += i_gain_ * error * dt;
00181
00182
00183 i_term_ = std::max(i_min_, std::min(i_term_, i_max_));
00184
00185 double d_term = d_gain_ * error_dot;
00186
00187 return p_term + i_term_ + d_term;
00188 }
00189
00190 }