Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Torque curve problem

Discussion in 'Scripting' started by NDSno1, Oct 9, 2016.

  1. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Hi,
    So I'm using a torque curve to define torque at certain engine RPM. However, right now I'm having problem with my physic calculation. The max torque I wanted is 425.3 ftlb at 4000 RPM. The problem is at low gears the torque jumps really high, at about 1000 ft lb, so the wheel RPM also jumps along with engine RPM. The rigidbody speed jumps like crazy to more than 400 km/h. I think I might have some flaws in my physic calculation formula, maybe when converting units to SI units or just wrong calculation formula. Below is my code and my torque curve (based on a 2009 Nissan GTR). The curve has negative torque value at 0 to about 500, I fixed that to 0.

    Here are my gear ratios and final drive:
    1: 4.056
    2: 2.301
    3: 1.595
    4: 1.248
    5: 1.001
    6: 0.796
    finalDrive: 3.7
    wheel collider mass is 17 kg each
    wheel collider radius is 0.5334 meter each
    rigidBody mass is 1768 in kg
    engineAcceleration is about 434.1731 rad/s^2 after calculation from wheel Inertia and max torque at 1:1 gear ratio.
    My code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using XInputDotNetPure;
    4. using System.Collections.Generic;
    5. using UnityEngine.UI;
    6. using Random = UnityEngine.Random;
    7.  
    8. public class CarController : MonoBehaviour
    9. {
    10.  
    11.     public Text text;
    12.     public Text text2;
    13.     public Rigidbody body;
    14.  
    15.     GamePadState state;
    16.     GamePadState prevState;
    17.  
    18.     Quaternion FRRotation;
    19.     Vector3 FRPosition;
    20.     Quaternion FLRotation;
    21.     Vector3 FLPosition;
    22.     Quaternion RRRotation;
    23.     Vector3 RRPosition;
    24.     Quaternion RLRotation;
    25.     Vector3 RLPosition;
    26.  
    27.     public WheelCollider FL;
    28.     public WheelCollider FR;
    29.     public WheelCollider RL;
    30.     public WheelCollider RR;
    31.  
    32.     public Transform FLTrans;
    33.     public Transform FRTrans;
    34.     public Transform RLTrans;
    35.     public Transform RRTrans;
    36.  
    37.     public AudioClip engineSoundClip;
    38.     public float pitchMultiplier = 1f;                                          // Used for altering the pitch of audio clips
    39.     public float lowPitchMin = 1f;                                              // The lowest possible pitch for the low sounds
    40.     public float lowPitchMax = 6f;
    41.     public AudioSource m_engineSoundSource;
    42.  
    43.     public AnimationCurve torqueCurve;
    44.  
    45.     public float wheelInertia;
    46.     public float engineAccel;
    47.     public float engineInertia;
    48.     public float maxTorque;
    49.     //array of gear ratio, gear 0 is neutral with 1 ratio
    50.     //so engne rev free but clutch will disengage
    51.     public float[] gearRatio;
    52.     public int currentGear = 0;
    53.     public float finalDriveFront;
    54.     public float finalDriveRear;
    55.     public float reverseRatio;
    56.     public float minRPM = 700f;
    57.     public float maxRPM = 8000f;
    58.     public float shiftUpRPM = 7100f;
    59.     public float throttleInput;
    60.     public float clutchInput;
    61.     public float wheelRPM;
    62.     public float currentEngineRPM;
    63.     public float currentTorque;
    64.     public float currentSpeed;
    65.     public float currentWheelRPM;
    66.     public float bodySpeed;
    67.  
    68.  
    69.  
    70.  
    71.     // Use this for initialization
    72.     void Start ()
    73.     {
    74.         //set up wheelcolliders by automaticlly find one with certain name
    75.         //will use this later to get car prefab dynamically from prefab name
    76.         FL = GameObject.Find("FL").GetComponent<WheelCollider>();
    77.         FR = GameObject.Find("FR").GetComponent<WheelCollider>();
    78.         RL = GameObject.Find("RL").GetComponent<WheelCollider>();
    79.         RR = GameObject.Find("RR").GetComponent<WheelCollider>();
    80.         //for testing
    81.         text.GetComponent<Text>();
    82.         text2.GetComponent<Text>();
    83.         //compensate car's center of mass
    84.         body.GetComponent<Rigidbody>();
    85.  
    86.         //  body.centerOfMass = com;
    87.  
    88.         //minEngineVelocity = rpmToRads(minRPM);
    89.         //maxEngineVelocity = rpmToRads(maxRPM);
    90.         //engineVelocity = 1;
    91.         wheelInertia = 0.5f * (RR.mass) * Mathf.Pow(RR.radius, 2);
    92.         engineInertia = (wheelInertia) / 4;
    93.         engineAccel = rads2torpms(lbftToNm(maxTorque) * engineInertia);
    94.         //engineAcceleration = lbftToNm(maxTorque) / engineInertia;
    95.  
    96.         text.GetComponent<Text>();
    97.         text2.GetComponent<Text>();
    98.  
    99.  
    100.     }
    101.    
    102.     // Update is called once per frame
    103.     void Update ()
    104.     {
    105.         prevState = state;
    106.         state = GamePad.GetState(0);
    107.         throttleInput = state.Triggers.Right;
    108.         clutchInput = state.Triggers.Left;
    109.         text.text = nmtolbft(currentTorque).ToString("F0");
    110.         text2.text = currentTorque.ToString("F0");
    111.  
    112.         //Get the world pose of wheelcolliders
    113.         //which aways be the right pose
    114.         FR.GetWorldPose(out FRPosition, out FRRotation);
    115.         FL.GetWorldPose(out FLPosition, out FLRotation);
    116.         RR.GetWorldPose(out RRPosition, out RRRotation);
    117.         RL.GetWorldPose(out RLPosition, out RLRotation);
    118.         //then apply the poses to wheel mess
    119.         //the messes will move accordingly
    120.         //quickest way without using raycast
    121.         FRTrans.position = FRPosition;
    122.         FLTrans.position = FLPosition;
    123.         FRTrans.rotation = FRRotation;
    124.         FLTrans.rotation = FLRotation;
    125.         RRTrans.position = RRPosition;
    126.         RLTrans.position = RLPosition;
    127.         RRTrans.rotation = RRRotation;
    128.         RLTrans.rotation = RLRotation;
    129.  
    130.         //engineSound();
    131.         shiftGear();
    132.         bodySpeed = mstokmh(body.velocity.magnitude);
    133.         FL.steerAngle = state.ThumbSticks.Left.X * 30;
    134.         FR.steerAngle = state.ThumbSticks.Left.X * 30;
    135.     }
    136.  
    137.     void FixedUpdate()
    138.     {
    139.         currentTorque = 0.0f;
    140.         //currentEngineRPM = 0f;
    141.         //float minTorque = 0;
    142.         currentSpeed = 2 * Mathf.PI * RR.radius * RR.rpm * 60 / 1000;
    143.         if (currentGear > 0)
    144.         {
    145.             float rpmToEngine = ((RR.rpm + RL.rpm) / 2.0f) * gearRatio[currentGear];
    146.             currentWheelRPM = (RR.rpm + RL.rpm) / 2.0f;
    147.            //currentEngineRPM = minRPM + (currentWheelRPM * finalDriveRear * gearRatio[currentGear]);
    148.             currentEngineRPM = Mathf.MoveTowards(currentEngineRPM, rpmToEngine, Time.deltaTime * engineAccel);
    149.             currentTorque = lbftToNm(torqueCurve.Evaluate(currentEngineRPM)) * finalDriveRear* gearRatio[currentGear];
    150.            
    151.         }
    152.         else
    153.         {
    154.             // Neutral gear, simulate the engine idle. Temporaly using lerp for now
    155.             float targetRPM = Mathf.Lerp(minRPM, maxRPM, engineAccel);
    156.             //float targetRPM = Mathf.MoveTowards(minRPM, maxRPM, engineAccel);
    157.             currentEngineRPM += (targetRPM - currentEngineRPM) * Time.deltaTime * throttleInput;
    158.             if (throttleInput < 0.3 || clutchInput > 0.3)
    159.             {
    160.                 currentEngineRPM -= (targetRPM - currentEngineRPM) * Time.deltaTime;
    161.             }
    162.             //currentEngineRPM = Mathf.Clamp(currentEngineRPM, 0f, maxRPM);
    163.             currentTorque = 0.0f;
    164.         }
    165.         currentEngineRPM = Mathf.Clamp(currentEngineRPM, 0.0f, maxRPM);
    166.         RR.motorTorque = currentTorque / 4 * throttleInput * (1.0f - clutchInput);
    167.         RL.motorTorque = currentTorque / 4 * throttleInput * (1.0f - clutchInput);
    168.         //RR.motorTorque = (maxTorque / 4) *gearRatio[currentGear]*finalDriveRear* throttleInput;
    169.         //RL.motorTorque = (maxTorque / 4) * gearRatio[currentGear] * finalDriveRear * throttleInput;
    170.         float pitch = Mathf.Clamp(1.2f + ((currentEngineRPM - minRPM) / (maxRPM - minRPM) * 2.5f), 1.0f, 10.0f);
    171.         m_engineSoundSource.pitch = pitch;
    172.  
    173.  
    174.     }
    175.  
    176.     void engineSound()
    177.     {
    178.  
    179.     }
    180.  
    181.     void shiftGear()
    182.     {
    183.         if (prevState.Buttons.RightShoulder == ButtonState.Released && state.Buttons.RightShoulder == ButtonState.Pressed && currentGear < gearRatio.Length - 1)
    184.         {
    185.             currentGear++;
    186.             //engineVelocity = rpmToRads(RR.rpm);
    187.         }
    188.         if (prevState.Buttons.LeftShoulder == ButtonState.Released && state.Buttons.LeftShoulder == ButtonState.Pressed && currentGear > 0)
    189.         {
    190.             currentGear--;
    191.             //engineVelocity = rpmToRads(RR.rpm);
    192.         }
    193.     }
    194.  
    195.     #region Conversion Handler
    196.     //convert rad/s velocity to RPM
    197.     static float radsToRPM(float rads)
    198.     {
    199.         //float RPM = ((2 * Mathf.PI) / (rads + 1)) * 60;
    200.         //float RPM = (rads / (2 * Mathf.PI)) * 60;
    201.         float RPM = 2 * Mathf.PI * rads * 60;
    202.         return RPM;
    203.     }
    204.  
    205.     //convert RPM to rad/s
    206.     static float rpmToRads(float RPM)
    207.     {
    208.         float rads = (RPM / 60) / (2 * Mathf.PI);
    209.         return rads;
    210.     }
    211.     //convert torque pound foot to newton meter
    212.     static float lbftToNm(float lbft)
    213.     {
    214.         float Nm = 1.3558179433f * lbft;
    215.         return Nm;
    216.     }
    217.     //convert newton meter to pound foot
    218.     static float nmtolbft(float nm)
    219.     {
    220.         float lbft = 0.737562149277f * nm;
    221.         return lbft;
    222.     }
    223.     //convert W to HP
    224.     static float wToHP(float w)
    225.     {
    226.         float hp = w / 746f;
    227.         return hp;
    228.     }
    229.     //convert HP to W
    230.     static float hpToW(float hp)
    231.     {
    232.         float w = 745.699872f * hp;
    233.         return w;
    234.     }
    235.     static float mstokmh(float ms)
    236.     {
    237.         float kmh = ms * (1 / 3600);
    238.         return kmh;
    239.     }
    240.     static float rads2torpms(float rads2)
    241.     {
    242.         return rads2 * 9.549296586f;
    243.     }
    244.     #endregion
    245. }
    246.  
    The main physic script is in FixedUpdate() and at Start() I calculated the inertia and engine acceleration. Also I have helper functions to convert units too and they might be incorrect. Those are the 3 main parts that I think are causing problems. Please take a look. Any comment is appreciated.
    THank you very much
     
  2. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
  3. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    I did read that actually and that's why I came up with the calculation I'm having right now. The problem is I can't figure out where I went wrong.
    Thank you for your reply/
     
  4. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Bump. Anybody got any idea?