Self-Driving Car Engineer Nanodegree Program
I implemented a PID controller with C++ for vehicle lane tracking in the simulator. The PID controller's parameters are automatically tuned by twiddle method.
The performance is not good enough, especially for the curve road tracking, it might be caused by the straight road is mainly used for training PID params at the beginning, and twiddle is stuck into local minimum. The performance can be better with larger running steps, but it would cost much more time. More sophicticated cost function (such as running distance on the track included) might also be useful otherwise using MSE to determine controller's performance. However, it has found PID parameters which can run a full lap.
The final parameters are shown as following
PID | Kp |
Ki |
Kd |
---|---|---|---|
Initiation | 0.1 | 0.01 | 1 |
Tuned params | 0.504175 | 0.000180134 | 4.54589 |
Twiddle | dKp |
dKi |
dKd |
---|---|---|---|
Initiation | 1 | 0.01 | 1 |
Final params | 0.0721396 | 0.000216406 | 0.0655811 |
Even though the vehicle can run a lap with the previous PID parameters, I modified them manually based on the previous results to gain a robust performance.
The final PID parameters are
PID | Kp |
Ki |
Kd |
---|---|---|---|
Tuned params | 0.3 | 0.000180134 | 4.54589 |
-
I firstly initialized PID parameters Kp, Ki and Kd with
[0.1, 0.01, 1]
from experience ofKp = 0.1*Kd, Ki = 0.1*Kp
. -
Then these parameters are tuned with twiddle method with
dp
of[1, 1, 1]
. However, I found thedp[1]
is too large forKi
.dp[1]
is always decreasing in the first 60 epochs. Hence, I reinitialized thedp
with[1, 0.01, 1]
for converging faster. -
After hundreds of simulator restarting, the final result indicates that we can manually set initial PID parameters and using small
dp
to fine tuning them. It would save a lot of time.
- The following code is used for automatic restarting simulator (found it on forum)
void reset_simulator(uWS::WebSocket<uWS::SERVER>& ws) {
std::string msg("42[\"reset\",{}]");
ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
}
- There are some unusual error feedback before simulator connected after using auto reset, a
if...else
is simply used to remove this.
if(n_iter>2)
{
PID and Twiddle...
}
- Twiddle method in Python code
def twiddle(tol=1e-10):
p = [0, 0, 0]
dp = [1, 1, 1]
robot = make_robot()
x_trajectory, y_trajectory, best_err = run(robot, p)
while best_err > tol:
for i in range(3):
p[i] += dp[i]
robot = make_robot()
x_trajectory, y_trajectory, err = run(robot, p)
if err < best_err:
best_err = err
dp[i] *= 1.1
else:
p[i] -= 2*dp[i]
robot = make_robot()
x_trajectory, y_trajectory, err = run(robot, p)
if err < best_err:
best_err = err
dp[i] *= 1.1
else:
p[i] += dp[i]
dp[i] *= 0.9
return p, best_err
Pseudo Twiddle Code by Sebastian Thrun.
- Clone this repo.
- Make a build directory:
mkdir build && cd build
- Compile:
cmake .. && make
- Run it:
./pid
.
Alternatively some scripts have been included to streamline this process, these can be leveraged by executing the following in the top directory of the project:
- ./clean.sh
- ./build.sh
- ./run.sh
- cmake >= 3.5
- All OSes: click here for installation instructions
- make >= 4.1(mac, linux), 3.81(Windows)
- Linux: make is installed by default on most Linux distros
- Mac: install Xcode command line tools to get make
- Windows: Click here for installation instructions
- gcc/g++ >= 5.4
- Linux: gcc / g++ is installed by default on most Linux distros
- Mac: same deal as make - [install Xcode command line tools]((https://developer.apple.com/xcode/features/)
- Windows: recommend using MinGW
- uWebSockets
- Run either
./install-mac.sh
or./install-ubuntu.sh
. - If you install from source, checkout to commit
e94b6e1
, i.e.git clone https://github.com/uWebSockets/uWebSockets cd uWebSockets git checkout e94b6e1
- Run either
- This project involves the Simulator which can be downloaded here