The online racing simulator
The inputs from LFS are running as fast as it LFS lets me, so I get approximately 100 updates a second about the car information, and I have added a some prediction to this to attempt to smooth it a little more when there are bigger delays between packets...

The low FPS of the sensors is a big concern, certainly, and it would make it hard to drive. I've actually driven a handful of laps using only the view available from the AIRS screen- I can't hit near PB times as there is some lag between the game and the update, but it was reasonable.

The racing line computation, as it stands right this moment, is creating a geometric racing line. Meaning it is pretty much the smoothest path while remaining in the borders specified by the track edges. I won't get as detailed to do per car, or per setup racing lines, however I would like to take another pass at the racing line in the future to attempt to add "sacrificial corners" or to change the apex. As in, taking the geometric line through a corner is reasonable for fair laps, but taking a later apex should help enter a long straight with more speed.

EDIT: Yea that graphic looks pretty neat. You are spot on with the faster it goes the more difficult it is to drive and control. There are a few things the driver needs to learn, (be told how to deal with via programming), in order to drive faster. Among the first of those, it to be able to see/plan for further ahead the faster he goes. Right now it is programmed to aim for a spot about 20 meters in front of the car and has a temporary "look ahead" point on the racing line of about 60 or 70 meters in front of the car. The braking is dependent on the angles, but he needs to look ahead further than that when going faster.

That and I need to teach the driver how to actually use the Prediction Unit more in order to understand the "limit" of the car and to predict. Such that, if the prediction unit shows the car is going to go off track, SLOW DOWN. If the prediction unit shows an oversteer situation, handle it appropriately. Etc.
Just opened up the AIRS project again, decided I tracks should be easier to create and a bit more accurate. So instead of using line segments for the track edges, I am attempting to create a bezier curve that lies along the points represented by the track edges.

Using a curve will allow a much higher level of accuracy as well. The primary reason for doing this is due to the failure of my attempt to add AS1R as a driveable track. Well it wasn't a complete failure but it was made much more difficult than it needed to be. One of the line segments had turned TOO sharply so the centerline algorithm could not find the other track edge correctly. (The perpendicular line went down the front stretch). It took nearly half a day to track it down and correct it as I wasn't able to just move the cone in the layout file - that seemed to reorder the cone and mess up the entire layout file as AIRS would be expecting the cones in order.

So, by converting the points into a curve it should remove that possibility entirely and allow the layout to be created with FAR fewer cones, making it easier. Also by doing this, I have the option to give the AI driver direct access to this curve, or to create N number of reference points around the edges to be tested against, or both. It also means I will be able to use the mathematics of a curve to represent the centerline and the racingline.

Unfortunately, this involves redoing a bit of work that I've already got completed, but hopefully it will make things a lot better overall, certainly easier for a new track.
This is an image of adding curves to handle the track edges, center line and racing line. You can clearly see the better precision the curve math will have, but the major benefit and driving force of this improvement is for adding tracks easier.

Lines vs Curve

Although the Curve is visible it is still quite a bit of work to make the Reference Point manager use curves completely. But once it does that will be great.
I want all of that! I've always hated the blocky nature of the PTH files and the CMX files. It would be nice to apply this to the pth parser, so that I can generate some higher quality images.
Dygear - Not sure if you are familiar with C++ much or not, but once I finish my basic "Curve" object I will upload the class header and source and from there you, and others, can use it how they wish.

The class currently:

Makes a curve from a set of points along the curve.
Allows you to make a container of points from the given curve.
Estimates the total distance. (Estimation only because it is a curve and the more steps the more accurate the estimate but it will never be exact).
Quote from blackbird04217 :Dygear - Not sure if you are familiar with C++ much or not, but once I finish my basic "Curve" object I will upload the class header and source and from there you, and others, can use it how they wish.

The class currently:

Makes a curve from a set of points along the curve.
Allows you to make a container of points from the given curve.
Estimates the total distance. (Estimation only because it is a curve and the more steps the more accurate the estimate but it will never be exact).

If you give me the source code, I'm sure I can translate it to PHP. Thank you for the assistance.
Quote from blackbird04217 :That and I need to teach the driver how to actually use the Prediction Unit more in order to understand the "limit" of the car and to predict. Such that, if the prediction unit shows the car is going to go off track, SLOW DOWN. If the prediction unit shows an oversteer situation, handle it appropriately. Etc.

