pid.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2014, Fetch Robotics Inc.
5  * Copyright (c) 2013, Unbounded Robotics Inc.
6  * Copyright (c) 2008, Willow Garage, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Unbounded Robotics nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *********************************************************************/
36 
37 /*
38  * Derived a bit from control_toolbox/pid.cpp
39  */
40 
41 #include <robot_controllers/pid.h>
42 #include <cmath>
43 
44 namespace robot_controllers
45 {
46 
47 PID::PID(double p, double i, double d, double i_max, double i_min) :
48  p_gain_(p),
49  i_gain_(i),
50  d_gain_(d),
51  i_max_(i_max),
52  i_min_(i_min)
53 {
54  reset();
55  checkGains();
56 }
57 
59  p_gain_(0.0),
60  i_gain_(0.0),
61  d_gain_(0.0),
62  i_max_(0.0),
63  i_min_(0.0)
64 {
65  reset();
66 }
67 
68 bool PID::init(const ros::NodeHandle &nh)
69 {
70  if (!nh.getParam("p", p_gain_))
71  {
72  // If P-gain is not specified, this often indicates wrong namespace was used
73  ROS_ERROR("No P gain sepcified. Parameter namespace %s", nh.getNamespace().c_str());
74  return false;
75  }
76 
77  nh.param("i", i_gain_, 0.0);
78  nh.param("d", d_gain_, 0.0);
79 
80  double i_clamp;
81  nh.param("i_clamp", i_clamp, 0.0);
82  i_max_ = std::abs(i_clamp);
83  i_min_ = -std::abs(i_clamp);
84 
85  // If i_min or i_max was specified use those values instead of i_clamp
86  nh.getParam("i_min", i_min_);
87  nh.getParam("i_max", i_max_);
88 
89  return checkGains();
90 }
91 
93 {
94  bool pass = true;
95  if (!std::isfinite(p_gain_))
96  {
97  ROS_WARN("Proportional gain is not finite");
98  p_gain_ = 0.0;
99  pass = false;
100  }
101  if (!std::isfinite(i_gain_))
102  {
103  ROS_WARN("Integral gain is not finite");
104  i_gain_ = 0.0;
105  pass = false;
106  }
107  if (!std::isfinite(d_gain_))
108  {
109  ROS_WARN("Derivative gain is not finite");
110  d_gain_ = 0.0;
111  pass = false;
112  }
113  if (!std::isfinite(i_max_) || !std::isfinite(i_min_))
114  {
115  ROS_WARN("Integral wind-up limit is not finite");
116  i_max_ = 0.0;
117  i_min_ = 0.0;
118  pass = false;
119  }
120  if (i_max_ < i_min_)
121  {
122  ROS_WARN("Integral max windup value is smaller than minimum value");
123  double tmp = i_max_;
124  i_max_ = i_min_;
125  i_min_ = tmp;
126  pass = false;
127  }
128  if ((i_min_==0) && (i_max_==0) && (i_gain_ != 0))
129  {
130  // It is easy to forgot to set a wind-up limit
131  ROS_WARN("Integral gain is non-zero, but integral wind-up limit is zero");
132  }
133  if ( ((i_min_ != 0) || (i_max_ != 0)) && (i_gain_ == 0) )
134  {
135  ROS_WARN("Integral gain is zero, but wind-yup limit is zero");
136  }
137  return pass;
138 }
139 
141 {
142  i_term_ = 0.0;
143  error_last_ = 0.0;
144 }
145 
146 double PID::update(double error, double dt)
147 {
148  double error_dot;
149  if (dt <= 0.0)
150  {
151  ROS_ERROR_THROTTLE(1.0, "PID::update : dt value is less than or equal to zero");
152  // if dt is zero is not possible to perform division
153  // in this case assume error_dot is zero and perform reset of calculation
154  error_dot = 0.0;
155  }
156  else
157  {
158  error_dot = (error-error_last_)/dt;
159  }
160  error_last_ = error;
161  return update(error, error_dot, dt);
162 }
163 
164 double PID::update(double error, double error_dot, double dt)
165 {
166  if (!std::isfinite(error) || !std::isfinite(error_dot) || !std::isfinite(dt))
167  {
168  ROS_ERROR_THROTTLE(1.0, "PID::update : input value is NaN or infinity");
169  return 0.0;
170  }
171 
172  if (dt <= 0.0)
173  {
174  ROS_ERROR_THROTTLE(1.0, "PID::update : dt value is less than or equal to zero");
175  dt = 0.0;
176  }
177 
178  double p_term = p_gain_*error;
179 
180  i_term_ += i_gain_ * error * dt;
181 
182  // apply wind-up limits to i_term
183  i_term_ = std::max(i_min_, std::min(i_term_, i_max_));
184 
185  double d_term = d_gain_ * error_dot;
186 
187  return p_term + i_term_ + d_term;
188 }
189 
190 } // namespace robot_controllers
PID()
Constructor. Starts all gains and limits at zero.
Definition: pid.cpp:58
double i_term_
integral wind-up term
Definition: pid.h:104
#define ROS_WARN(...)
bool checkGains()
Checks and fixes gain settings.
Definition: pid.cpp:92
#define ROS_ERROR_THROTTLE(rate,...)
double error_last_
Last error value, used for calculating error_dot when not provided.
Definition: pid.h:107
double update(double error, double dt)
Run PID calculation and return control result.
Definition: pid.cpp:146
bool param(const std::string &param_name, T &param_val, const T &default_val) const
const std::string & getNamespace() const
double i_max_
integral gain min and max limits
Definition: pid.h:101
void reset()
Reset integral wind-up term.
Definition: pid.cpp:140
bool getParam(const std::string &key, std::string &s) const
double p_gain_
proportial gain
Definition: pid.h:95
#define ROS_ERROR(...)
double i_gain_
integral gain
Definition: pid.h:97
bool init(const ros::NodeHandle &nh)
initialize gain settings from ROS parameter values
Definition: pid.cpp:68
double d_gain_
derivative gain
Definition: pid.h:99


robot_controllers
Author(s): Michael Ferguson
autogenerated on Sun Sep 27 2020 03:22:39