The objective for this project was to make a behavior planning module and a trajectory generator to steer the car in highway driving. The challenge lies in the requirements:
Safety first: we have to keep an eye on our environment to make sure we react appropriately to other cars
Fast: within legal limits, overtake other cars if necessary
Comfortable: passengers should be comfortable with the acceleration and jerk, our trajectory planner should keep these variables under certain limits
We have at our disposal information about our position and our environment (data about other vehicles in our direction). We provide the simulator a list of coordinates to be visited at regular intervals (Thus also speeds and accelerations).
The project boils down to solving three problems:
Behaviour planner: take decisions about changing lanes and determine maximum speeds.
Trajectory planner: based on the directives from the behaviour planner, create a good trajectory that respects all constraints.
Interface with the simulator: there are some artificial difficulties which arise from the clunky interface to the simulator, i.e. faulty coordinate conversions.
This was one of the coolest parts of the course, since it is in this project that we can really shape the way the car interacts with its environment. Below a video showing my results:
In this project the task is to program a Model Predictive Controller which is able to drive the car around the track, with the difficulty of having a latency of about 100ms to simulate delays in the network and the time until the actuators engage.
The inputs to the MPC are:
Waypoints, approximated by a third degree polynomial.
Car status: position, orientation, speed, and current state of the actuators
MPC uses a model to predict future states based on actuators input and tries to find a series of actuators inputs which minimizes a cost function. The model can be kinematic or dynamic, but I used a simple kinematic model for this project. The selection of MPC parameters and cost function are key to having a capable and stable controller. The cost function I defined is based on factors such as:
Reduce position and orientation error w.r.t. the waypoints trajectory
Keep a reference speed
Reduce actuator use
Reduce actuator derivatives, i.e. no sudden changes
The optimizer (a C++ library) is fed the discretized kinematic equations, constraints and the cost function. It is important to balance the number of steps and the time step for good and timely performance.
I tuned the cost function for the MPC to be able to drive up to 80mph. Video performance below. Yellow line in the video are waypoints, green line is the solution from the MPC.
It is nice to explore another “simple” controller which can safely drive the car (in the simulator at least!) but it also showcases the need of self-driving cars to integrate several systems into one coordinated unit. This method is dependant on dynamic information (Waypoints) and it disregards most of its environment. I hope part 3 of the self-driving car nanodegree will feature some kind of “integration” scenario where different systems have to be combined to give the car some autonomy, rather than mere automation.
In this project, a simulator is giving us the state of the car with respect to a predefined path around the circuit in terms of:
cross track error: how far the car is from the circuit
orientation error: the angle between the car’s orientation and the tangent to the path.
The mission for our controller is to give steering and throttle commands to drive safely and as fast as possible around the circuit.
Implementing the PID controller is straightforward, tuning its gains however is not and can get very tedious.
I programmed the twiddle algorithm to tune the gains for me. Twiddle is an algorithm that alters the parameter by a small amount each iteration, and checks if the error is smaller. If that is the case, it will change the parameter by a bigger amount the next time. If not, it will reduce the amount of change. It will iterate over the parameters making a couple trials for each of them, ad infinitum. This is easy to program and can find a local optimum.
Since the controller behaves differently depending on the speed, I first trained it on a speed function which set low speeds, and then gradually increased the speed.
The speed function is basically an on-off controller coupled to a “desired speed” function. The “desired speed” is selected in linear dependence of the cross track error like this:
The speed stays constant for CTE greater than 2, so that the car keeps moving even when it has deviated from the path.
In this project we implemented a particle filter. The goal is to locate a driving car based on a map which contains landmarks and the feedback from on-board sensors.
Particle filters are very intuitive and easy to implement. The drawback is speed and, I guess, difficulty to use in real situations. In a real life implementation it would be necessary to decide what is a landmark and to be able to tell if the feedback form the sensors corresponds to a landmark in the map or not.
This video shows the performance of the filter within the simulator provided by Udacity:
In this challenge, we control a car whose mission is to catch another car. Both cars have the same maximum speed. We have a radar and lidar to feed our Unscented Kalman Filter and track and predict the other car. Almost like the plot to Fast & Furious saga.
In this project, we improved upon the Extended Kalman Filter by using a non-linear model which is better prepared to deal with complex movement patterns. This means the RMSE is going to be lower and our predictions more accurate. It also means the steps are more complex and the added complexity layers hinder a natural understanding of intermediate results. Debugging is not easy!
This table shows the comparison between Unscented using one or two sensors and Extended using two sensors:
Using the Unscented filter required to tune two parameters, the process noises standard deviations of linear and angular acceleration. To guide us in the process we calculated Normalized Innovation Squared values and compared them with the 95% confidence of the corresponding Chi Square distribution. This is the result for the final tuned version of my project:
This video shows the performance of the Unscented Kalman Filter in the same task we used to evaluate the Extended one:
In this project we programmed an Extended Kalman Filter in C++.
The filter performs sensor fusion of Radar and Lidar data, using a non-linear model for the update of radar data. In the video below, radar and lidar data is represented by red and blue dots. The predictions of the filter are shown as green dots.
It was a relatively easy project, since Udacity gave all the framework required for the programming task. Nonetheless, a good warm up for the more advanced topics this term.