I think LFS skidpad might be interessting for that:
Have the AI drive in circle with constant speed.


Slowly increase the speed until it is over the grip limit and AI has to actually predict.
Or watch the output of predicition unit as speed increases and compare it with what actually happens.

I think such "isolated tests" could speed up testing because it is easier to create the situations that you want to test.
LFS skippad also has those painted rings, so if you set AI path on one of the rings it is easy to see how good it can follow etc.

Other basic test could be slalom: Can compare how excact it goes around the cones and if further down the course the mistakes maybe add up.

Another test could be to place some curbs (or other objects) to purposely unbalance the car and see if AI can recover.
Ahh, yea. Now that is a grand idea. I think setting up one layout around the autocross circuit would be great, then I could put the drive into a car with a understeer induced setup until he can control that situation, then put him into an oversteer inducing setup until that is also handled.

Then move to the autocross and setup the ultimate "practice" layout with two most of a circle turns, one tighter than the other, linked by two, (or more), slaloms, one slow one faster, could prove useful for getting the driver to handle different car conditions.

This will still require me to get the prediction unit working at the appropriate level so the driver can actually understand what the car is doing.
Dygear; The files are far from complete, however, here I will share them in their current state. I added a little documentation where things were not yet implemented, but it should be enough to get you started.

EDIT: After a little bit of actual testing I've found that isLoop is actually not completing the loop like I expected. Glad I setup a test kit for this...



I am trying to implement a way to get normals and tangents from any point along the curved path to actually make use of the curves in the racing project. Gutholz; I will swing back around to your idea of a practice layout on the autocross area once I get the curves ready. Otherwise making new track layouts is much more painful than it should be.
Attached files
bezier_curve.zip - 2.7 KB - 380 views
Okay, in my test kit I figured out what I was doing wrong with the tangents.

Screenshot here

