odom_control.cpp
Go to the documentation of this file.
1 #include <ctime>
2 #include <vector>
3 #include <string>
4 #include <cmath>
5 #include <fstream>
6 #include <iostream>
7 #include "ros/ros.h"
8 
11 
12 namespace openrover
13 {
14 void OdomControl::start(bool use_control, PidGains pid_gains, int max, int min)
15 {
16  K_P_ = pid_gains.Kp;
17  K_I_ = pid_gains.Ki;
18  K_D_ = pid_gains.Kd;
19 }
20 
24  , MOTOR_DEADBAND_(9)
25  , MAX_ACCEL_CUTOFF_(20.0)
26  , MIN_VELOCITY_(0.03)
27  , MAX_VELOCITY_(5)
28  , K_P_(0)
29  , K_I_(0)
30  , K_D_(0)
31  , velocity_history_(3, 0)
32  , use_control_(false)
33  , skip_measurement_(false)
34  , at_max_motor_speed_(false)
35  , at_min_motor_speed_(false)
36 {
37 }
38 
39 OdomControl::OdomControl(bool use_control, PidGains pid_gains, int max, int min, std::string log_filename)
40  : MOTOR_MAX_(max)
41  , MOTOR_MIN_(min)
42  , MOTOR_DEADBAND_(9)
43  , MAX_ACCEL_CUTOFF_(20.0)
44  , MIN_VELOCITY_(0.03)
45  , MAX_VELOCITY_(3)
46  , enable_file_logging_(false) // not implemented
47  , log_filename_(log_filename)
48  , K_P_(pid_gains.Kp)
49  , K_I_(pid_gains.Ki)
50  , K_D_(pid_gains.Kd)
51  , velocity_history_(3, 0)
52  , use_control_(use_control)
53  , skip_measurement_(false)
54  , at_max_motor_speed_(false)
55  , at_min_motor_speed_(false)
56 {
57 }
58 
59 OdomControl::OdomControl(bool use_control, PidGains pid_gains, int max, int min)
60  : MOTOR_MAX_(max)
61  , MOTOR_MIN_(min)
62  , MOTOR_DEADBAND_(9)
63  , MAX_ACCEL_CUTOFF_(20.0)
64  , MIN_VELOCITY_(0.03)
65  , MAX_VELOCITY_(3)
66  , enable_file_logging_(false) // not implemented
67  , K_P_(pid_gains.Kp)
68  , K_I_(pid_gains.Ki)
69  , K_D_(pid_gains.Kd)
70  , velocity_history_(3, 0)
71  , use_control_(use_control)
72  , skip_measurement_(false)
73  , at_max_motor_speed_(false)
74  , at_min_motor_speed_(false)
75  , stop_integrating_(false)
76  , velocity_error_(0)
77  , integral_value_(0)
81 {
82  ROS_INFO("odom Kp: %f", K_P_);
83  ROS_INFO("odom Ki: %f", K_I_);
84 }
85 
86 unsigned char OdomControl::run(bool e_stop_on, bool control_on, double commanded_vel, double measured_vel, double dt)
87 {
88  velocity_commanded_ = commanded_vel;
89  velocity_measured_ = measured_vel;
90  velocity_filtered_ = filter(measured_vel, dt);
91 
92  //If rover is E-Stopped, respond with NEUTRAL comman
93  if (e_stop_on)
94  {
95  reset();
96  return MOTOR_NEUTRAL;
97  }
98 
99  // If stopping, stop now when velocity has slowed.
100  if ((commanded_vel == 0.0) && (fabs(velocity_filtered_)<0.3))
101  {
102  integral_value_ = 0;
104  {
105  return MOTOR_NEUTRAL;
106  }
107  }
108 
109  // If controller should be ON, run it.
110  if (control_on)
111  {
112  velocity_error_ = commanded_vel - velocity_filtered_;
113  if (!skip_measurement_)
114  {
116  ROS_DEBUG("PID: %i", motor_speed_);
117  }
118  }
119  else
120  {
122  }
123 
125 
126  return (unsigned char)motor_speed_;
127 }
128 
130 {
131  return (int)round(velocity_commanded_ * 50 + MOTOR_NEUTRAL);
132 }
133 
135 {
136  integral_value_ = 0;
137  velocity_error_ = 0;
139  velocity_measured_ = 0;
140  velocity_filtered_ = 0;
141  std::fill(velocity_history_.begin(), velocity_history_.end(), 0);
143  skip_measurement_ = false;
144 }
145 
146 int OdomControl::PID(double error, double dt)
147 {
148  double p_val = P(error, dt);
149  double i_val = I(error, dt);
150  double d_val = D(error, dt);
151  double pid_val = p_val + i_val + d_val;
152  ROS_DEBUG("\nerror: %lf\n dt: %lf", error, dt);
153  ROS_DEBUG("\n kp: %lf \n ki: %lf \n kd: %lf \n", p_val, i_val, d_val);
154 
155  if (fabs(pid_val) > (MOTOR_MAX_/2.0))
156  //Only integrate if the motor's aren't already at full speed
157  {
158  stop_integrating_ = true;
159  }
160  else
161  {
162  stop_integrating_ = false;
163  }
164 
165  return (int)round(pid_val + 125.0);
166 }
167 
168 double OdomControl::D(double error, double dt)
169 {
170  return K_D_ * (velocity_history_[0] - velocity_history_[1]) / dt;
171 }
172 
173 double OdomControl::I(double error, double dt)
174 {
175  if (!stop_integrating_)
176  {
177  integral_value_ += (K_I_ * error) * dt;
178  }
179  return integral_value_;
180 }
181 
182 double OdomControl::P(double error, double dt)
183 {
184  double p_val = error * K_P_;
185  return error * K_P_;
186 }
187 
188 bool OdomControl::hasZeroHistory(const std::vector<double>& vel_history)
189 {
190  double avg = (fabs(vel_history[0]) + fabs(vel_history[1]) + fabs(vel_history[2])) / 3.0;
191  if (avg < 0.03)
192  return true;
193  else
194  return false;
195 }
196 
197 int OdomControl::boundMotorSpeed(int motor_speed, int max, int min)
198 {
199  at_max_motor_speed_ = false;
200  at_min_motor_speed_ = false;
201 
202  if (motor_speed > max)
203  {
204  motor_speed = max;
205  at_max_motor_speed_ = true;
206  }
207  if (motor_speed < min)
208  {
209  motor_speed = min;
210  at_min_motor_speed_ = true;
211  }
212 
213  return motor_speed;
214 }
215 
216 int OdomControl::deadbandOffset(int motor_speed, int deadband_offset)
217 {
218  // Compensate for deadband
219  if (motor_speed > MOTOR_NEUTRAL)
220  {
221  return (motor_speed + deadband_offset);
222  }
223  else if (motor_speed < MOTOR_NEUTRAL)
224  {
225  return (motor_speed - deadband_offset);
226  }
227 }
228 
229 double OdomControl::filter(double velocity, double dt)
230 {
231  static double time = 0;
232  float change_in_velocity = 0;
233 
234  // Check for impossible acceleration, if it is impossible, ignore the measurement.
235  float accel = (velocity - velocity_history_[0]) / dt;
236 
237  if (accel > MAX_ACCEL_CUTOFF_)
238  {
239  change_in_velocity = dt*MAX_ACCEL_CUTOFF_;
240  velocity = velocity_history_[0] + change_in_velocity;
241  }
242  else if (accel < -MAX_ACCEL_CUTOFF_)
243  {
244  change_in_velocity = -dt*MAX_ACCEL_CUTOFF_;
245  velocity = velocity_history_[0] + change_in_velocity;
246  }
247 
248 // Hanning low pass filter filter
249 velocity_filtered_ = 0.25 * velocity + 0.5 * velocity_history_[0] + 0.25 * velocity_history_[1];
251 velocity_history_.pop_back();
252 
253  return velocity_filtered_;
254 }
255 
256 
257 } // namespace openrover
bool hasZeroHistory(const std::vector< double > &vel_history)
const double MIN_VELOCITY_
int deadbandOffset(int motor_speed, int deadband_offset)
double D(double error, double dt)
std::vector< double > velocity_history_
int PID(double error, double dt)
const double MAX_VELOCITY_
int boundMotorSpeed(int motor_speed, int max, int min)
double I(double error, double dt)
const int MOTOR_SPEED_MAX
Definition: constants.hpp:55
#define ROS_INFO(...)
void start(bool use_control, PidGains pid_gains, int max, int min)
const int MOTOR_NEUTRAL
Definition: constants.hpp:54
double P(double error, double dt)
double filter(double left_motor_vel, double dt)
unsigned char run(bool e_stop_on, bool control_on, double commanded_vel, double measured_vel, double dt)
const double MAX_ACCEL_CUTOFF_
const int MOTOR_SPEED_MIN
Definition: constants.hpp:56
#define ROS_DEBUG(...)


rr_openrover_basic
Author(s): Jack Kilian
autogenerated on Fri Jan 17 2020 03:18:17