Several days later, and I'm starting to get the cars working the way I want.
The reason for the delay is Open Steer. It's simply undocumented, and the example demonstrations are over-engineered to say the least. The forums have been minimally helpful.
Since I released the video a few days ago that showed the steering behavior working pretty well, I've been picking apart how Open Steer does it's job in an effort to figure out how to get the cars to do exactly what I want. There is no documentation besides comments in the code, and the internals are pretty complicated in places, so I've found that the best way to get familiar is to set it up to do what I think it should, then step through the code to find out why it's not behaving. That can take a while.
I thought I'd list a few of the more important limitations/weirdness/gotchas that I've found when playing around with this library.
All the available methods are aimed at keeping the vehicles moving. One of the possible reasons for this is that the API doesn't really have a proper method for stopping a vehicle. Sure, there's the SimpleVehicle::applyBrakingForce() method which comes close, but it doesn't actually cause the vehicle to stop, it will continue to creep forwards.
The LQ Lattice proximity database is definitely the best one to use for what I'm doing, and I'd be surprised if it's not the best for all but the simplest systems. It's purpose is to allow vehicles to only be tested against other vehicles that are nearby, saving valuable CPU.
One thing to watch out for when you create an LQ lattice database is that you'll want the size of your lattice to be bigger than the maximum area in which your vehicles can travel. The reason is that a vehicle that is overlapping the edge of the area will be considered to be outside the lattice, so proximity tests will then be made against all the active vehicles, effectively using the brute force method. This includes keeping an eye on the radius of your vehicles. As an example, I'm using a 2D lattice, and I had to make the lattice depth (Y axis) larger than the radius of my largest vehicle, or the brute forth method was used when checking for vehicle proximity.
The steerToFollowPath method is approximate at best - sure, it'll keep the vehicle on the path, but it will wildly swing to the left and right as it hits bends, and no amount of tweaking the parameters would fix this - the closest I got was to set the steering force really high, but that caused the car to shudder and wobble as it rolled along the path. If you want your vehicles to closely follow a fixed path, you'll need to come up with your own solution. The way I've done it is simply to apply force directly towards the nearest point on the path. No fooling around with approximations and smoothing for me!
Speaking of approximations and smoothing, there's tonnes of cruft in the example plugins. Most of the calculations made in the Pedestran plugin for instance don't really seem to be necessary, and would appear to have been arrived at through a process of trial and error, tweaking here and multiplying there until the vehicles behaved as expected. The MapDrive plugin is similar in that it really is overkill, presumably because it was intended to drive a real robotic vehicle across real terrain.
Overall, Open Steer is worth the effort to use, even if just for the LQ Lattice alone.
As I write this, the car control is probably about 80% complete. I've got the cornering working a lot better, the cars will actually slow down now. They'll also queue up if the car ahead slows or stops. I've been able to overcome the creeping problem and I've even got cars giving way to the right at three way intersections. The last thing to do is to get the cars paying attention to the traffic lights I'll finally be able to move on.