I still have to clean up the code in the bezier curve. Dygear, if you are planning to use it, the above zip has a few quarks about it that I was silly about. (In particular in the Curve Section structure, A is the start, B is the end and C / D are control points. I am going to modify it to be A as the start, D as the end and B and C as the controls. As well as test the isLooping more, and implement the non-looping mode too.
I used hermite splines in the VRC AI years ago. I don't think I used tangent/forward vectors and normals, but they shouldn't be too hard to estimate from hermite splines because two of the four inputs are forward vectors to begin with. Anyway, that could be an option for you if it turns out to be too hard to do with the Beziers.
I actually got it working. I am not 100% sure the "normal" is correct for a curve, but it will work for all situations I can think I'll ever want, (normal = cross product of UP and tangent). Basically I may have cheated a bit there, but it will work for my needs.

It isn't a video but it isn't hard to imagine what the video would look like, this is my testing application for the curves and it seems to be working pretty well:
Screenshot 1
Screenshot 2
Screenshot 3

Ignore the two red dots in the first screenshot, I was attempting to take multiple screens quickly, but it failed.

NOTE: I've actually added the application, it doesn't have a proper timer so it may run SUPER fast or SUPER slow for you, but running it allows you to see it in motion, if you care that much.

So I think that is working better, now to put it back in the AI project and multiple steps to make the center line computations use the curve, then the racing line computations... Ughf.
Attached files
curve_testing.zip - 32.9 KB - 398 views
Quote from blackbird04217 :Dygear; The files are far from complete, however, here I will share them in their current state. I added a little documentation where things were not yet implemented, but it should be enough to get you started.

Nice! Thank you, when I get some time in the next few years I'll translate that into PHP.
The dynamic_vehicle.exe runs so fast, it almost looks like just flickering
But interessting to see parts like this. Is there any keys/way to move the points?

For the track coordinates, you still place pylons by hand? Maybe this is another way: track images in svg format.
https://www.lfsforum.net/showt ... php?p=1594577#post1594577
Since svg is textbased, all the coordinates are in readable format in the vector file. Just need to parse them somehow and reduce their amount...
Yea Gutholz, like I mentioned it doesn't have a proper timer yet.

I am still placing it by hand, but with the curves it makes this process much better and eliminates any problems I had in the past. Still takes time to make new tracks, but it isn't too bad.

I actually started a basic track for the autocross area, and I will continue working on that a bit until I'm happy with it, although the project is taking a bit of a back burner or still low priority with other things in life taking my attention.
Good weekend to all,

Well, it is a good weekend for the Artificial Driver. I am not sure whether or not they want to remain anonymous or not, so I will err on the side of caution until I know otherwise - someone generously gave the AI driver an S2 license.

This means we can now track his mileage, personal best laps, fuel used, and ... you can actually see him if I get a server setup. I actually just set one up on my local machine, however port forwarding has always eluded me and the world may not be able to connect. His LFS user name is: airs_artificial_driver

I'll reach out to some people to see if they want to lend a server, to allow anyone to actually visit - if they so wish - during the development to watch the artificial driver live.

I've also been thinking about giving the AI a single state to allow for "learning". I will still be programming logical states, but I will take a look into how hard and complex it actually might be to create and apply a learning algorithm. My thought was to input car speed, engine speed, car gear, etc etc... car position, input positions, and most importantly the 5 to 10 points ahead of the driver that are on the racing line.

The outputs obviously would be the control positions. I don't know how this would work exactly, as I've never actually implemented a learning algorithm and still think it'd be too complex for the scope of the project, but maybe a side project within. For scoring how well the learning is doing I would take some distance/time parameter of the desired and actual course followed. The closer the actual course is to the desired course - along with the faster overall movement, the better.

I'm not focusing on that right now. But will at least peak into create a learning state just for playing around with....

Back to the current plan....

Now that the AI can join a server, I'd like to be able to change tracks a lot, LOT, easier than I can currently. Currently I must adjust some code to allow the Racing Line to be computed, wait 5 to 10 minutes while it optimizes the geometric racing line, then outputs that to the file which I then paste into the code and adjust the code so it doesn't compute the racing line next time...

The plan is to save out the racing line and other reference points into a file that can be loaded quickly, with version identifier so if I ever modify how the racing line is computed (I do plan to in the future) it will update the file.

Also planned, is to get the artificial driver to be able to drive/shift the cars with a sequential gearbox - which shouldn't be terribly hard, but currently he only does H-shifter. He may not be able to drive the MRT only because it would require some extra logic for first gear to shift down from neutral, and no reverse, but I maybe?

So if you want to check out the progress live, try finding the user: airs_artificial_driver

Warning: The driver may not always be online. The driver may be sitting on the grid, spectating, or stopped in the course for large chunks of time as I tweak or write more code. The driver will not respond, but if I am around and see you join I will attempt to get him running. He is not competitive at this time, and will not pay attention to the location of another car.
This sounds interesting.
I should have seen that one coming... Having a few issues converting the Reference Point Manager (which contains the track edges, center line and racing line), to use curves for these instead of a container of points...

The first issue is nearly everything wants a container of points, not a curve... I tried to take a short cut by converting the curve to points, but funny enough, by doing that the data gets too dense for no benefit. Drastically slows the loading process.

I should have seen that coming.

In other news, the driver can, mostly theoretically, shift a sequential gear box, although watching him drive the XRR nearly killed me as he couldn't get the car moving. Stalls every time, so needs to be a little more aggressive with launching that car, all cars really as I haven't yet done that logic.
There are times when programming can just beat you up. I spent a large portion of my weekend working on the AI project, I did make a little progress, but not nearly as much as I desired. The reference point manager will now save a "processed" file to disk including the track edges, center line, racing line, etc. This drastically increases load time and I no longer need to do the ugly code changing/copy file contents hacks in order to change tracks.

However in the process of doing that I ran into troubles left and right. Finally got it working. The next step planned was to break down the curve by estimated segment lengths, which is actually not working as expected. I'm still debugging that portion of code. I will eventually need to save that in the processed information also.

I've done a bit of reading on neural networks and am still at a loss of how to go about implementing this. In some manner it sounds pretty straight forward, a set of inputs, random weights, a set of outputs.... How that will help the AI drive at all is so far above my head I stopped searching for the moment.

I need to section the curve by length for an optimization, I also need to find the point on the curve that is closest to the drivers position, which is actually a very troublesome problem it appears, and my math knowledge at this time is unfortunately too low, need to level that up a bit. I do have ways to make it work, but it will be slower and slightly less accurate - the accuracy in this particular situation shouldn't effect much, it is essentially the "drive to point" on the racing line.

Once I get that curve broken down for the optimization, I should be able to get the driver to look further ahead and realize when he is on a straight section, and maybe improve his logic a bit from what it is now. It is actually miraculous that he can drive a high 1:09.92 at FE1 in the XRG. I realize that is not a special or fast time by any means, but his logic is pretty dumb at the moment.

EDIT: So I've finally have the ability to [u]roughly[/i] break down the curve based on a distance from start. I went ahead and tried using this without the optimized lookup table, and it actually works... for the first third of FE1. So now I need to process the curve into a more optimized structure like I was expecting but hoping I didn't need to do.

I am still running into the same issues with the memory/prediction units that I had a few months ago. I'm not sure the artificial driver will be able to rely on using the prediction unit for determining over steer / understeer or "at the limit" like I had previously planned and hoped for.

Just added a little bit of code so that instead of always looking 20 meters ahead, the artificial driver will now look from 10 meters to more than 40 meters ahead depending on vehicle speed. This has not proven to help lap times yet, because with the performance issues for two thirds of the track the artificial driver weaves back and forth over correcting like a maniac... Caused by low sample/simulation rates, not of LFS).


A little later. . .

So, I have succeeded!! In making the artificial driver [u]even slower!!![/u] His best laps around FE1 are now in the mid 1:23s... Awesome. I was attempting to change the way he used the throttle and brake, attempting to make him a little smoother. It is tricky though, I certainly need to find a better way to perform this logic. Currently I'm using angles of points along the racing line, essentially a tighter radius turn results in higher angles and using this I've been attempting to modify the throttle/braking inputs. With little success.

Obviously there is more to just the radius of the turn to take into account, such as over/under steer. But this is very similar to the approach I had previously and yet working so much worse. Maybe it was simply better to treat the throttle a little more like an on/off switch... Let me try making him have a heavier foot.


Backing up a bit...

I've now added a new supported track for the AI drive, I use the term track loosely. It is actually the skidpad.



The prediction and memory units are still having troubles and I've temporarily run out of ideas on how to solve that. I am going to attempt to use the skidpad and maybe an autocross layout, if I can figure out how to do a multiple lap playout, to with any luck create the logic to sort out if the car is at the limit, and if not, push harder... As well as get it back under control if it is over... This will be challenging to say the least and at this moment I don't know exactly where to begin.
I just went through the entire thread, skimming along the old posts and spikes of progress over the years. It certainly seems that 2009 was mostly tossing ideas around, a lot of very long winded posts. 2010 I kicked it up with some prototyping and threw together the first replays of the artificial driver driving with a virtual controller, of which now throw OOS errors. After an extended break and some refactoring of the initial code, 2013 comes back in for the challenge of creating a racing line, given only the left and right edges of the track. Fairly successfully.

Then since the beginning of 2014, by far the most improvements and progress has happened. Created the Visual Sensor, Car Sensor, Physical Sensor by gathering all possible information from LiveForSpeed, The Memory Unit and Prediction Unit looks amazing in their video, - unfortunately they don't behave quite as awesome despite a lot of effort trying to make it work.

The artificial driver now has an S2 license and the current personal best for FE1 with the XRG is a 1:09:920 however with the changes today (see the post above) this is no longer his current time as he lost speed... Ughf.

I am reaching a point where I need to gather thoughts and find an angle to attack this project from. In some way it would be nice for the AI driver to learn, and ANN's have appeared many times throughout the thread, I'm still unconvinced it would be worth doing, or really even how to fully implement. I've seen multiple implementations for pattern recognition or such, but it doesn't quite click how it would be used in this particular situation.

It is easy to see the inputs would come from the sensors, visual, physical, car and maybe even a "desired path" (probably a portion of the racing line, though with room to modify).

//-----------------------

Then I go back to one of the fundamental ideas of the project, and I realize I have strayed slightly. The driver is using the Visual Sensor and reference points for detecting his position, but he should be using them to signal when to brake, turn and exit a corner. This is, of course, much easier said than done.
Quote from blackbird04217 :I need to section the curve by length for an optimization, I also need to find the point on the curve that is closest to the drivers position, which is actually a very troublesome problem it appears, and my math knowledge at this time is unfortunately too low, need to level that up a bit.

You're talking about a tangent point here, basically. Indeed, there may not be a way to compute this exactly (I could never figure it out either), but you might be able to get a reasonably good estimation by doing some iterations. I've never worked with Bezier curves so can't help you there, but with Hermites the input was basically a value from 0 to 1 representing the normalized distance between the two end points on the curve, which would spit out an x/y point that is actually on that curve.

