Search Unity

Help with simple 2D car physics "

Discussion in 'Scripting' started by TheVulcan, Apr 3, 2012.

  1. TheVulcan

    TheVulcan

    Joined:
    Nov 8, 2011
    Posts:
    32
    Hi,
    Trying wrap my head around 2D car physics here.
    I have tried breaking apart the Car tut but can't figure this bit out.

    How do you get the RPM / Gear to limit the speed?

    I will simplify below.

    Force_x = torque * 1st_gear * diff * wheelsize * throttle
    acceleration = Force_x / weight
    v = v + dt * acceleration

    This gives the car veloicty just fine.
    However this will accelerate to infinity. (not taking drag into account drag)
    But 1st gear is only good for 50kph ?



    If I use the RPM to calculate forward speed.

    Speed = wheelsize * 1st_gear * diff * RPM

    This will limit my speed to the rotation of the wheel.
    But then it doesn't take torque into consideration.
    So a Honda would accelerate as fast as a Ferrari.
    And wheel spins wouldn't work.

    I think they refer to the problem as a "feed back loop".
    But I can't see how its done in the car tut.
    And I am yet to find an example that shows how it is done.


    The only way I could think of is calculate the max_speed for the current gear using RPM.
    Then accelerate using torque until you hit max_speed.
    Then set acceleration back to zero until the next gear is selected.

    But I can't see anything like that in the car tut and don't know how realsitic that would be.

    Anyone know how this is done properly ?
     
  2. outrunner

    outrunner

    Joined:
    Apr 1, 2011
    Posts:
    12
    Last edited: Apr 3, 2012
  3. TheVulcan

    TheVulcan

    Joined:
    Nov 8, 2011
    Posts:
    32



    Hi thanks for posting and thanks for the link to the wiki page.

    I have been using that tut "Car Physics for Games".
    I have read it enough that I know some of it off the top of my head.
    Fdrag = .5 *cd * A * rho * v2
    Frr = 30 * Fdrag

    And when I add drag into it, the car tops at at a max speed as expected when drag = torque.

    However unless I am wrong in my programing, or have miss understood the physics.
    I was working on the assumption that the 1st gear ratio itself should cause it to max out speed, not the aerodynamic drag.
    Seeing as 1st gear is the highest torque multiplier and at low speed the drag is minimal.

    I believe that in the tut it says as you go up gears your trading torque for speed.
    Which makes sense since fist gear is a 2.66x multiplier of torque vs 0.50x in sixth gear.

    So when your in 6th gear at speed you have the lowest torque, vs the highest drag that has been increasing at squared rate of V.



    So unless I am completely missing something.....
    I am still stuck with the same problem....

    How do you limit your speed in low gears?
    When drag is negligible and your at max torque output.
     
    Last edited: Apr 3, 2012
  4. TheVulcan

    TheVulcan

    Joined:
    Nov 8, 2011
    Posts:
    32
    I am now thinking that the answer to what I am looking for is calculated in the Wheel.cs

    That they are using the anglar velocity of the wheel along with the Pacejka coefficents to calculate the torque for a given RPM.

    I'll try work down this path for now unless someone else knows better.
     
  5. outrunner

    outrunner

    Joined:
    Apr 1, 2011
    Posts:
    12
    Put a RPM limiter on the engine code
     
  6. TheVulcan

    TheVulcan

    Joined:
    Nov 8, 2011
    Posts:
    32
    Thanks.
    But I already have a max and min RPM set and linked to torque curve formula.

    I basically need something like: (very simplified)

    Force.x = wheel_RPM * Torque - Slip;

    This is from the car tut, I think once I fully understand this I will have my answer.

    Code (csharp):
    1. Vector3 RoadForce () {
    2.         int slipRes=(int)((100.0f-Mathf.Abs(angularVelocity))/(10.0f));
    3.         if (slipRes < 1)
    4.             slipRes = 1;
    5.         float invSlipRes = (1.0f/(float)slipRes);
    6.        
    7.         float totalInertia = inertia + drivetrainInertia;
    8.         float driveAngularDelta = driveTorque * Time.deltaTime * invSlipRes / totalInertia;
    9.         float totalFrictionTorque = brakeFrictionTorque * brake + handbrakeFrictionTorque * handbrake + frictionTorque + driveFrictionTorque;
    10.         float frictionAngularDelta = totalFrictionTorque * Time.deltaTime * invSlipRes / totalInertia;
    11.  
    12.         Vector3 totalForce = Vector3.zero;
    13.         float newAngle = maxSteeringAngle * steering;
    14.         for (int i=0; i<slipRes; i++)
    15.         {
    16.             float f = i * 1.0f/(float)slipRes;
    17.             localRotation = Quaternion.Euler (0, oldAngle + (newAngle - oldAngle) * f, 0);        
    18.             inverseLocalRotation = Quaternion.Inverse(localRotation);
    19.             forward = transform.TransformDirection (localRotation * Vector3.forward);
    20.             right = transform.TransformDirection (localRotation * Vector3.right);
    21.            
    22.             slipRatio = SlipRatio ();
    23.             slipAngle = SlipAngle ();
    24.             Vector3 force = invSlipRes * grip * CombinedForce (normalForce, slipRatio, slipAngle);
    25.             Vector3 worldForce = transform.TransformDirection (localRotation * force);
    26.             angularVelocity -= (force.z * radius * Time.deltaTime) / totalInertia;
    27.             angularVelocity += driveAngularDelta;
    28.             if (Mathf.Abs(angularVelocity) > frictionAngularDelta)
    29.                 angularVelocity -= frictionAngularDelta * Mathf.Sign(angularVelocity);
    30.             else
    31.                 angularVelocity = 0;
    32.                
    33.             wheelVelo += worldForce* (1/body.mass) * Time.deltaTime * invSlipRes;
    34.             totalForce += worldForce;
    35.         }
    36.  
    37.         float longitunalSlipVelo = Mathf.Abs(angularVelocity * radius - Vector3.Dot (wheelVelo, forward));    
    38.         float lateralSlipVelo = Vector3.Dot (wheelVelo, right);
    39.         slipVelo = Mathf.Sqrt(longitunalSlipVelo * longitunalSlipVelo + lateralSlipVelo * lateralSlipVelo);
    40.        
    41.         oldAngle = newAngle;
    42.         return totalForce;
    43.     }