Я пытаюсь сделать ПИД-регулятор колесного коллайдера на основе следующего урока:
https://www.habrador.com/tutorials/pid-controller/1-car-follow-path/
Я внес изменение в метод FixedUpdate, чтобы измените направление рулевого управления на основе разности углов с помощью сплайн-путевой точки (если она определена в сценарии), а также попробуйте ввести режим «выбега» или «торможения» в зависимости от того, насколько быстро движется автомобиль и насколько узок угол поворота. очередь будет. В настоящее время «дрейф» устанавливает кривую трения колес на переменную жесткость трения между колесами вперед и вбок. Обычно, любой автомобиль имеет коэффициент боковой жесткости 2 на коллайдере, как здесь:
Теперь проблема в том, что трудно найти баланс идеальных настроек ПИД-регулятора и ожидаемого порога 1.) тормоза или выбег из-за угла поворота, который, возможно, выйдет из-под контроля 2.) "дрейф", когда угол наклона между двумя последующими путевыми точками впереди автомобиля составляет узкий угол для поворота автомобиля.
Вот мои текущие значения PID, честно говоря, я немного их настраивал (что, я знаю, в некоторой степени ожидается):
Вот соответствующий код - FixedUpdate l oop:
void FixedUpdate()
{
float motor = carControl.maxForwardTorque;
//Manual controls for debugging
//float motor = carControl.maxForwardTorque * im.throttle;
//float steering = carControl.maxTurn * im.steer;
//
//Calculate the steering angle
//
//The simple but less accurate way -> will produce drunk behavior
//float steeringAngle = maxSteeringAngle * Math.SteerDirection(transform, steerPosition, currentWaypoint);
//Get the cross track error, which is what we want to minimize with the pid controller
float CTE = AIVehicleMath.GetCrossTrackError(steerPosition, previousWaypoint, currentWaypoint);
//But we still need a direction to steer
if(splineWalker)
CTE *= AIVehicleMath.SteerDirection(transform, steerPosition, splineWalker.transform.position);
else
CTE *= AIVehicleMath.SteerDirection(transform, steerPosition, currentWaypoint);
float steeringAngle = PIDControllerScript.GetSteerFactorFromPIDController(CTE);
//Limit the steering angle
steeringAngle = Mathf.Clamp(steeringAngle, -carControl.maxTurn, carControl.maxTurn);
//Average the steering angles to simulate the time it takes to turn the steering wheel
float averageAmount = 30f;
averageSteeringAngle = averageSteeringAngle + ((steeringAngle - averageSteeringAngle) / averageAmount);
Debug.Log("Average steering angle is " + averageSteeringAngle);
//
//Apply everything to the car
//
float signFactor = averageSteeringAngle/carControl.maxTurn;
im.steer = signFactor;
if (Mathf.Abs(averageSteeringAngle) > 15 && rb.velocity.magnitude > 15)
{
im.throttle = 0;
im.brake = true;
}
else if (Mathf.Abs(averageSteeringAngle) > 5 && rb.velocity.magnitude > 15)
{
im.throttle = 0;
im.brake = false;
}
else
{
im.throttle = 1;
im.brake = false;
}
float currDistFromWP = Vector3.Distance(transform.position, allWaypoints[currentWaypointIndex].position);
float speed = rb.velocity.magnitude;
float timeFloatLeft = currDistFromWP / speed;
Vector3 nextVector;
Transform nodeA;
Transform nodeB;
if (currentWaypointIndex == allWaypoints.Count - 1)
{
nodeA = allWaypoints[currentWaypointIndex];
nodeB = allWaypoints[0];
}
else
{
nodeA = allWaypoints[currentWaypointIndex];
nodeB = allWaypoints[currentWaypointIndex + 1];
}
float distanceBetweenNextTwo = Vector3.Distance(nodeA.position, nodeB.position);
float angleBetweenTwo = Vector3.Angle(transform.position, nodeB.position);
if (currDistFromWP < 20 && angleBetweenTwo > 30)
im.drift = true;
else
im.drift = false;
}
Может кто-нибудь дать рекомендации о том, как я могу подойти к этому более эффективно, может быть? Независимо от того, что я делаю, машина продолжает вращаться в пьяном виде, даже когда я ограничиваю скорость до чего-то очень медленного, например, 10 или 20. И затем, конечно, представьте, что машина движется со скоростью 70 или 90! Сейчас это становится головной болью.
Цените любые предложения или комментарии. Еще раз спасибо.