That's not the exact point you're looking for but most of the time might be close enough. That could be extended into an iterative scheme where you score that x/y point by comparing it to the car's actual position, then trying another value (for the 0-1 input part) based on that. An easy way to do it would be simple bisection where you just start at 0.5 (or some better approximation), then either go to 0.25 or 0.75, then if it was 0.25 then you go half way between 0.25 and 0.5, etc., cutting it in half each time. Eventually if you get a point on the curve hopefully that you can do a computation on that says "this point is close enough" and just use that as the closest point on the curve. It won't be perfect, but neither will the steering/brake/throttle algos, so it probably won't matter. "Close enough" can get you a long way.

Quote from blackbird04217 :Just added a little bit of code so that instead of always looking 20 meters ahead, the artificial driver will now look from 10 meters to more than 40 meters ahead depending on vehicle speed. This has not proven to help lap times yet, because with the performance issues for two thirds of the track the artificial driver weaves back and forth over correcting like a maniac... Caused by low sample/simulation rates, not of LFS).

That's how my VRC code worked too if I remember right. Conceptually I was imagining the AI asking "where will I be x seconds from now," then using that point on the curve as a target of sorts. Same thing you're doing in principle, really. To stop the weaving I had to add a damping term to the steering algorithm that used the left/right velocity toward or away from the path. This wasn't real hard to tune either, there was a pretty wide range that worked reasonably well and would stop the weaving. If necessary you could also code in some hard limits, say if the distance is really big (after a crash or whatever) then it might not damp it at all, things like that.

So basically it was something very roughly like this:

steeringAngle = someConstant1 * (desiredCarHeading - actualCarHeading) + someConstant2 * velocityTangentOfPath

You could also add in power constants to tune this more, something like this:

steeringAngle = someConstant1 * (desiredCarHeading - actualCarHeading)^somePowerConstant1 + someConstant2 * abs(velocityTangentOfPath)^somePowerConstant2 * sign(velocityTangentOfPath)

Then there were more terms added to deal with other nearby cars, basically. I think in the actual code I ended up breaking these all into separate terms to clean it up so in the end I could just go like this:

term1 = something
term2 = somethingElse
term3 = somethingElseAgain
steeringAngle = term1 + term2 + term3

That kind of thing.

Regarding throttle, each of my curve's node points had a target speed for the car which was recorded by my own driving in slow motion attempting to do perfect laps. This could be scaled up and down a bit for difficulty levels that the user chooses and worked very well so long as the car was actually capable of making the turns at those speeds.

Throttle was then a simple matter of doing something like this:

throttle = someThrottleConstant * (desiredCarSpeed - carSpeed)

Or using a power constant something like this:

throttle = someThrottleConstant * abs((desiredCarSpeed - carSpeed))^somePowerConstant * sign(desiredCarSpeed - carSpeed)


Neural networks

What I have above is probably pretty similar to what you have. You might have even more terms than this, but I just wanted to show you the basic approach and thinking that worked quite well in VRC back in the day. What a neural network does is turns those equations basically into a black box, so your curve and whatever other information you want goes in on one side while throttle and steering come out on the other. The trouble with this is you can't just tuned it all by hand like you can with the other approach which is a simple matter of adjusting the constants and observing what they do to the car. Instead you really have to let it just learn by itself by trial and error.

If you get interested in this I might be able to point you in the right direction. Most of the stuff on ANN's online is unnecessarily complicated for this kind of task. There's all kinds of learning algorithms, back propagation and so on, discussions about how to limit the weights and initialize them, on and on, but really there are much easier ways to get good enough results and much of that can be ignored in the end for an application like this, so don't let it intimidate you. I hardly understand half the ANN stuff I've read. When I experimented briefly with an ANN driven car, I initialized weights with totally random values, unrestricted (not necessarily between -1 and 1 or 0 and 1 or whatever), then just used a particle swarm algorithm to adjust the weights using a very simple fitness scoring mechanism:

In the beginning before the cars were smart enough to drive a lap:

fitnessScore = distanceTravelledAlongPath

Then once they were smart enough to lap the whole circuit, it was changed to something like this:

fitnessScore = 1 / laptime

So the faster an ANN went, the better score it received and the weights of all the ANN's in the system were shifted a little bit in that direction via the particle swarm algorithm rather than some enormously complicated backprop nonsense. Rinse, wash, repeat, and the ANN's all evolve to become really fast. It worked pretty well.

