Ruud van Gaal wrote:
> Hi all,
> To simulate an AI driver steering, I have a class lying around; SMD
> (spring-mass-damper). I can set a goal location for the object, and
> much like a wheel attached to a damper the object will move towards
> the target.
This turned out way too long, but I found it interesting.
"If only one developer's soul can be saved, it will all
have been worth it" ;);)
Hopefully this will be of some use:
TWICE DIFFERENTIABLE PATHS ARE GOOD
SEQUENTIAL STRAIGHT LINE SEGMENTS ARE EVIL
I don't like this system because it basically is a
heading command system. It generates a path made up
of a sequence of straight lines. This kind of path
isn't twice differentiable so looking ahead at
the next several goal points to decide when to brake may
be difficult because you can't easily determine what
lateral acceleration you will need at speed and then
what speed you will want given an assumed capability.
The heading commands don't restrict a path completely,
so you don't have precise control of crosstrack position.
If you slop to the side you won't recover back to the
desired "line" - because there isn't one ;).
Sometimes this is useful, but in a racing game with
hard constraints often surrounding the path there are
other ways to get the same behavior of not immediately
fixing crosstrack errors if it isn't important yet.
But when it IS important you have no real way of
telling the algorithm that.
If you have a twice differentiable path you can calculate
the desired path's curvature and thereby the
lateral acceleration capability required at any speed.
(Thus the needed speed given an assumed constant
capability.) You can build a crosstrack controller
that you can adjust the bandwith of to return to the
path quickly or slowly as desired.
Twice differentiable paths don't have to be fancy splines.
Straights and circles is a good first order approximation
to a road course.
"Flocking"-ish stuff is useful if you don't mind going
slow (far off optimum) and it doesn't hurt to go off the
path a bit once in a while. Neither situation is
usually a luxury that real racing offers :)
If you want to stay near optimum, the AI has to
have/find a near optimum path and be able to control
speeds carefully as it follows it. Using a path
formulation that makes it as easy as possible for
the AI to determine the needed speeds just seems
very useful.
GAIN SCHEDULING:
Crosstrack controllers are easier to gain schedule
(although this isn't really a big problem) because
the gains are independent of velocity.
(The velocity terms happen to cancel out.)
Heading gains have to change with velocity.
If you aren't used to doing linear analysis of
controllers though, you could either mess that
up and have to figure it out from practice - or
just live with less capability, possibly without
even realizing. If you include compensation for
the damping reduction of the "path curvature
stiffness" lateral stability derivative as the
speed increases, this requires extra gain
scheduling for both formulations.
(see chapter 5 IIRC of Race Car Vehicle Dynamics
for the physics behind this)
You can end up with exactly the same controller
transfer function with both crosstrack and
heading systems (for small errors in the
linear range) but I think the heading system is
much harder to analyze because it is subtler.
The non-linearites occur sort of in the middle
of the whole flow rather than at the end.
This may just be a familiarity thing.
I've worked with real vehicles using crosstrack
controllers and none with heading controllers.
RAMPS AND STEPS:
A steady turn is a ramp command in heading.
Simplistic controllers result in standoff
errors to ramp command inputs.
For a crosstrack command, ateady turning can be
made just a constant "feed forward"
acceleration signal. This simplifies analysis
of the control loop for a beginner. It provides
good performance because the feed forward
can give good speed of response to sudden
turn ins without requiring high gains
in the controller (possibly resulting in
increased overshoot which is bad when racing
near walls, or stability problems because
of too little gain margin for bad conditions
like crests, curbs, or slippery surfaces.)
With a good twice differentiable path, the
acceleration feed forward is straight forward
to calculate. (Not easy, but at least you can
be sure when you have gotten it right.)
OVERRUNNING WAYPOINTS IN A HEADING SYSTEM:
The acceleration you will calculate
to follow a heading command goes to infinity
as you overrun the goal point.
So you need to drop that goal at some point
before you reach it and go on to considering
the next. This means that performance is highly
influenced by the exact placement of goal points
in and near corners. (Because the distance between
them can interact with your goal switching
algorithm.)
Crosstrack controllers don't twitch if they
pass a particular point on their commanded path
0.5 meter off. A heading controller will go crazy.
Again, this can feed back into the total system.
Suppose you decide for car A that 20 meters is the
correct distance between waypoints around a corner
with your switching logic. If you change to a
faster car B the periodic twitches will change
frequency getting faster. If you
happen to approach the car's yaw frequency...
you can have hard to repeat stability problems.
SATURATING CONTROLS AND THE "UNDERSTEER TRAP":
If you let your controls saturate then you will have
a large standoff error as you go around the corner
(missing the apex). This is harder to keep away
from IMO with a heading controller than a crosstrack
because of the ramp input vs step input thing.
The cause of this saturating is that you are too
fast. Your AI will understeer around the corners.
This can masquerade as close to optimum, but only
if you very very carefully control the turn entry
speeds. If you get into this situation, you can
easily fall into the real trap of adjusting your
driving line such that it will only work well
for one vehicle at one weight at one tire
condition at one... etc. Also, remember
far far above ;) where it was mentioned that the
"sequence of straight lines" path type makes it
very difficult to figure out what speed you need
to be at. You've just made your controller
incredibly sensitive to a value you've also made
very hard to calculate.
The last paragraph was for final understeer vehicles.
If your vehicle is final oversteer and you let it
saturate you will spin. All sorts of logic paths
to detect and control out of that condition
would need to be added.
HOW TO DESTABILIZE YOUR ENTIRE
GAME PROJECT DEVELOPMENT LOOP:
The understeer trap interacts horribly with
physics changes. You have "optimized" your driving
line but decide later to add 0.25 G of turning
capability: Suddenly your AI is bouncing off the
curbs well inside the apexes. So start over
"optimizing" the driving lines tweaking the points
outward because you can now turn faster.
If you instead reduce the G capability the
effect is even worse. Possibly understeering
off the course at almost every corner.
Because the straight line segments
path is so hard to use to get allowable speeds,
you might be tempted to hold the algorithms hand
helping with the speed decision or help
finding where to start braking or even both.
(Ouch). This means you also have to
redesign when you change braking performance.
(Or burn fuel, or have wet weather, or worn
tires or...)
LANE CHANGES ARE EASY WITH CROSSTRACK CONTROL:
Lane changes or passing is a maneuver that can
be handled "naturally" using a step change in
crosstrack command. Steps are easy to analyze.
Imagine how you would perform such a maneuver using
heading commands. (Kind of complicated, hmm?)
Now imagine you wanted to pass
the car in front 1 meter farther to the
left than before: how much more heading error
do you want to induce by adjusting your future
target point or some such strangeness?
Can't guess? Have to experiment?
I prefer just to subtract 1 meter from my
crosstrack command ;).
With a crosstrack controller, knowing the
bandwidth and damping of the overall system
and the resulting step response you've made
constant over a wide speed range, you will
know exactly how long it should take to do
the lane change. (So you also know when to start
the manuever!) When you picked your gains you
even chose what kind of overshoot behavior in
crosstrack you wanted: and you thereby know
whether you can expect to safely fit between
the passed car and the wall.
CROSSTRACK ERROR MORE INTUITIVE WHEN
EVALUATING PERFORMANCE:
Finally, if you have a desired path, the crosstrack
error can be easily used to evaluate the systems
performance. The heading error performance of a
heading controller isn't so intuitive.
To me, "5 ft outside at the apex"
is easier to evaluate than "14 deg of heading error
at the apex." You can get crosstrack error statistics
from the heading controller but remember that you
didn't really want to exactly follow the set of
straight line segments. You really wanted to sort
of curve around the corner in a unknown one of the
infinite number of smooth curves that passes through
the waypoints.
So a plot of crosstrack errors versus the
straight lines is harder to use for a heading
controller because zero error
isn't perfect in this case. Not having a
physically realizable desired path makes it
both hard to follow and hard to evaluate afterwards.
Gasp ;)
- Matt