Interesting, I've actually already got BL1 done, although during the test something did go wrong in the chicane area so I should be able to move reference points and fix that issue now. So that would is a grand idea dawesdust_12. If anyone else has suggestions I've actually got layouts started/made for: FE1, BL1, AS1R and I think AS2.
Also I tried a few different cars last night for fun, and it shows how little the artificial driver knows about driving at the limits. The current algorithm looks at several points on the racing line that are ahead of the driver to determine braking. The driver attempts to enter a turn at some speed (I think 40mph?) depending on how tight it turns. So watching him drive in the FZR was quite comical as he could go twice the speed around the turns. Hopefully the new algorithm will be better and adapt to other cars better: I'll have to remember to make the reference points change based on the car driven.
Gutholz let me get it tested right quick and get back to you with some more details. You might already have the fe1_airs_lr.lyt since you were on the server which you could use as reference, but essentially I placed cones approximately 15-30 meters apart or so (closer on the turns, further on the straights). With the new distance thing you will need to make sure the first cones are closer going the correct way around the track, I haven't yet tried using fe1 for fe1r yet, in theory it could work just changing the meaning of left and right edges but that remains untested.
Server is going up soon for a little bit of development tonight.
EDIT: From my experimenting with the dragstrip this "find the nearest" might not be so great. I admit though the drag strip is a very unusual case, and I wasn't using the return road correctly, but you can see here the nearest cone is jumping across to the return side.
It didn't take much to fix that particular issue, just add more cones that need to be deceivingly close together, but then another issue returned which is because of the hairpin like turns the algorithm for detecting the center line has an issue where it can't always find the edge. Lets put it this way: Making tracks for this AI Driver is still not as easy as I was hoping for. I've given up on this portion for now, sorry Gutholz I know you were looking to make a layout or or two and help out. If you feel up to it you can still try to, but I'd choose one that doesn't have very sharp turns because these give the AI some troubles, I need to work on a debugger for this but I don't want to at this moment in time.
He seems to be doing pretty good on AS1R so I'll run him there for a bit for a change of scenery.
Now for my next trick, since I'll stop playing with the tracks for the time being, I want to give the driver information about the track in a different way. For long time readers of the project you may remember I wanted to use reference points for driving much like a human would. If nobody noticed, I sort of didn't do that as completely as initially desired. (I used the left/right edge track reference points to create a racing line). Now I will take that racing line and create several points of interest for the driver to distinguish between straights and corners.
A straight will be defined as a section of the racing line where no two nodes exceed some threshold angle for some minimum distance where as a turn will be almost anything else.
Each turn will have several bits of information:
- A reference point for the entry of the turn.
- A reference point for the exit of the turn.
- A reference point for the brake point.
- At least one reference point for the apex*.
*The first left/right chicane in FE1 will likely be defined by this all as 1 turn but will have 2 apex reference points. Not entirely sure how the algorithm will determine each of the apex points at this time, or even if that is really needed. (The braking point, entrance and exit points are certainly needed though the driver should change behavior after passing the last apex since that should basically be the throttle out quickly point).
I've said it a few times but I've recently began running the artificial driver in other cars, just to get a feeling for differences, and boy are there many differences.
First it is IMPORTANT to realize that the current logic has been based fairly drastically on the XRG at FE1. Some of the variables that I KNOW are hardcoded for this combo are things including braking distances, speed in turns of certain angles (35-40mph) and various others. Actually just changing to a different setup in the XRG can make the artificial driver fail like a fish out of water. Seriously. This is one major reason I want to change the logic to be less hard coded and more "feeling of the limit" not to mention that is one of the underlying goals of this project.
So with the current, hardcoded and simple, driving logic I've been watching how it performs with other cars and trying to figure out the "whys". This way when I plan and write the new "at the limit" driving logic I can have ideas about what needs to change per car or even things to keep in mind.
So far in all my testing the airs_artificial_driver has been fastest in the FZ5 with a mid/high 55 something. You can check all times for the driver on LFS world, username: airs_artificial_driver. This time was set without ABS and a lot of locked tires. Current hardcoded logic just slams on the brakes and expects the car to have ABS for threshold braking. Interestingly in the FZ5 turning ABS on will cause a spin when braking on the back straight, the rear end gets loose and winds up in front so the driver prefers to kill the tires. I believe the FZ5 is so fast because it weighs a lot and takes a long time to slow down but still doesn't drive over the limit, too much, and has the power to really accelerate out still.
The FZR was quite amusing to watch as well, I'm not sure what the time was but this car makes it extremely clear the artificial driver has no concept of tire limits because it is excruciatingly slow through the turns at 35 to 40mph. I was practically screaming "go faster" during each turn because the slicks have much more grip available.
I also recently added sequential shifting to the shifting logic so I could try out the single seaters, and well, that was disappointing. Quite like the FZR the driver never got near the limit of the car. The BF1 brought up another very interesting problem I'll need to keep in mind - not all cars have the same steering setup. What I mean by this is the AI driver rarely turns the steering wheel to full lock, and in some tight turns the single seaters (particularly BF1) requires this because they have a limited range. Essentially the artificial driver plows the BF1 into the tire stack in the chicane because he didn't turn sharp enough. Amusing, yes. Fast - no.
Then there was the UF1 test, I figured this couldn't possibly end badly with a car so slow grandma can drive it. Well surprise surprise. The artificial driver doesn't shift properly. What I mean by this is because of some hardcoded logic the driver slowly shifts up to fourth gear about as expected, but then never downshifts. Instead stays in fourth gear the entire time. The problem with the hardcoded value is the tachometer reading never gets a certain percentage below the engine speed with max torque, so the downshift threshold is never reached. I'm sure he would down shift if the car was stopped for some reason, but he doesn't while driving. Yet another thing to keep an eye for. I may need to have different values for each car.
Finally I've put the driver in the LX4 and a new problem came shining through, clutch wear/temperature. As of now the artificial driver has been shifting with very VERY basic logic. Clutch in 100%, shift to gear, once gear is engaged, clutch out. This means the driving logic was controlling the throttle during the shift and generally meant for a full throttle, no lift, upshift. Which was working flawlessly for the XRG with a stronger clutch.
I have now changed the shifting mechanism a little bit so that it now controls the throttle while the driver is attempting to shift. It takes 30 to 50 milliseconds to fully press the clutch and release the throttle, then shift to gear and once engaged it will take 200 to 250 milliseconds to release the clutch and press the throttle. With one exception, if the engine speed drops near engine idle speed it will then press the throttle fully, this isn't perfect, but I found that otherwise he would stall when starting from a stop and shifting into first.
This change now has me wanting to do some heel-and-toe down-shifting. The driver isn't losing control, but a keen eye will notice the traction breaks away at the drive wheels during a down shift because the driver isn't very smooth. Also the shifting logic still needs to be modified slightly to detect up or down shift. The new logic with applying throttle will occur even on a downshift, something that is obviously not desired when attempting to brake for a corner. The driving logic will quickly correct it, but that is still ~0.1 seconds with more than half throttle while trying to stop the car.
It is quite neat to watch the different cars and learn these little things. For instance when testing the "at the limit" logic for acceleration the BF1 without traction control will prove very useful, possibly the same car would be useful for testing the braking threshold, but I suspect that the FZ5 might be better due to the tendency to get loose at the rear. Still not sure how I will detect "under, at or over the limit" for these different conditions, (braking, accelerating, turning), but hopefully I'll figure something out.
One last thing, this isn't specific to just car changes, for instance at BL1 the artificial driver had an issue in some cars not being able to stay on track at the end of the long straight. Although there is currently an issue with the track layout somewhere in the chicane. I wish creating tracks was easier, but I don't want to spend more time on making it easier, so for now I will stick with FE1.
It is quite difficult to see this in a screenshot, and this shot was taken before the apex point was added, but I've got the driver to figure out the braking point, turn-in point apex and exit of the corners in FE1. It might need slight adjustment but it seems to work, for the most part. Some of the corners are connected, such as the final chicane and final turn all counts as a single turn to the algorithm because there was no straight section along the racing line for a long enough time.
If anyone even cares about the technical details, here is essentially what I did to figure out these points.
First I found the starting and ending node of the first corner. I defined a threshold angle of 2 degrees, and if a node along the racing line angled more than this amount to its previous and next nodes it would count as a corner. Simply finding the first of them gives the starting point of the first corner. The ending point of the first corner continued until I found multiple nodes together that were detected as straight, I think minimum distance was set to 50 meters.
From here I go from the end of the corner until I find the start of the next, then find the end of that one, and then the start of the next and then the end until the start of the next is the same point as the start of the first corner. Essentially finding the entry and exit positions of all the corners.
The braking is not perfect by any means, and it could be a little smarter so I may do so in the future, but currently it starts at each corners entry point and walks backward along the racing line 50 to 80 meters and plops down the braking point. The overall idea is to have the driver keep track of this point in his memory and modify it depending on how the car is behaving. If it was easy to reach the target entry speed, the brake point can be moved closer - etc. The initial placement could be smarter though, as I could check how long the straight before the corner is and make longer braking areas for longer straights - assuming here that the driver will be going faster on these straights than the shorter ones, needing more time to brake for target speed.
Finally the tricky bit, which I admit didn't work out quite as well as I was hoping for but such is life and I will let it be as it is until I find a better idea. The apex point of the corner. I realize some corners can have multiple apex points, but for the artificial driver I was going to have a single apex - even for chicanes. Essentially I'm using the apex point as the point in which it should be safe to start speeding out of the corner towards the exit.
With this loose definition it made sense, intuitively to me, to start at the exit point of the corner and work backwards along the racing line. While working backwards monitor the distance from the racing line to the INSIDE edge of the corner. At the exit the racing line should be near the outside of the track so as this distance decreases keep walking backwards. Once it increases, stop! Step forward slightly and that would be the apex.
This sounds reasonable in my head, but for turn one the exit is actually near that side of the corner because after T1 and before the chicane the track is constantly turning even though it is sort of a mini straight as far as racing is concerned. Otherwise, the chicane apex and far back turn worked flawlessly. The final turn apex looks a little later than one would expect, but not terrible for an automatic corner detector. I haven't yet run this on other tracks, but I am looking forward to getting the driver to understand the different sections of the track and change the driving logic to drive at the limit instead of how it is currently with drive by wire.
I don't really have much to show and tell this time around, but I have been busy working on the project for the past two nights. Mainly I am back to trying to get the artificial driver running on different tracks even though last week I had given up. It was quite interesting how this happened;
First I started adding a portion of code that would allow users that join my SRS:TestingGrounds server a chance to see some of the information from the driver in action, so with the new corner detection I decided to send some LFS layout objects (chalk lines) to show some of this information, and it works. If you ever join and see some lines on the track you will know what they are. (Red is braking point, White is entry, Blue is apex and Yellow is exit).
When I got this working I had found a bit of test/experimental code that I started writing a long time ago, but never really finished and completely forgotten about. The function was named "LoadPathTest()" which cleared out the left/right edge and loaded them from the path file instead. This actually works, sort of. At least for forward direction tracks. The path does indeed follow the track well, but in some situations the left/right is actually not where it should it be making the track a bit more narrow than it would be with a handmade layout.
After finding this I decided to try out SO1, and it did work, sort of. The driver slammed into the walls over and over again, particularly at the chicane. For this to work on reversed configs I just need to swap the order and sides, which wouldn't be terribly hard - if it ends up being worth it.
At this point I ran into some weird issue, the AI driver going down a straight would go no faster than 35-40mph, and tries zig-zagging like crazy. Still not sure what is causing it but after spending two or three hours looking at all code changes it seems to have always happened except in the FE1 data that was processed a long time ago, so I decided to make sure I didn't lose it. (The issue reproduced when I tried reprocessing FE1, even on the codebase back in June 2014, thanks again source control.)
Today I found part of the issue and when I processed the FE1 data again it still failed. But restarting with the already processed data got it working. So I tried with the other tracks and that seemed to help, it has always been a challenge to keep the processing of data (first time) and loading processed data (other times) completely in sync, but at least now I know where the problem is and I've started ignoring it for now even if it is annoying to restart the driver after processing the data.
Right now I'm trying to add some code to have the application tell players that the server is a testing ground for the airs_artificial_driver. Also been trying to clean up some of this codebase, because such surprises as the LoadPathTest() shouldn't be so surprising. Unfortunately there has been quite a lot of experimental hacking in the years I've been working on the project.
I've had some issues with the server and a handful of random users (unknown) that crashed the ai driver while I left him overnight. So to combat this, from time to time I may password the server and those that follow this thread and have a respect for the project will still be able to access it with the password: airs although usually when passworded I will probably not be around.
On occasion I may password it with a different password completely, but will try to limit this. Hopefully the public password above doesn't get abused. The other thought I had was to make the AIRS application spectate any users who try to join the track if they don't have prior approval, although I don't really want to do that because most people have been respectful of the AIRS project, and for this I thank all of you.
I didn't get much done tonight, and I think this is the last night of development for a couple weeks for family coming in. I didn't get much, but I moved some things around to be easier to maintain in the future, deleted some unused bits of code and made it easier to add debug visuals to LFS. In doing so I added a chalk line along the racing line that the artificial driver computes and tries to follow. Next time you visit the server you will be able to see how far away from his own racing line he gets.
I also tried making it easier for the driver to start the car but that will remain to be seen if it works or not. The driver did an insane personal best today, but I think it may have been because of a big push from a BF1 driver at just the right time. 1:01.14, his old PB which is actually him and him alone was a 1:01.30 so I suspect there was a bump that played into that lap, or somehow he got major aero effects and or extreme circumstances...
Then again I was shocked when he got down to a 1:01.30. The logic has not changed since back when he was setting a 1:01.78, although recently I did change his set (after the 1:01.30) that did make him hit the 1:01.50s more consistently, so it is possible...
I've been able to push him to make a pitstop, this worked, with the help of viraaj5555, once the pitstop finished he tryed to go back on the track, without succes. We pushed him back to the track but his clutch burned. But this worked again.
It was the first time i saw your work, and i have to say WOW! nice work man! keep work on it !
That is hilarious! Good work on getting him into and out of pits! I would like to teach him how to pit but that is a bit of a challenge. I'm also trying to get him to understand the restarting of the race a bit better so he won't jump the start and get spectated. Sometimes it works, sometimes it doesn't.
I need him to be able to keep going around the track all night long, restart when he gets out of fuel, and continue some more. This is needed before I get the new driver logic written so that he can adjust the braking point and entry speed over a long period of time. Still not exactly sure how I will go about that portion.
I wanted to say he is running on the server now, his racing line is shown and I'll try to keep him going most of the day but since I am actually working (on real work stuff) I can't watch him or the server non-stop. So if you have some time and want to stop in, you are welcome to do so.
I guess he must have restarted the race and sometimes when he does this he gets in a funny state where his sensors are very glitchy. Somehow causing him to cut corners a LOT and even hit some tires. Unless you mean to say his current best was 1:01.14, in which that was the lap that possibly had him bumped with a BF1. Not sure if I can believe the time or not so for now I'll wait until he does it again.
A good handful of people had joined the server while I was working, so I wasn't able to hangout much. Had work/life stuff to be done. I'm going to take the server down for a couple weeks until while family visits, but I will get it back up as soon as they leave and things calm down enough for me to continue working on the artificial driver.
When I get back to development I would like to build up a debugging screen in LFS with InSim buttons that show what state the driver is in and what information and when it starts coming together get that debug information shared with everyone that wants to see it. Two other priorities, before new driver logic, will be to properly handle race restarts and being spec'd and make sure that during multiple restarts the driver doesn't get glitchy.
sorry, have some problems with the layout creation.
You said it is not so urgent but still awkward...it used to work fine just a week ago.
Kind of annoying... Now *somehow* the coordinates are always wrong resulting in "can not place object", maybe I did something different when editing the svg or something else.
Well last night I was able to get a little bit more work into the project. By unfortunately that will be it for a couple weeks. I should still have access to the forums should anyone have questions or if I have any breakthroughs. I took the server down since I won't be free enough. Overnight though I was able to make a few improvements to the airs application. First I added a quick way to add text information through insim buttons to the debug controller. It isn't very amazing feature wise, but it will get the job done. Minor issue is that I either turn it on for just me or for all users and the way it stand you can't turn it off via shift-I. But I don't think that is a giant problem for this server though.
The next improvement was with the driver restarting races. He would get glitchy after the first restart. I figured out why and have fixed this issue and a different crash issue that popped up today from some recent maintenance changes. Pesky bracket locations. Hehe
Finally I modified the downshifting point to be a little higher as one player suggested. I didn't really get to watch the driver after making this change, but it should stay in the power and better.
Now that family has left I've got the server running again, from time to time, and am working on making the driver better at restarting races so he can drive all night. He has driven successfully for 24 hours, about 4 to 5 restarts, but still seems to get hung up from time to time. And I've witnessed a few times when I come back to check on the driver that the AIRS application starts running extremely sluggish. Not entirely sure why that would happen all of a sudden, memory usage looked as expected, but he was down to 1fps at best - far too sluggish to drive the car.
Still planning how I will attack the new driver logic, there is a lot of things I have in mind, but the trick will be getting the driver to understand it! For instance, when entering a corner too hot, it would be best to straighten the wheel and go offline a bit to allow more braking before initiating a sharper turn. This is easy to understand as a human, but for the artificial driver, it is much more complicated than the current logic of "try to follow this line".
The thought I had was to have the racing line, and then have a "driving line" which gets modified in real-time by the driver. This would work great for multiple thoughts: passing lines, aggressive/defensive lines through a corner, pitting, and even modifying the line as described above when entering too fast. The trick here would be having the driver follow the line accurately!
If I go with the real-time modified "driving-line" I will need to make the driver be able to follow that line much more precisely than he currently does. If you haven't checked it out, the racing-line he computes and "follows" is shown on the server by a chalk-line. Watching him drive, you will notice he tends to fall off the outside edge of each turn. Sometimes more, sometimes less. This is also dependent of the car he is driving - in single seater cars the problem is much worse.
A while ago I tried a solution to aim the driving point to the left/right depending on how far away he currently was, which worked to some degree but also added more of a wiggle in straights so I removed that.
I may not go with the "driving-line" idea, as I am still thinking about the new driver logic, but currently it is a thought.
I went ahead and tried modifying the steering behavior to get a more accurate line, and by simply doubling steering angle change by 2 the XRG is now following the line almost, but not quite perfectly. I haven't yet tried other cars. What I can say already is WOW, what an improvement on lap times, IMMEDIATELY. The driver has only done 5 laps and he has already smashed his old PB by over a second. New PB is down to 1:00.00 exact, and bound to drop in the 59s shortly! (while writing this he has now dropped to 59.99!)
In the few laps I've watched, he now tends to stay on the inside of most corners, during entry and slides on the outside during exit. He is also on the outside of the back sweeping 'corner' that behaves like a straight. So my conclusion is that the faster he is driving, the bigger the multiplier will need to be. I will also assume that this is a value that will need to be tweaked for other cars, and I'm still pondering the best way to do that since I really don't want a table of values that I need to hand-tune to get the driver to go fast. I'm on the fence about this though, since to some degree it will be required.
It seems that there is still some form of issue with the AI driver getting confused about the location of his car. I haven't seen any issues there for a month or so when I first started up making the server public, but it did just need to be restarted because a player joined and the driver was confused.
Strange. I wasn't able to track it down but will keep my eyes open. I've been trying to think of ways to get the driver to feel the limits of the car in a given moment, in hopes to have a better algorithm for the new driving logic.
Also need the driver to understand restarts even better. The other day a player joined and restarted the race. The driver jumped the start and was spectated. Currently the driver does okay if he restarts the race, so now he just needs to understand when others do.
I worked a bit more on this last night and actually got a handful of improvements. First I've refactored the race restarting portions, and now the driver can handle a player restarting the race much better than he was doing before.
I've also deleted a large portion of code that had become infected with code-rot, not being updated as things improved. That means the nice visualizers I created for showing how I computed the racing-line and several things when I was trying to create my own physical world have been deleted and stripped from the project. I can always get this back by using the source control, but it makes things easier to maintain.
I also modified how the InSim debug interface is working and it will now show the developer status. I can change this status myself by typing an insim command or by using the menubar that I have also just added to the AIRS application. This should give people that connect an idea of my whereabouts / availability.
But probably the BIGGEST change was some hackery, that I will need to clean up, to detect which corner, and what phase of that corner the driver is currently in. I had to mess around with this quite a bit before I finally figured out how to get things working. The primary problem was the distance the car can travel from "frame to frame" in the AIRS project. So I actually had to run the checks backward to get the furthest possible point and make it more accurate - this does mean that other points could be skipped, but the display on the server shows it correctly the best it can.
There is also a slight delay in the InSim Button updates that make it somewhat slower than AIRS actually catches it, but it has been running all night and is still going strong and accurate. I encourage you to join the server SRS:TestingGrounds and check it out for yourself.
The driver does NOT yet use this information in any way, so even though it is displayed, it doesn't change any logic for the driver, yet. Driving logic version 2 will use it though and this was one of the steps to getting there.
Feels like it is just me here again! Even if it is I guess I'll keep talking.
Tonights developments progressed quite a bit! I started by allowing myself to send commands from my laptop / BlackBird account to the other machine, hoping that I'd be able to send "/press reset" or something similar and found that I was unable to do that, unfortunately. But it does let me send "/w pb" much easier than typing out "/ws fe1 xrg pb airs_artificial_driver" each time... I just need to look at the other screens to see the actual pb and it isn't easy to share.
I then worked on a config file for all the InSim/OutSim/VirtualController ports and IP addresses. Previously these were all hardcoded values and that worked out just fine, but if I want to try running AIRS on one machine and LFS on another I couldn't before without making a specific build. I've previously been too lazy to write the saving/loading config but now I've got it and won't need to do it again.
I also moved the interface around a bit and cleaned up the code from the other night with the corner detection. To add some more mess I decided to quickly add some "is at/near limit" buttons to the interface and really cruddy first attempt to detect if the car is at the limit for Oversteering, Understeering, Throttle or Braking conditions. It is working pretty well, though the values need some tweaking still.
Unfortunately these values will need to be tweaked per car / per setup, and that is one of those things I am really trying to avoid doing in this project. It is just really hard not to back yourself into one of those corners. For now Oversteering is calculated simply by checking directionOfCar vs directionOfMotion and as the angle increases it eventually crosses the threshold to be over the Oversteering limit.
Over throttle limit is determined by looking at the speedometer reading and the physical movement speed of the car, and if these are mismatched by some threshold, the car is considered over the throttle limit. Same for the braking actually, except in reverse. This does mean for the driver to detect the braking limits the setup will need to lock the drive wheels first, even if only slightly.
Understeering limits have not been implemented yet. This one is actually more tricky and I've yet to think of a good way to compute this limit. Sometimes you don't need to turn in very much to be understeering so "turning hard while going straight" isn't exactly the way to detect it.
All these can be seen with the new display, black / blue is under the limit. Green is nearing the limit but still under. Yellow is just under / at the limit and Red is over the limit by any amount. I think I'm getting closer to being able to start driving logic 2.0, had a lot of good thoughts about that today and I just need to finish the understeer limit detector then tweak the values - hopefully finding a way for the values to work for all cars ... Eesh.