// calculate the difference between
// the desired value and the actual value
error = desiredSpeed - currentSpeed;
// track error over time, scaled to the timer interval
integral = integral + (error * Dt);
// determine the amount of change from the last time checked
derivative = (error - preError) / Dt;
// calculate how much to drive the output in order to get to the
// desired setpoint.
output = (Kp * error) + (Ki * integral) + (Kd * derivative);
// remember the error for the next time around.
preError = error;
So my overall idea is
decide what speed is desired by rules above (I think for the start hardcoding some kludge values TargetSpeed +/- Constant for SpeedUp/SlowDown will do)
calculate the error by using this desiredSpeed and the currentSpeed of the AI controlled vehicle
calculate the rest as in pseudo code sample above
Sticking points:
I think my problem is that the code sample operates on speed, not on throttle values? How do I get throttle values if I do not know what throttle value represents what speed?
If I get this to work, what to do with the actual closing velocity? Currently I am assuming the AI vehicle is directly behind and facing the target, which will seldom be the case in the actual game. What to do about that? Simply ignore to get a good enough solution?
PS: hope this is the right forum, it is kind of between game design and scripting, I think
So you’ve got a loop that is going to produce the answer to the question “Where should my throttle be?”
Here’s something from a project I was fooling around with, using the physics engine for movement.
private void CalculateLinearForces()
{
// Now calculate forces acting on the aeroplane:
// we accumulate forces into this variable:
var forces = Vector3.zero;
var forwardForce = CalculateForwardThrust();
var lateralForce = CalculateLateralThrust();
//Add the forward thrust
forces += forwardForce;
//Add the strafe thrusters
forces += lateralForce;
m_Rigidbody.AddForce(forces, ForceMode.Impulse); //This does the actual pushing.
if (InertialBrakes)
{
DampInertia(forwardForce + lateralForce);
}
}
private Vector3 CalculateForwardThrust()
{
Vector3 forwardThrust = Vector3.zero;
forwardThrust += EnginePower * transform.forward; //Engine power is Throttle * MaxEnginePower
return forwardThrust;
}
Your speed is going to be rigidbody.Velocity.magnitude - you can predict what your speed is going to be after applying force by doing velocity = force/mass * time - of course unless time is constant you’ll have some error there, but it shouldn’t be enough to matter.
I don’t think it can be that difficult, basically it is like a cruise control for a car, and I don’t think especially older models could predict the speed of a certain throttle value (factoring in going uphill/downhill, friction, wind, current gear… some of them unknown to the controller I would guess).
So how does a cruise control control the throttle?
My guess is it knows
current speed
desired speed
current throttle position (0 to 1)
Output should be another throttle position.
I am currently thinking the “magic” lies in the PID coefficients.
For simplicity I will ignore the ID part and try a simple P controller (as far as I understand it the ID part is for getting better results closer to the target value and could be ignored if a value close enough to the target is ok, like 45 or 55 in this case, just to throw some numbers around).
So lets say current throttle value is 0.5, current speed is 30mph, desired speed is 50mph.
This gives an error of 20mph. So with a Kp = 0.05 I would get: