/PID_control

My solution for PID Controller-Udacity’s Self-driving Car Nanodegree

Primary LanguageC++MIT LicenseMIT

My solution for CarND-Controls-PID project


Udacity - Self-Driving Car NanoDegree

Dependencies

Fellow students have put together a guide to Windows set-up for the project here if the environment you have set up for the Sensor Fusion projects does not work for this project. There's also an experimental patch for windows in this PR.

Basic Build Instructions

  1. Clone this repo.
  2. Make a build directory: mkdir build && cd build
  3. Compile: cmake .. && make
  4. Run it: ./pid.

Tips for setting up your environment can be found here

Editor Settings

We've purposefully kept editor configuration files out of this repo in order to keep it as simple and environment agnostic as possible. However, we recommend using the following settings:

  • indent using spaces
  • set tab width to 2 spaces (keeps the matrices in source code aligned)

Code Style

Please (do your best to) stick to Google's C++ style guide.


Project overview

PID control is technique to revise the behavior of vehicle such as steering angle and throttle value based on several P(propotional), I(integral) and D(differential) loss components, given the CTE (cross track error).

Take steering angle for example, it can be set by

$\mathrm{steer}=-K_pL_p-K_iL_i-K_d*L_d$

  • P component, directly minimize the CTE by setting it with a propotional factor, just using this term can make the real trajectory vary around the reference trajectory.
  • In order to avoid the above problem, D component takes effect. It minimizes the change between the two nearby points in the trajectory, which can smooth the real trajectory.
  • I component is to compensate the systematic bias.

With c++, I implement PID by:


PID::PID() {}

PID::~PID() {}

void PID::Init(double Kp_, double Ki_, double Kd_) {
  /**
   * TODO: Initialize PID coefficients (and errors, if needed)
   */

  this->Kp = Kp_;
  this->Ki = Ki_;
  this->Kd = Kd_;

  this->p_error = 0.0;
  this->d_error = 0.0;
  this->i_error = 0.0;

  this->prev_cte = 0.0;

}

void PID::UpdateError(double cte) {
  /**
   * TODO: Update PID errors based on cte.
   */

  this->p_error = cte;
  this->d_error = cte - this->prev_cte;
  this->i_error += cte;

  this->prev_cte = cte;

}

double PID::TotalError() {
  /**
   * TODO: Calculate and return the total error
   */

  double total_error = this->p_error + this->d_error + this->i_error;

  return total_error;  // TODO: Add your total error calc here!
}

double PID::CalcSteer() {

  double steer_angle = -this->Kp*this->p_error - this->Kd*this->d_error - this->Ki*this->i_error; 

  return steer_angle;


}

In order to initialize the proper parameter for the car to move, I first set the I component to zero. Then, I tune the P and D. After I make sure the car can successfully run 700 cycles in the simulator and I make twiddle algorithm to better finetune those parameters.

Twiddle

Twiddle algorithm is a proper parameter selection technique, which can minimize the error. The key idea is to tune each individual parameter by increasing and decreasing its values and observe the change of error. If either the direction can favors for the error minimization, the change rate of such direction should be enlarged, otherwise, decrease the change rate.

Below is the twiddle algorithm implemented for the simulator:

alt text

Result

alt text

Discussion

Bayesian optimization also comes into my mind of parameter tuning, I implement it with python for the robot example utilized in the lecture. I find it can give us a better parameter solution. Please have a check on my repo.