Search Unity

WheelCollider position setting

Discussion in 'Physics' started by NDSno1, Nov 26, 2016.

  1. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Hi all,
    I'm trying to tame WheelCollider's friction and position (relative to the body collider) setting to have a, at least, driveable car. The reason I don't use other pre-made package is that I've been so deep in the project with my own physic model that I cannot back out now.
    Enough with that. So in the picture below is my current wheelCollider position. I've seen @Edy tutorial on wheelCollider settings for his Vehicle Physic Pro, and the collider should be placed at the edge of the wheel visual mesh, and outside the bound of the body collider, which is not what I have here:
    2016-11-26 (1).png
    My question is: what is the different between placing the wheel collider inside the body collider and outside, at the edge of the visual wheel? I have a simple body collider setup with a big box collider represent the main body and the smaller box collider represent the upper body:
    2016-11-26 (2).png
    Also is my suspension value OK? The weight of the rigid body is 1263 kg.
    Also if possible, can you suggest a setup for wheelCollider's friction curve. I've been modeling it based on this Pacejka curve from EA's F1-2002 tire.tbc file from this website: http://www.racer.nl/reference/pacejka.htm
    pac_f12002.jpg
    However, by car is still undriveable, a lot of wheelspin at launch and a slight change in steer angle results in a spin.
    I also would like to know what's a typical steering angle of a sport car. I'm setting it to 25 but is it to low?
    Please help.

    Thank you very much.
     
    Last edited: Nov 26, 2016
  2. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Bump. can someone help me please? I can't understand how the sideway friction curve works at all.
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    In VPP the WheelCollider should be placed at the edge of the wheel, but inside the bound of the body collider. The edge of the wheel is a better representation of the reality as provides a wider track (= better stability). The position should be inside the bound of the body collider for preventing ugly effects when contacting other objects, such as the vehicle flying without control on touching a wall slightly.

    As for the other questions (making a driveable car, suspension settings, tire friction etc) I refer to my previous post on good settings for the WheelCollider.
     
  4. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Thanks for your reply.
    It's exactly like what you've said, I've tested different wheelCollider positions with the same car and same specs, the car with wheelColliders on the edges feels more stable.
    I've been looking at Unity Unite 2015 on wheelColliders and realized that ForceAppPointDistance is actually very important and should not be 0. I changed it a bit to 0.15 for the car above and thing changed dramatically. Suspension travel now looks more realistic and the wheels actually grip on better now. The hard thing is to find the actual CenterOfmass of the vehicle so that I can place ForceAppPointDistance "correctly the way Nvidia recommends it", which is 0.3m below the centerOfMass.
    But the thing is, with race cars, like the one I'm going to show below, the centerOfMass is very low, if the ForceAppPointDistance is 0.3m below the centerOfMass, the point will go outside the bound of the wheelCollider. The centerOfMass for this car is about 0.3m above ground (0m), and if I do it the "Nvidia way", the ForceAppPointDistance is now 0, which is pointless. Looking at the EasySuspension package from Unite, the example car has centerOfMass of 0,0,0), which is the center of the cube, but I don't understand the way they calculate the forceAppDistance.
    In my project I use an empty gameObject, place it where the centerOfMass should be and set the center of mass to its localPosition. It works well since I can really feel the difference in tire grip and suspension travels between front and rear wheels when changing the centerOfMass position. Untitled.png
    So my new question, where should I place the forceAppPointDistance? i also noticed that the higher the ForceAppPointDistance, the more grippy the tire gets (and more understeer), I have no idea why?

    Also thank you so much @Edy for your guide on setting up Vehicle Physic Pro, it helped me a lot with setting up suspension settings. It would really help if you have a guide on setting up friction curves as wheel, since I don't really know how the sideway friction works. Forward friction is pretty straight forward, in my understanding, the force applied at certain slip would push the car forward, but how the force in sideway friction is going to be applied?

    Again, thank you so much,
     
  5. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    My pleasure! Glad to know that the Vehicle Physics Pro guides are useful to you.

    forceAppPointDistance lets you specify the point the forces will be applied to the rigidbody at. The closer the point to the CoM, the vehicle roll will be smaller. The more distance to the CoM, the vehicle will get more roll. If the application point is above the CoM, the vehicle will experience inverse roll (i.e. motorbike style). I use a similar method for the "Anti-roll" parameter in Edy's Vehicle Physics. It's a very handy concept for controlling the vehicle's roll rate without having to deal with suspension parameters.

    However, forceAppPointDistance is a kind of "invented" parameter without a true physical meaning. Unless the entire suspension structure is accurately simulated, the most physically correct position for the application of the suspension and tire forces is the contact point of the wheel with the ground. Any other position is highly subjective and provides a physically incorrect behavior.

    In Vehicle Physics Pro forceAppPointDistance is recomputed on each frame for applying the suspension force at the tire's contact point. The vehicle's roll rate is then configured using realistic and physically correct methods: configuring dampers and using anti-roll bars. This allows to use real-world techniques for diagnosing and setting up the suspension behavior in the vehicle.

    I don't know how the sideways friction works in the WheelCollider either. I've said many times that I've been unable to extract any logic out of the WheelCollider's tire friction parameters.

    Recently I've added useful information on tire curves to the VPP docs:


    You may also check out some in-depth information on tires and tire friction here:

    Note that these documents refer to the wheel component in Vehicle Physics Pro. They're not applicable to the stock WheelCollider component.
     
    Last edited: Nov 29, 2016
  6. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    My goodness @Edy I should buy you a beer. The source you gave on Tires is super helpful. I still need time to swallow all of them, but at least I know what direction I should head to.
    Also I have another question, if you don't mind, and it's more about coding. So I followed this video on Unity Unite

    I follow the "recommended" way of getting the engine RPM by working backward from wheelCollider RPM. I do it by getting the average RPM of drive wheels * finalDrive * gearRatio (2 front or 2 rear or all 4, I know it's not 100% correct since you have different type of axles, but due to the time constrain of a school project, I cannot go further) shown in my code below:
    Code (CSharp):
    1.  
    2. //this is 4 wheel drive
    3. rpmToEngine = Mathf.Abs(((RR.rpm + RL.rpm + FL.rpm + FR.rpm) / 4.0f) * Mathf.Abs(currentGearRatio) * ((finalDriveRear + finalDriveFront) / 2.0f));
    Once I have that, I use that RPM to look up the "RPM" curve that I have to workout the current torque (just a simple animation curve)
    Code (CSharp):
    1. currentTotalEngineTorque = lbftToNm(torqueCurve.Evaluate(currentEngineRPM)
    Once I have that total, I divide it up by the number of drive wheels * finalDrive * gearRatio * throttleInput * clutch
    Code (CSharp):
    1. RR.motorTorque = (currentTotalEngineTorque / 4) * (throttleInput) * (1.0f - clutchInput) * currentGearRatio * finalDriveRear;
    2.                 RL.motorTorque = (currentTotalEngineTorque / 4) * (throttleInput) * (1.0f - clutchInput) * currentGearRatio * finalDriveRear;
    3.                 FL.motorTorque = (currentTotalEngineTorque / 4) * (throttleInput) * (1.0f - clutchInput) * currentGearRatio * finalDriveFront;
    4.                 FR.motorTorque = (currentTotalEngineTorque / 4) * (throttleInput) * (1.0f - clutchInput) * currentGearRatio * finalDriveFront;
    Then because I want to simulate the clutch, free reving and launching from neutral, I don't immediately set the engine RPM to wheel RPM (since wheel RPM will be 0 when launching so it's going to be pointless, no torque), instead I set the engine RPM to move slowly to the worked backward RPM from wheel. That way when launching from 0, the engine RPM will slowly move down, and provide torque (by looking up curve) until the wheel spin and can give RPM that can be worked backward for engineRPM, shown here:
    Code (CSharp):
    1. rpmToEngine = Mathf.Abs(((RR.rpm + RL.rpm + FL.rpm + FR.rpm) / 4.0f) * Mathf.Abs(currentGearRatio) * ((finalDriveRear + finalDriveFront) / 2.0f));
    2.                     targetRPM = rpmToEngine;
    3.                     //trying to simulate engine friction when clutch contact drivetrain
    4.                     //engine rpm slowly decrease but still sending torque to wheel until wheel rotate at enough speed
    5.                     //to fully engage clutch without stalling
    6.                     currentEngineRPM = Mathf.MoveTowards(currentEngineRPM, rpmToEngine, (Time.fixedDeltaTime) * Mathf.Abs(maxRPM - minRPM));
    So I only want to do that when launching from 0, other times I will get engine RPM directly from worked back wheel RPM.
    My problem now is sometimes when in low speed or low gear, the tires slip, and the wheelcolliders RPM just jump all over the place (I'm talking about jumping up and down in 6000 to 4000 range), resulting in a super weird and unstable engine RPM. When the car reaches high speed (or stable grip), the RPM return to normal range.
    My full code shown here, this time for RearWheelDrive"
    Code (CSharp):
    1. if (currentGear != 0 && clutchInput < 1)
    2.                 {
    3.                     if (currentGear <= 1 && currentGear >= -1)
    4.                     {
    5.                         float rpmToEngine;
    6.                         currentWheelRPM = ((RL.rpm + RR.rpm) / 2.0f) * finalDriveRear;
    7.                         rpmToEngine = Mathf.Abs(((RL.rpm + RR.rpm) / 2.0f) * finalDriveRear * Mathf.Abs(currentGearRatio));
    8.                         targetRPM = rpmToEngine;
    9.                         //simulating when clutch contact drivetrain
    10.                         //engine rpm slowly decrease but still sending torque to wheel until wheel rotate at enough speed
    11.                         //to fully engage clutch without stalling
    12.                         currentEngineRPM = Mathf.MoveTowards(currentEngineRPM, rpmToEngine, (Time.fixedDeltaTime) * Mathf.Abs(maxRPM - minRPM));
    13.                         currentTotalEngineTorque = lbftToNm(torqueCurve.Evaluate(currentEngineRPM) + modTorque);
    14.                     }
    15.                     else
    16.                     {
    17.                        currentEngineRPM = Mathf.Abs(((RL.rpm + RR.rpm) / 2.0f) * finalDriveRear * Mathf.Abs(currentGearRatio));
    18.                         currentTotalEngineTorque = lbftToNm(torqueCurve.Evaluate(currentEngineRPM) + modTorque);
    19.                     }
    20.                 }
    21.              
    22.                 else
    23.                 {
    24.                     // Neutral gear, simulate the engine idle.
    25.                     currentEngineRPM = Mathf.MoveTowards(currentEngineRPM, maxRPM, engineAccel * Time.deltaTime * throttleInput);
    26.                     if (throttleInput < 0.07)
    27.                     {
    28.                         //if no throttle decrease RPM
    29.                         currentEngineRPM = Mathf.MoveTowards(currentEngineRPM, minRPM, (engineAccel / 2f) * Time.deltaTime);
    30.                     }
    31.                 }
    If I omit (if (currentGear <= 1 && currentGear >= -1)) part then just let the engine RPM to slowly reach the target in every gear (except 0 of course), it's a bit better (still jumping, "vibrating" around but in lower range), but introduces delay and not very realistic engine behaviour (since engine RPM and wheel RPM are not in sync). Also right now there is no engine braking simulation.
    Would you mind giving me a direction on how I can improve/fix this? Or just another way of working out the engine RPM?
    I would really like to get help on this, as this is the last part of the puzzle I have to solve in order to complete my project.
     
    Last edited: Nov 30, 2016
  7. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    No no no, that was the poorest presentation about car simulation I've seen ever. I was personally there at Unite Europe 2016. It was a total loss of time to most people that assisted. There was a guy in the front row eager to take notes at his laptop. As the time was passing he eventually lifted the hands off the keyboard, later he closed the laptop and packed it away. It was pretty obvious he wouldn't get anything useful. That was the general feeling in the room.

    Implementing an engine and powertrain where everything is correctly simulated and produces every expected behavior is very complex. It won't fit in a handful of lines of code. So you should find a simplified model that mostly fits with the main behaviors you want to simulate.

    For example, the PhysX approach is built around the clutch itself:

    From http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/Vehicles.html
    You may develop the engine at one side of the clutch, and the wheels and driveline at the other side. If clutch is engaged (open) then both parts can rotate freely. If clutch is disengaged (closed) then both parts must rotate at the same exact rate.

    Still, the problem with the WheelColliders is that they don't provide enough information for building a proper system. Maybe the PhysX approach somewhat works because they've coded it, but that part is not exposed to Unity. I'm not even sure that WheelCollider.motorTorque will provide the equivalent force to the vehicle via tire force.
     
  8. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Thank you for your reply.
    About that presentation, what you've said was also my feeling about the presentation. I can't get anything useful out of it since it only recited what's in the API, and there was no solid example of implementation.
    I also took a (very close and long) look at PhysX approach of engine simulation when I first initialize the project, and wonder why Unity doesn't expose all those useful parts and left us with only wheelCollider.motorTorque. Then because of that I have to follow the "Unity" way of implementing it. And I went around Unity forum and a number of threads said that rigidBody mass doesn't really affect wheelCollider's such as acceleration or tire grip, it's just for calculating how far that rigidBody will fly if it hits another. What are your thoughts on this?
    Is there a way to directly implement PhysX and bypass Unity's ?
    Also would you mind sharing some examples or sources for a simplified model of engine simulation? It doesn't need to be exact code, just theory is perfect, just need to be in terms of using Unity's components.
    That makes me thinking about Project Cars, a game that uses Nvidia's PhysX, I'm wondering if they used PhysX vehicle simulation? Cars in that game drive like boats though.
     
  9. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    In terms of suspension, the rigidbody mass doesn't affect the contact depth of the suspension at rest. That value (contact depth at rest) is imposed with the parameter targetPosition, which is physically meaningless. PhysX does that as consequence of their arbitrary (and wrong) interpretation of the "sprung mass model", and causes most of the adverse effects and unrealistic behaviors typically observed in the WheelCollider.

    In terms of tire friction and grip, again, I've been unable to extract any logic out of the stock WheelCollider, so I implemented my own physically coherent tire friction model.

    Not to my knowledge.

    There's no need to use any Unity components for simulating an engine. The simplest model is just a rotational mass of inertia I that rotates at an angular velocity w. Applying positive torque to it increases the angular velocity. This would be the torque applied as per the throttle. Applying negative torque decreases the angular velocity. This would be the engine friction. Combine both torques results in a final torque that modifies the angular velocity of the engine. The maximum torque may also made dependent of the actual angular velocity (here you have the engine's torque curve).

    I don't think so. The wheel model in Project Cars was widely announced as a complex set of elastic points simulating the rubber in the tires (or something like that). If they use PhysX then surely use it for the rigid body simulation, and maybe for the suspensions. I haven't tested the game but if it happens as you say, then their model hasn't been a good approach either.
     
  10. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Thank for your reply. At first I was going to use this approach. I used Inertia = 1/2 (mass * radius^2) to find the inertia of the wheel. Then from , I get the Reflected load inertia to the engine by Jreflected = Jload/(gearRatio ^ 2). Jload would be the inertia of the wheel, and Jreflected would be the inertia of the engine.
    Or I can do this. I have Torque (angular momentum) = RotationalInertia * rotationalSpeed(angular velocity). Then by looking at torque curve or specs, I know the maximum torque at a certain RPM, then that can be used to work out rotationalInertia of the engine.
    However, I was stuck with one problem, where I need to figure out the engine RPM. At 0 RPM there is no torque, so I can't increase RPM just by torque if I were to use the torque curve. Also RPM needs to increase at a certain rate, which is the engine acceleration, and I don't know how to implement this. As the torque simulation depends on RPM, I went into deadend, so I followed the Unity way of doing thing.
    My approach above might be wrong even in foundation, and there are lots of formula that I don't know. Would you mind helping me on this one?
    And also I don't know the formula to get engine friction and to simulate engine brake horsepower when releasing the throttle.
     
  11. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Why the torque at 0 rpm is an issue? You control that, so you can put any torque you want. I have an option for a non-stalling engine which generates a torque curve providing torque at any rpms, even negative ones. On a more realistic approach, there's the torque from the starter engine as well, which provides torque until the engine reach the rpms where it can produce the combustion torque.

    The formulas are the basic rotational kinematics and rotational dynamics. They are just equivalent to the standard kinematics and dynamics. Here are some courses:


    All the formulas are here:

     
  12. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    I think I just broke a 1000W light bulb after you gave me the equations
    So this is what I'm going to do, it's going to be long and boring with just formulas, so please forgive me for that.
    My equations will contains these formulas and known variables:
    Known:
    - Inertia: Calculated from specs to get inertia of engine. Once the clutch contact the drivetrain, update this in relation to clutch force percent to get the inertia of the whole system (including wheels and drivetrain)
    - Torque: Look at torque curve
    - deltaTime: time.fixedDeltaTime
    Unknown:
    - Angular Acceleration
    - RPM (angular velocity)
    Formulas:
    Torque = Inertia * Accel
    RPM = (deltaTime * Torque) / Inertia
    AngularAccel = deltaRPM / deltaTime
    Now here is my calculation for engine RPM, independent from wheel RPM
    Code (CSharp):
    1. //keep the free-reving part to get initial RPM and feed into this
    2. //here is when clutch contacted after free reving to certain RPM
    3. inertia = GetInertia();
    4. currentTorque = torqueCurve(RPM) * throttle;
    5. //once got torque, get engine angular acceleration
    6. currentAccel = currentTorque / Inertia;
    7. //got acceleration, find delta angularVelocity to predict the RPM of the next frame (or next physic calculation step rather)
    8. deltaRPM = currentAccel * time.fixedDeltaTime;
    9. //once got the delta RPM, feed to the RPM of the next frame
    10. RPM += deltaRPM;
    11. //clamp so RPM doesn't go over max
    12. if (RPM > maxRPM) RPM = maxRPM;
    13. //end frame, RPM got feed into lookUpTorqueCurve(RPM)  at the beginning of next frame, then got new torque, take new torque and begin new RPM calculation.
    I know this is wall of text TL;DR but please take a look and verify that my formula is correct. Although I have the above formula, I'm still facing the problem of chicken and egg, where I need RPM to get the first torque and predict the next frame's RPM, and I need torque to calculate RPM.
    And that's just acceleration. I need to figure out deceleration so the RPM will drop when no throttle is applied. I really need your help on this
    Heck I even need to figure out how to calculate the inertia of the whole system with drivetrain and wheels
    Once again, thank you very much and please look over my solution.

    Oh about the tire friction curve, I actually brought the documentations to my physic professor and she said the slip ratio doesn't make much sense, since if the slip ratio is 0 then the wheel is spinning without slipping and should give full force, not 0, based on the definition of slip ratio being (wheelVelocity/bodyVelocity - 1). It would make more sense if 0 is full slipping where the wheel doesn't contact the road at all, just spinning and give no force. So she asked me to research more on how the slip ratio is defined in PhysX. Would you mind explaining how slip is calculated in PhysX and its unit to me?
     
  13. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    The piece of code looks ok to me.

    Just apply a negative torque that causes a negative angular acceleration to decrease the RPMs.

    I have no idea at all. I tried to make some sense of slip vs. angulaVelocity vs. tire forces in PhysX but I was unable to extract any logic out of them.
     
  14. NDSno1

    NDSno1

    Joined:
    Dec 20, 2014
    Posts:
    223
    Thank you very much for your reply.
    Right now I'm stuck at the step where the clutch contact the drive train. Because of the added Inertia from the wheels, the RPM would decrease (same thing when up shifting) . However with my solution above, the deltaRPM would always be positive. I need to find away to figure out the sign (direction) of angularAcceleration. Would you mind helping me with this one?
    Also can you help me figure out the relationship between clutch force and RPM (or inertia)? From my understanding, there will be friction between the clutch and the drive train, so working back from wheelRPM to get engineRPM would not be 100% correct. When launch from 0 (or torque from engine is too high), even though they are in contact, the clutch would spin at different speed from the drive train due to the friction. So roughly here is my "code":
    Code (CSharp):
    1. //figure out inertia
    2. void GetInertia()
    3. {
    4. totalInertia = (loadInertia/(GearRatio^2) ) * (clutchInput * clutchForce) + engineInertia
    5. }
    So (loadInertia/(GearRatio^2) ) + engineInertia would be total inertia, which is LoadInertia over gear system, plus engine inertia. Multiply LoadInertia by the fraction of clutch force, so that when the clutch is fully disengaged, only the engineInertia remains. I need to figure out where to put friction in the equation. Can you help me out?

    Another quick question: I don't understand how wheelDamping value in wheel collider works? Would you also mind explain this to me? I've googled the keyword but can't find anything that is wheel - related, all I could find was suspension damping.

    Again, thank you so so much. I know you are super busy with work, especially with finishing up Vehicle Physic Pro, yet you're still spending time answering my questions.
    P/s: by the way I took a look at some Unreal Engine Vehicle stuffs and the physics look great for a built-in asset. They have simulation for engine and transmission, differential built-in. The tire friction model is still meh but easier to understand. I just need more time to understand the blueprint model and how to setup the animation stuffs. After finishing this project I'll jump over to Unreal and try out their vehicle physic.
     
    Last edited: Dec 14, 2016
  15. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    After that comment decided to watch it. You're not wrong... that was pretty terrible.
     
    Edy likes this.