Can anyone drive a car and a tank?

How many neurons and sensors does it take to drive a car?

The answer depends. It also depends on how you define “neuron”.

If the track has smooth curves, like the one below it actually works with 1 sensor (45 degrees to left) plus connecting the sensor to the output. No hidden neurons!

Did you get the answer right?

What it does is simply stay a fixed difference from the left. To be fair if you could only see like that you’d probably want to hug the left side but not too close.

Do more neurons lead to better behaviour?

That question refers to the cars, not that bigger-brained humans behave better. A neuron per sensor would make sense. The more sensors the faster it can safely go at faster speeds in my experience but the distance it sees is a major factor. This leaves you may be feeling a little empty too. Having 9 hidden layers of 20 neurons is not going to lead to a better car in my experience. It will however make the cars run slower (more computation) for no real gain.

Please do add comments below if you have a different opinion!

How can I use the trained AI to race?

You can’t, sorry. I am just as disappointed. I really wanted that next. In fact, I put them in a grid and tried, then gave up (for now).

Racing looks easy. I thought that given it avoids things if I give it sensors and enough neurons it will work. I was wrong.

The speed of the car is based on the input. It can speed up or slow down, but it hasn’t got a competitive brain. To overtake, you have to be confident that you can drive faster than the other car, and still stay on track when it comes to braking. This I’m afraid problem highlights the need for multiple neural circuits.

Firstly you would need a concept of (and implementation) of slip-stream – i.e. using the hole punched by the car in front to enable you to speed up (less wind resistance). You’d need to learn to not ram the car in front, this is not banger racing. That requires spotting a “gap” at an opportune time when you can pull alongside.

I am guessing you would want to be on the side where either you are able to take the bigger radius (outside of a curve) at a higher speed and have more bravado than the person you’re overtaking. Or you go up the inside and are able to stomp the brakes without locking them and forcing the other car to brake to avoid you. All whilst awareness of avoiding collision, as that isn’t conducive to not writing off your car.

There is a skill to it. Don’t ask me. I am not a racing driver.

Before folks point out that plenty of racing games do it, I know – I play them including Forza. I didn’t say I couldn’t code something to race. Simple neural networks aren’t going to work.

The solution requires more inputs (speed, grip, lateral g-force, a learnt car behaviour) and probably an idea of your opponent’s weaknesses/driving style. Learnt car behaviour goes beyond bias/weights, it’s about prediction: I believe at speed X I can keep the car on the road and have time to nip around, but more importantly, the other driver’s action.

It could be that all these things seem out of reach because I play with 7-parameter neural networks, not the billions OpenAI have.

Replacing AI with a simple formula

Given I am writing this, I am aware this is an AI/ML blog, so you must think this sounds like a crazy heading.

Yeah, but I will say something I said previously. “Use AI only when everything else failed“.

These tanks learnt to go around the track using just ONE sensor, and that is 1 input, 2 outputs (left/right throttle), with no hidden neurons.

Notice it started at the middle of the track width and then headed off to the outer edge, where it sat for the rest of the journey.

The formula for steering the tank (generated by the app in c:\temp\formula.txt) is this:

outputFromNeuralNetwork = new double[2];

/* throttle1 */ 
outputFromNeuralNetwork[0] = Math.Tanh( 0.28105000343202846*visionSensor[0] -0.07895000791177154);

/* throttle2 */ 
outputFromNeuralNetwork[1] = Math.Tanh( 0.013950000749900937*visionSensor[0] -0.003000000026077032);

As you read that you’re probably staring at it and thinking I have gone mad? Nope, although I wonder if we aren’t all a little bit crazy.

When I described the tank as having two throttles (left and write), none of you thought to ask about the physics around how that impacts the steering. So here is the tank steering “Dave” style.

// based on which throttle is higher we steer in the direction of the slower
AngleVehicleIsPointingInDegrees += (carInputState.Throttle2 - carInputState.Throttle1) / 2;

// if both are "1" we move top speed, anything else is less than.
Speed = (((carInputState.Throttle1 + carInputState.Throttle2) * 0.9F) / 2F);

Speed is proportional to the average of the throttles.

Angle is proportional to the difference in throttles, treated as degrees.

Taken literally as written, won’t turn enough and it would go slow. So we have modulation/amplifier values, as covered in the config section. It steers like this; the example amplifier being 50.

As is evident above that it tracks the left edge. But it still leads to interesting behaviour, like the route it took below… Every righthand curve seems to make the tank seems to go wide and at the bottom seemed to come dangerously close to the left.

But don’t think the formula it creates is identical every time in behaviour – the biases and weights can hugely affect the result. The following code is from one that stays roughly close to the middle of the track. I’ve picked this because it’s easier to explain the behaviour.

The sensor typically stays around 0.75 +/- 0.1.

outputFromNeuralNetwork = new double[2];

/* throttle 1 */ 
outputFromNeuralNetwork[0] = Math.Tanh( 0.262800008058548*visionSensor[0]-0.1936500072479248);

/* throttle 2 */ 
outputFromNeuralNetwork[1] = Math.Tanh( 0.0038500018417835236*visionSensor[0]+0);

Putting the formula into Excel allows you to see how it responds – it’s a simple linear relationship:

  • If the sensor returns approx 0.75 (because the tank stays a fixed distance) it rotates 0 (or 0.01 for that exact value).
  • If the tank deviates from straight, the sensor output (input to the neural network) changes to less or more. In response, a negative or positive angle is applied.
  • As a result, the tank steers itself to maintain a fixed distance.

What you’ve seen is that whether it’s tanks or cars, in a simple 2D universe it doesn’t take much brain power.

You can find the source code on GitHub.

I hope you found this post interesting, and that you have fun with the app. Please post your comments below.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *