Self driving racing car, Oscar
Heavily interested in the work and development of Roborace, I decided to try and develop a little self driving car that could drive itself around any (flat) track, using Grasshopper3D.
This is the story of Oscar, the self driving racing car.
Before we start, I would like to point that this post is just about playing around, there is no major breakthrough. On the other hand, I entend to go more in detail and have already started to build a “slightly closer to real life” model. A lot of work has yet to be done before posting it here. This is my very first attempt in self driving car, and one of my first grasshopper model that uses a neural network.
This is not intended to be a tutorial… However, I do hope that you will find interest in the logic behind the scene and that it will bring you ideas for your own work.
Back to business !
This post will be organized in 8 chapters :
1 - Training track
2 - Automatic racing line
3 - Data & visualisation
4 - Training logic
5 - Training track
6 - Logic board
7 - Getting fancy
8 - Driving skills showcase !
Let’s start !
1 - Training track
This is the part were you can express the artist hiding deep down inside. There are plenty of manners to build your (flat) race track. As it wasn’t the point of this research, I decided to go for a simple planar curve that is then offset twice to produce a path. You might want to scale it down or up, depending on your units and the result you will get later, we will come back to this later.
Two important things to notice here : the track isn’t closed, and it finishes in the same direction as it started. This is to minimize the Oscar’s tendency to learn more how to turn one way better than the other. It is not entirely 100% correct, but it’s preferable to train him with this in mind.
2 - Automatic racing line
This clickbait-like title is a little bit of a lie. In this chapter we will see one way to make a basic (and actually not so good) approximation of what the racing line is on this track.
For this, lets grab back the simple planar curve (left previous picture), and evaluate its curvature at some parameters. For a better understanding, let’s pick a few of them.
We will talk now about the image on the right.
As you might have noticed : the bigger the radius, the larger the turn. Actually when the curve is straight (no curvature), the radius is infinitely big.
From this point, we simply use the points where the curve is being evaluated, and move it in the direction of the curvature. However for a tight turn, we want to move the point further than for a wider turn. This will get better results like in turn 2 and turn 6, with a double apex turn. When that is done, we construct a new nurb curve, and rebuild it, to make sure the trajectory is smooth.
The following GIF illustrates this badly explained process. It starts with the same amount of evaluated points than on th²e previous picture up to 200 points (in this example). The blue lines represent the track limits, and the black one the approximated racing line.
3 - Data & visualisation
Here we will discuss what kind of data Oscar will train on to be able to perform at (almost) any track.
The word almost is there for many reasons. I would call what where doing here as a very basic autopilot. The results depend on quite few manual settings and also on the training track the model has been trained on.
For this exercice, I decided to go for a simple sensor model. These would fire from the car, hit the boundary mesh of the track, and return the distance (for each sensor). The more sensors the model has, the more “aware” of its environment the model will be However, keep in mind that you’ll need more training data and that it will take more time to compute at each iteration on the testing track (at least for the model I’m showcasing here). In my tests, I usually went from 3 up to 11 sensors, but again, the results depend on so many parameters that this could actually be a bit irrelevant.
Here under the sensor model I came up with. The colours are actually just there for visualisation purposes. All the neural network component takes as input are values from 0 to 1. I’ll elaborate slightly more on that part a bit later down.
A tiny detail I’d like to point out is that not only the colours are automatically being created as more sensors get involved, but the brigthness of each colour depends on the perception of danger according to each sensors. This part is not visible in the last GIF, but will be in the further ones. Again, this serves as a nice way to display and show what will be going on as we run some simulations. This “notion of danger” colour scale is related to the training dataset that Oscar has been trained on.
4 - Training logic
In machine learning, there are two main difficulties : Choosing meaning full data & Collecting that data.
Choosing meaningful data means that the data should be relevant to what the model is trying to predict. Knowing the color of my socks won’t help any model trying to predict the forecast (duh).
Collecting the data can be difficult because a model most of the time requires a large amount of data to be able to be consistent, but it’s also a difficulty because the Human is lazy. In this case, one doesn’t want to populate the circuit with thousands of points and then manually input if Oscar (the car !) should go to the left, right or straight. I mean, I personally don’t… So we always want to find some ways to automate this process, while getting a good and exhaustive enough training dataset.
In order to automatically get the data for turning predictions, I came up with the following training logic (use the next gif as illustrated explanation) :
Evaluate the racing line curve at many parameters in order to get the tangent vectors (dark blue arrows)
For each vector, compare it’s direction to the direction of the next vector on the racing line (light blue arrows)
Cross product the first one with the second to get a third vector (pink arrows)
If that third vector points upward, Oscar should be turning left. If pointing downward, Oscar should be turning right
So there we go. From all the evaluations on the racing line curve, we have the values collected by the sensors (regardless their number), and we also have the turn prediction.
In other words for each evaluation of the curve, we have Oscar’s sight (values of the sensors), and the direction he should take in that situation.
The following gif shows all the cross product vectors on the training track. The number of points that need to be evaluated are depending on many parameters and will definitely influence the training and testing results. There is not really a best practice (or at least I didn’t ended up finding one), it’s more a trial and error workflow for me at this point.
As you might have noticed already, after calculating all the vectors, Oscar and I decided to unitized them (give them a length of 1). The reason for this is that it will provide better results as Oscar only needs to know if he should turn left or right. The turning value is to be set manually.
If you’ve paid full attention to the (following) gif, you might also have noticed that some vectors are collapsing on the ground. This is trying to teach Oscar that sometimes, he doesn’t need to turn, but can simply go straight; if the absolute value of a cross product isn’t high enough,that value is set to 0, otherwise is either to 1 or -1 depending on left or right.
Disclaimer : over-fitting vs generalization
Usually in machine learning, you not only want representative training datasets for the model to learn from, but you also want diversity in the training data. While the technique used and showed above gives us a decently representative dataset for the task we are teaching Oscar about, its diversity is quite poor. We could have used multiple training circuits, sharp turns, wide ones, more straight lines, …
Low diversity in the training data might end up in a over-fitting scenario, where the model is really good if the testing data is very similar to the training data. The model will very good on very specific cases only.
High diversity in the training data will create a more robust trained model, capable of a better adaptability in some cases where the testing data would differ (in a certain margin) from the original training data.
5 - Testing track
Now that all the training data is being collected analysed and labelled automatically, we need to talk about Oscar’s brain and the logic board that makes him drive around almost any track. But first, we need a testing track; a track that Oscar has never seen before (you got to trust me on this one).
On the picture bellow, in the middle, the training track (the only one Oscar has been trained on) with all the visible sensors rendered for each training evaluation. The red path is a test track on which Oscar will be tested on. I promise he hasn’t seen it before, trust me.
Oh look ! He’s ready to go !
6 - Logic board
Having the track created and Oscar ready to start his very first lap, I think it’s time to elaborate a bit more on the logic behind Oscar the self-driving racing car.
Oscar’s brain is made out of two main actions : Decision and Repetition.
Decision comes from the neural network component (pink group) from Lunchbox made by Proving ground. That is basically where all the magic happens. You feed the “Test” input with the current state of Oscar’s sensors, and based on what the neural network learned (“Inputs” associated with “Labels”), it will spit out a decision.
Repetition comes from Anemone made by Mateusz Zwierzycki, a plugin that allows loops inside of Grasshopper3D (weird blue groups). For every iteration, Oscar will move, create new sensor states, make a decision through the neural network component and then make a turn (or go straight). Anemone takes the updated position (after Oscar’s move) and updated direction (after Oscar’s rotation) and loop then so they become the inputs for the next iteration.
7 - Getting fancy
As you might have seen on my Instagram account, Oscar is a shapeshifter. Through his existence, he adopted many forms.
But at the beginning, Oscar is actually simply made of a single point, and a pointing vector. From there we create a plane around which we build our dream car.
Here under are some of the shapes the latest model could produce.
And yes, some of them are complete garbage (from a aerodynamic point of view only, obviously).
As this is some serious business internet blogpost (hum), I decided to pick the most “realistic” design, which also happen to be the most boring one.
Just before showing you the results, keep in mind that this is only :
8 - Driving skill showcase !
HERE WE ARE !
Thank you to bravest readers like you who made it this far ! I hope you are not disappointed (so far / yet) and that the results will live up to your expectations !
Did you remember? In the chapter 5, I introduced the racing test track. As this website host doesn’t allow for GIF files larger than 20Mo (bouh), we will have to focus on three turns carefully handpicked by myself from some of the most notorious turns.
As stated many times, Oscar has never seen this track before actually driving on it.
Here are the zooms from his very first and only lap of this magnificent racing track (yes, we can admit it).
What a mad man, seriously. This is truely amazing.
Here it is folks. This is the story of Oscar for now.
As I said in the very beginning of this never-ending post, I’ve already started a Oscar 2.0 but still very far away from posting anything yet. Different algorithms, different learning techniques, different way of turning and varying speed, … So who knows, you might live long enough to see a season 2.
I don’t really have any conclusions to draw from all this little experiment. This started as I was diving into machine learning applied to architecture + some guys actually building crazy self racing driving robots. My brain lagged and got lost in between the two. I just hope you found this interesting enough for the time you spent on reading.
Do not hesitate contacting me for more details or if you have any specific questions about this post, I’d be glad to provide them / answer those.
Thank you for your attention.
Antoine -