1

我正在尝试根据以下教程制作车轮对撞机 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 的速度行驶!事实证明,现在有点头疼。

感谢任何建议或意见。再次感谢。

4

0 回答 0