I've had a break through last night. Sometimes on this project all I need is a little bit of time and voila new bits come to me. I've been pondering how to handle the situation with the many different variables at play and how to make the artificial driver faster without hardcoding information specific to FE1, the XRG or the particular setup being used. I went through reading some of my older posts about the reference points and how I wanted to use them previously,
(way back when I had wanted to have braking, turn in, apex points instead of just left/right edge, though in my defense I just never got that far... yet)
Last night the light bulb went off, I can modify how I compute the racing line ever so slightly and add a brand new reference point for the driver to keep track of. If you recall from previous bits, the artificial driver is already driving towards a
driveToPoint that moves in front of the car along the racing line. This new reference point will be added at the start of every corner on the racing line, or at least after some length of a straight section, to be determined by the angle between the hinges used in the computation.
This new TurnPoint will go into the drivers memory unit, and will hold some information that cannot be changed, where the turn begins, and the distance and position at the end. With this information I should be able to determine if the
driveToPoint is within a turn, and/or if the car is within a turn. When it is within a turn the driver will attempt to drive at the limits of the car or try smoothly accelerating to the limit.
The TurnPoint will also hold a few values that will change over time like brakingPoint and entrySpeed. As the driver is approaching a turn, he will begin braking once he reaches the brakingPoint and attempt to reach entrySpeed before reaching the actual turn in. I can then set these values to long braking areas and slow entry speeds which should allow the driver to smoothly enter the corner, but obviously not be at the limit. The driver could then check on the conditions of the car, how much at the limit was the car at various points, and determine if more braking area is needed, extend the brakingPoint. If more or less speed is required to take the corner quickly but safe, it can also be modified in the long term memory.
This should allow the driver to tune his braking points and driving as I originally wanted to using pseudo-reference points. This "TurnPoint" won't be the same as the points on left/right track edges, instead it will exist only in drivers long term memory, and always be "seen" or at least thought of.
...
Now, this gets me back to a slightly minor problem, which last nights brilliance solved most of but still a slight issue exists. This method of driving requires me to semi-accurately judge how "at the limit" the car is at a given point. This is the job of the prediction unit however instead of using the future predicted path, (which as we can see has been unreliable and may eventually need to be fixed or stripped out), it will need to predict several immediate states of the car:
- isOverSteering() - (can be determined by comparing carHeading with velocityDirection)
- isUnderSteering() - (possibly determined by comparing steeringAngle vs yaw rotation?)
- isFrontLocked() / isRearLocked() - (can't be accurately determined that I am aware of, but would be great!)
- isOverBraking() - (possible determined by comparing longitudinal G forces with a value specific for the car)
- isOverThrottling() - (can be determined by comparing carSpeed (speedometer) with velocityMagnitude (physical speed))
So the unknown is how accurate I can determine understeer condition and over braking conditions. Both are needed for the driver to tune corner entry and determine if the car is at or over the limit. I also need to find a way,
which I haven't figured out yet, how to determine that the car is NEAR the limit. It is easy to determine over the limit (any one or more of the above conditions is true), and reasonable easy to determine under the limit (all of the above conditions are false), but the artificial driver should be able to find when the car has neared the limit so he doesn't push too far. The best thought here so far, and I don't really like it, is to determine if one of the conditions were true within the last tenth or two tenths of a second, then assume the car is near the limit. Of course this requires driving over the limit to be near the limit...
Those functions won't only be black and white, for instance isOverSteering() can and likely will use a different function quantifyOverSteering() to determine if the car is in an oversteer state... Something like:
bool isOverSteering() { return quantifyOverSteering() > limitThreshold; }
So it MAY be possible, to determine if the car is near the limit if one or more of the states are less than the limitThreshold but greater than some grandmaThreshold.
If I haven't lost you yet, great! If I have, and this is likely to be the case, please ask questions. Get involved! It makes me think more about the solutions, and keeps my motivation up.
....
So this means I need to do several things:
- I should seriously consider removing the curve path, and possibly even reducing visual sensor wasted time.
- Modify the Racing Line Computer to find/separate straights and turns.
- Create TurnPoint reference points and put in the long-term memory unit with default slow values.
- Modify prediction unit to accurately determine state of car, and if it is near limit.
- Create a driving state to get the artificial driver to drive near the limit and handle over limit cases.
- Make driver modify long term memory based on what happened at different points during the turn.
This is a pretty heft list, but I think if I pull it off correctly the driver might be reasonable fast without hard-coded values specific to a car/track/setup configuration. It will be amazing to see the airs_artificial_driver with lap times closer to 107% of WRs