pid.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *  Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2014, Fetch Robotics Inc.
00005  *  Copyright (c) 2013, Unbounded Robotics Inc.
00006  *  Copyright (c) 2008, Willow Garage, Inc.
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Unbounded Robotics nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *********************************************************************/
00036 
00037 /*
00038  * Derived a bit from control_toolbox/pid.cpp
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     // If P-gain is not specified, this often indicates wrong namespace was used
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   // If i_min or i_max was specified use those values instead of i_clamp
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     // It is easy to forgot to set a wind-up limit
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     // if dt is zero is not possible to perform division
00153     // in this case assume error_dot is zero and perform reset of calculation
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   // apply wind-up limits to i_term
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 }  // namespace robot_controllers


robot_controllers
Author(s): Michael Ferguson
autogenerated on Wed Jun 14 2017 04:09:10