One neat thing about this is that you can in priniciple use any kind of inputs you want, vehicle slip angle, understeer gradient, yaw velocity, etc., maybe even the previous cycle's steering and throttle could be inputs too, in addition to whatever path information you want to use. You can add so much stuff that a human would never be able to try and write a useful equation such as in the non-ANN case and tune all the constants. You let evolution take care of it instead because it often does a far better job than a human ever could, and it does it much faster.

It's also really fun to watch the learning process evolve. Even if it doesn't work as well as you hope, it's a fascinating thing to see and gets you really thinking about real biological evolution.

Another way to do the weights in the ANN is to use a genetic algorithm. I've tried this too in an ANN, but not for a car driver. I think a particle swarm system will probably work better in the end anyway, and it's a lot easier to write and wrap your head around. KISS.
Yea the attempt of looking ahead is to get the AI driver to start braking as a turn is approaching. I am trying to avoid giving the driver the information about throttle/brake or speeds information by recording my own (or using WR).

The ANN stuff does scare me a bit with the "unknown" "magic" black-box. I understand it comes down to the training algorithm and unfortunately by using LiveForSpeed I am limited to real-time so I can't really fast forward, or use a swarm of any sort. The best thing I can see doing for the fitness routine is a full lap, or at least most of a lap.

I admit it would be neat to watch the AI driver learn how to drive, and hopefully, learn to get faster and faster. But you hit the nail on the head - it removes and ability to control it. My idea here was to feed in several points ahead of the driver (in driver/car space) and make the ANN take control of the throttle/brake/steering (shifting could be handled logically) and try to follow the given line.

This way when I decide to add other cars, or pit lane, the same algorithm can be used, and all that I need to change is the desired line for the car to follow. That was my concept anyway. It might even be possible to train the driver this way by using sections and the fitness be a function of how closely the last 100 meters was to the desired inputs.

Still unsure about using an ANN though since training it could be tricky and it can't be modified later, might be neat to watch.
The look-ahead also helped the swerving oscillations in my case by having a point out ahead of the car to aim for. I found that the further this point was ahead of the car, the lower the oscillations. I imagine you've seen this in your own work. Try setting it to 0 look-ahead distance and watch the mahem that ensues.

I don't think you should jump into ANN's right away. Instead you probably ought to go ahead with the hard coded stuff for awhile like you're doing now so you get a feel for what ideas for control work well, what inputs might be useful and not, that kind of thing. Conceptually you need a good idea how the system is working of course, and for me the best way to go about that in the beginning is to try and do it all manually. Once I find myself thinking "if only the cars could automatically do this or that in order to come up with a good number for this variable and that one in order to tune my constants without me having to do anything," that's the time to start looking at ANNs. Also when you want to include a lot more variables than your brainpower will let you write a hard coded system for, ANNs can be a good solution. They can solve really complicated problems that humans can't really wrap their minds around. I'm fairly sure that's how facial/speech recognition software and all that kind of stuff works, and there's currently a competition project for the CERN particle accelerator to process their data to find Higgs bosons that uses machine learning. There's no way to write stuff like that manually probably.

Back to the ANN racing AI: Since I wrote the physics engine I could do whatever I wanted including running things in fast forward which just sped up the process. It would still work without that of course, it'd just take longer. It might be a deal where you just let the AI evolve overnight or have it doing all this on a separate machine while you check on it every hour or so to see how it's going.

In the original VRC that had the hard coded type of AI (not ANNs, that was done years later as an experiment that was never finished/released), I had some extra windows open with the constants so I could change the numbers while the cars were driving around. That worked well enough to make a commercial product with it and there weren't really very many constants. There were just enough so that I knew what each of them did, and by playing with them I got a feel for the numbers and could tune things well enough.

The swarm stuff: The way I did it, each "particle" in a swarm was an entire ANN. During a training session there were multiple ANN's evolving. You only need one car to do a particle swarm with multiple ANNs. I just swapped in and out the different ANNs into one vehicle after it finished a cycle (i.e., completed a lap or two or maybe ran for some fixed time period in the initial phase before they could do complete laps). So it was only one car on the track every time that was using one ANN, then switching to the next ANN, etc.. After all the ANNs had taken their turn, it would adjust the weights and start over.

