我正在尝试根据以下教程制作车轮对撞机 PID 控制器:
https://www.habrador.com/tutorials/pid-controller/1-car-follow-path/
我对 FixedUpdate 方法进行了修订,以根据与样条航路点的角度差(如果在脚本中实例化一个)来修改转向方向,并尝试根据汽车的速度引入“滑行”或“制动”行为正在走,转弯的角度有多紧。目前,“漂移”将车轮摩擦曲线设置为车轮之间交替的前向和侧向摩擦刚度值。通常,任何汽车在车轮碰撞器上的侧向刚度系数为 2,如下所示:
现在,问题是,很难在理想的 PID 控制器设置和预期阈值之间找到平衡点 1.)由于转向角可能失控而导致制动或滑行 2.)当两者之间即将出现角度时“漂移”汽车前方的下一个航路点为汽车转弯提供了一个狭窄的角度。
这是我当前的 PID 值,老实说,我已经对这些值进行了相当多的调整(我知道这在某种程度上是可以预期的):
这是相关代码 - FixedUpdate 循环:
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 的速度行驶!事实证明,现在有点头疼。
感谢任何建议或意见。再次感谢。