What I did need to do though in the first phase before they were smart enough to run a lap was be able to reset the car positions/speeds and so on to some initial condition for the next ANN run. If you can have the software do that in LFS automatically then you might be good to go. It might also be possible to train the AI on a recorded run at first just so they could start the main learning process already able to do laps, but for me it seemed like a lot more work and wasn't really necessary, so I never bothered with that.

BTW, I don't think ANNs are particularly common in racing AI, so if it ends up turning you off, I wouldn't worry about it too much. One can make a pretty good AI without letting things go to the abstract black box level with ANNs. Just because it's an ANN doesn't necessarily mean it will be better than a well thought out traditional AI anyway.

If you do ever get to ANN's, let me know and maybe I can help out with some of the details. I've enjoyed watching you post on all this over the years and seeing it develop. I'd be happy to have some correspondence with you on this if you get stuck or want to bounce ideas off someone that's done it before.
I just remembered something. This was all so long ago, maybe ten or twelve years, that I'm not totally sure what I ended up doing in the final product, but I distinctly remember a phase in developing the hard coded type of AI for VRC (not ANNs) where I tried to let the AI evolve its own throttle/braking algorithms so that it was actually learning on its own to an extent.

One of things I think I tried was setting the default throttle position to 100% so they were at full throttle all the time. With my hand tuned steering algorithm the car speeds would be too high to make it around most of the corners. IIRC, I detected this by checking the car position to see if it was too far off the path (prerecorded lines in my case). If it was, it tried again with less throttle, then less still, eventually adding some braking, etc.. This did eventually work and the cars could eventually lap the track at a reasonable speed, but it not nearly as fast as they could using prerecorded target speeds that were sometimes processed a bit more. It was interesting anyway and was my first attempt at doing an actual learning algorithm that was much simpler than an ANN.

In the "recorded target speed" system that went into the final product, I think I also had a conditional throttle algorithm that would go to 100% throttle if the car was going slower than the target speed. So you can try little tricks like this to speed up the cars more. However, in my case it was a little bit simpler. For that system I cheated a little bit with the tires, giving the rear tires enough grip that the AI could do anything it wanted with the steering and throttle and the cars would never spin, that kind of thing. In your case you'll have to work a lot harder than I did. However, the ANNs didn't need to cheat at all with the physics. They could handle an extremely loose car amazingly well, better than a human, and learn that in a matter of minutes.

The trouble you might find is that there are so many variables involved at that point with the slip angles of the tires or car and so on, that hard coding a solution for all that, let alone coming up with the myriad of constants for it, might prove a lot more difficult and time consuming than learning to do ANNs and writing a system for it. ANNs can be an enormous time saver once you've got them set up. They can do all the hard work while you sleep, really.
Increasing the distance of the point the artificial driver aimed at made him tend to cut corners a bit more, and essentially hit the tires in the chicane or the tall curbing on the sharp 90 degree turn. Although you are correct looking too closely on a straight tends to make the driver wobble from left to right as it goes beyond the desired direction. Interestingly, I tried solving this problem much earlier in development by interpolating the actual steering input in a smooth step or inverse squared manner.

Essentially the idea was that the closer the driver already is to the desired direction, the less he would steer towards it in a non-linear fashion. This sounded pretty intuitive to me at the time, however it resulted in the artificial driver turning in far later than he should, because it takes longer for his steering angle to actually increase, I decided to remove that and simply steer linearly.

I'm taking a break from the project currently to do some other things in life, but it is only a matter of time before I get some thoughts jumping and wanting to be tested. It is really unfortunate that I can't get the predictions to be smooth enough for actual usage. I was hoping to get the artificial driver to change the inputs based on the predicted position/direction and desired direction/position. Theoretically, this will automatically look further ahead when travelling at speed and should, also theoretically, reduce weaving/wobble on a straight. I do see a slight potential that it could actually make the wobble worse.

I may work on a very small, two-dimensional racer project just to try out the genetic algorithms and possibly ANNs, they sound neat in concept, and it also sounds like one of those very rewarding things to create. Watching the cars get a little better would be super neat. I will not be using true physics in this project. That is actually quite advanced. I may simulate the engine, clutch, gearbox properly, but that force will then just move the vehicle forward, and turning will simply rotate the vehicle instead of applying torque with the front wheels and adhering to the ground with friction. Simplifying everything only to play around with learning algorithms.

FGED GREDG RDFGDR GSFDG