Questions on a vehicle controller - Torque and RPM on an Articulation Body

Hi all,
I'm trying to write yet another vehicle controller. I've created a power train that "sends power" to each driving wheel. I'm having an issue where no matter the calculations I do, the vehicle never goes faster in higher gears, only goes slower because of the "real life" calculations of the engine.

I am using Sphere colliders with articulation bodies on them to act as custom wheels. This way I am able to get the contact points and have a little more control over them (for example, driving big wheels upside down and gaining an average direction based on contact points).

As an example, my engine at 8000rpm and 333hp produces about 218ft-lb of torque. The first gear ratio 4.23 and a final drive ratio of 3.62. This should produce 522rpm and 1669ft-lb of torque to each wheel (218 * 4.23 * 3.62 = 3338 / 2).

Because I am using Sphere colliders, I am figuring I will have to use AddForce to each drive wheel to push the car forwards. I have tried many different approaches from here; applying force simply using AddForce with the torque output, applying force with watts, finding angular velocities, getting force in newton meters, using ForceMode.Acceleration, comparing expected speeds, etc.

All of these come up short when it comes to shifting to the next gear. Once I shift, because the RPMs increase but the torque decreases, I am not able to go any faster when using solely torque and am actually going slower than the previous lower gear. I've been working on this issue for days now.

I'd like to simulate this relatively realistically, but I cannot figure out how to realistically push the car forward to get to the correct speed.

I have my torque curve based off of maximum HP, RPM and a power curve (Red is HP and Blue is Torque)
9845775--1417029--upload_2024-5-20_17-30-44.png

// In Newtons
inputTorqueNm = inputTorque * 1.35582f;

// Get the tractive forces for later when I want the wheel to spin
tractionMax = frictionCoefficientMax * weightSupported * 9.80665f;
tractiveForce = inputTorque / wheelRadius;

// If the expected RPMs are higher than the current RPMs, need to check torque
expectedWheelRPM = inputRPMs;
expectedWheelSpeedMps = inputRPMs * wheelRadius * (2 * Mathf.PI / 60);

currentWheelRPM = articulationBody.velocity.z * 60 / (wheelRadius * 2 * Mathf.PI);
currentWheelSpeedMps = currentWheelRPM * wheelRadius * (2 * Mathf.PI / 60);

// Find resistive forces for later.
roadGradientRadians = Mathf.Acos(Vector3.Dot(averageDirection.normalized, Vector3.forward));
rollingResistance = 0.015f * weightSupported * Mathf.Cos(roadGradientRadians);
dragResistance = 0.5f * airDensity * dragCoefficient * frontalArea * Mathf.Pow(currentWheelSpeedMps, 2);

I've looked through many different ways, though I feel they either do not address the torque or they do not address the RPMs. I do not want to use a linear speed percentage to reduce the Acceleration force, but I want the calculation to "wind out" the gear.

I may have just been looking at this for far too long and am probably missing something simple, but any help is accepted. TYIA!

AddForce is the correct way to apply the tire forces to the vehicle's Rigidbody.

Recommendation: always use SI units in your calculations, so they will be coherent with Unity's world and physics units. You may configure the engine parameters in your own units if you like, but always convert them to SI before using them in any further calculation.

As for your description of the issue, I can think on several possible causes:

  • The rolling resistance and/or drag resistance are preventing the car to gain speed.
  • The physical friction of the sphere colliders with the ground is dragging the vehicle.
  • The total mass of all the rigidbodies and articulation bodies is larger than the expected total mass of the vehicle.

First, I'd try validating your powertrain calculations like this:

  • Don't apply any resistance (drag, rolling) or friction.
  • Ensure that the physics material assigned to the sphere colliders applies no friction (zero coefficients, "Multiply" combination).
  • Apply the wheel forces with AddForce in Newtons. Keep track of all the forces applied to the vehicle and the total resulting force.
  • Measure the acceleration of the vehicle in m/s/s.

When everything is correct, then F = m·a should be coherent with your results. The measured acceleration should be the sum of the forces you've applied divided by the total mass of the vehicle (all rigidbodies and articulation bodies).

Once this part is validated and you're 1) applying correct force magnitudes from the powertrain to the wheels, and 2) measuring an acceleration coherent with those forces and with the total vehicle's mass, then you can start working on simulating realistic drag and rolling resistances.

Thank you for your reply! Judging by your signature, you're just the person to talk to. Just to update the information on a few things;

  • I haven't implemented the resistances yet, they are set and ready for later
  • I have double checked the sphere collider's material and made sure it's set to zero for all fields.
  • In the root script (not mentioned of course), I calculate all masses in children and have a vehicleMass variable

When you say "The measured acceleration should be the sum of the forces you've applied divided by the total mass of the vehicle", I want to make sure I'm understanding this correctly. With the example numbers above,

  • my engine at 8000rpm produces about 218ft-lb of torque or 295nm.
  • With the first gear ratio 4.23 and a final drive ratio of 3.62 the wheels should be receiving an equal share of 4517nm of torque (I'm not worrying about limited slip or anything yet, just a locked diff) - So each wheel should be supplied 2258nm of torque.
  • The vehicle has a mass of 2040kg
  • The wheel radius is 0.42m

So taking these numbers into account, to use in AddForce with ForceMode.Acceleration, would I use `acceleration = force / mass?

If I'm following the Unity units here,

  • Mass = 2040kg
  • Force = input torque / wheel radius = 2258 / 0.42 = 5,376nm
  • Acceleration = force / mass = 2.63?

an acceleration force of 2.63 is extremely small. I think my unit conversions are incorrect. My acceleration measurement is showing 0.021 in the forward direction. I'm unsure as to where I'm going wrong here? Should I be recalculating the force to Force = Mass * Acceleration where I get acceleration from above? When I do this, I get numbers around the same as double the torque.

Sorry for my ramblings, I might need to take a step away for a while because I have a feeling I'm missing something very simple.

I've done some more reading and looking into using the acceleration forcemode. Here is the math I've come up with which seems to match other calculators. (Adjusted maximum and redline RPM a bit). All calculations are made at 7100rpm

  • Engine Torque = 246ft-lb || 333Nm
  • 1st Gear Ratio = 4.23

  • Transmission Torque = 4.23 * 333Nm = 1408Nm

  • Final Gear Ratio = 3.62

  • Axle Torque = 1408 * 3.62 = 5096Nm

  • Vehicle Mass = 2024kg (added all child masses to root)

  • Wheel Radius = 0.42m

With those numbers set I get

  • Force (In Newtons) = Axle Torque / Wheel Radius = 5096/0.42 = 12,133N
  • Mass = 2024kg
  • Acceleration = Force / Mass = 12,133N / 2024Kg = 5.99m/s/s

So the question is; Do I just plug the Acceleration value into the AddForce with ForceMode.Acceleration? When I try this, the vehicle moves extremely slowly. Is it because the Force needed for ForceMode.Acceleration takes a different type of value?

EDIT: I've just found that I get a more realistic acceleration when I use AddForce on the vehicle's main articulation body rather than the wheel's articulation body. I'm not sure why this would be the case since I have the same acceleration force either way?



No to both questions. Do not use ForceMode.Acceleration, as this will impose the resulting acceleration to the rigidbody bypassing its mass. Always use AddForce or AddForceAtPosition with the calculated tire force in Newtons.

The number of drive wheels is missing here. Assuming you have two drive wheels, then each one would apply 12,133 / 2 = 6066 N.

If you use AddForceAtPosition (without any ForceMode parameter) on each drive wheel with 6066 N, then you should measure an acceleration of 5,99 m/s/s in the vehicle's rigidbody.


The correct application point for the tire forces is the contact point with the ground. However, for simplification, the result should be the same applying the forces at the centers of the spheres acting as wheels (easier).

Note that only using AddForce in a rigidbody will apply the force at its center of mass. If you haven't sent the center of mass explicitly, then it will use a center of mass calculated out of the colliders assigned to the rigidbody. It's better to use AddForceAtPosition and specify the precise position you want the force applied at.

[quote=“Edy”, post:5, topic: 947987]

[/quote]

[quote=“Edy”, post:5, topic: 947987]
Do not use ForceMode.Acceleration, as this will impose the resulting acceleration to the rigidbody bypassing its mass.
[/quote]
In my experiments, when I use ForceMode.Acceleration, I make sure to divide by the mass.

forceInNewtons = inputTorqueNm / wheelRadius;
acceleration = forceInNewtons / weightSupported;

This gives me the correct acceleration numbers, though I was still trying to figure out how to apply it to the smaller articulation body. I’m not sure exactly how ArticulationBodies are different than RigidBodies besides the fact that they come with their own articulations/joints and are automatically child/parents of each other, but when I do the math for acceleration and apply it to the wheel’s articulation body, it only affects the wheel’s mass of 15kg, rather than the vehicle’s mass at ~2000kg.

If I were to use ForceMode.Force, I have been struggling to calculate the amount of force needed to go faster in higher gears, since the torque is reduced at each subsequent gear.

[quote=“Edy”, post:5, topic: 947987]
The number of drive wheels is missing here. Assuming you have two drive wheels, then each one would apply 12,133 / 2 = 6066 N.
[/quote]

You are correct, in my haste to try to make this question simple and straightforward to read, I didn’t get into the specifics of how I’m getting to the final torque numbers. I have a series of scripts, starting at the vehicle controller > Engine > Transmission > Transfer Case > Axle > Suspension > Steering > Wheel. The torque “travels” through each component, multiplying the torque and dividing the RPMs along the way based on gear ratios and eventually differential and AWD math. The final output is currently at the Axle (and assuming a closed diff), I do divide the torque by 2 and supply it to each wheel. Thank you for mentioning this as something I need to take account of!

[quote=“Edy”, post:5, topic: 947987]
If you use AddForceAtPosition (without any ForceMode parameter) on each drive wheel with 6066 N, then you should measure an acceleration of 5,99 m/s/s in the vehicle’s rigidbody.
[/quote]

You’re correct and just for my benefit to keep wrapping my head around this: 333 * 4.23 * 3.62 / 2 = 2548Nm of torque to each wheel. Converting that torque should be 2548Nm / 0.42m = 6066N of force for each wheel.

When I apply exactly 6066N to each wheel ```
articulationBody.AddForceAtPosition(transform.parent.forward * 6066 , transform.position, ForceMode.Force);


```csharp
currentVelocity = articulationBody.velocity;
acceleration = Vector3.Dot((currentVelocity - previousVelocity) / Time.fixedDeltaTime, transform.parent.forward);
maxAccel = (acceleration > maxAccel) ? acceleration : maxAccel;

Side note: I’m using transform.parent.forward because the wheel is spinning and forward changes every revolution.

If I apply the force to the vehicle itself, I get a max acceleration of 3.2m/s/s on the root body using ```
vehicleSetupWizard.articulationBody.AddForceAtPosition(transform.parent.forward * 6066 , transform.position, ForceMode.Force);


[quote="Edy", post:5, topic: 947987]
The correct application point for the tire forces is the contact point with the ground.
[/quote] 
I am using the sphere colliders and collecting the contact point data. This was my original plan, but I do have math giving me an average direction to use for the center of the wheels for now.

[quote="Edy", post:5, topic: 947987]
Note that only using AddForce in a rigidbody will apply the force at its center of mass. If you haven't sent the center of mass explicitly, then it will use a center of mass calculated out of the colliders assigned to the rigidbody. It's better to use AddForceAtPosition and specify the precise position you want the force applied at.
[/quote] 
This is great information. I did not know it would apply it at the center of mass! I will be using AddForceAtPosition from now on to get the right position.

So, all of this leads me to the final issue. Let's assume that my numbers actually came out correctly (which I will have to go back and figure out what's going wrong to fix). If I'm using torque alone, each subsequent gear shift will reduce the amount of force being applied to the vehicle because of the reduced gear ratios. What is the calculation to accumulate the force appropriately so I have more force in higher gears?


That may work in some specific cases and situations, and also in the theoretical cases, but it's not a generic solution in any way. Whichever mass you're using, it's purely speculative. Mass of the wheel body the acceleration is applied to, mass of the main body, total mass of the vehicle? With several drive wheels, how much mass each wheel is "responsible" for?

Wheels apply a force to the vehicle, and the resulting acceleration depends on the setup and conditions of the situation. That's how it works in reality.


This denotes some underlying problem. I'd discard everything about the powertrain, ratios, etc and focus on this issue exclusively. I'd start with something very very simple: a single rigidbody, no frictions, no drag, etc. Apply a constant force to it and measure the resulting acceleration. That must give you the correct value with total precision. If it's necessary, make it ignore the gravity and lock its rotation.

When you get the correct measures with an absolutely basic example, then add a piece complexity (restore gravity, for example), and measure it again. Repeat adding one change each time and measure the acceleration right afterwards, reconstructing the complex case (multiple colliders, articulation bodies, etc). At some point the measurement will become wrong. Then you should have the cause in front of you, and you could work on fixing it.

Once you have your vehicle entirely rigged, and applying a known force to the wheels results in the expected acceleration, then you could move forward and implement the powertrain, which in the end will output a force you could apply to the wheels and get the expected results.


There's no such accumulation. Torque from the engine translates to torque in the wheels applying the ratios (gear, differentials, etc), and it's converted to force in the wheel using its radius. There's nothing else here. That's why it's so important to verify that when you apply an arbitrary force to your physics rig, it accelerates at the expected precise rate.

If all the calculations and the measures are correct, and the acceleration you receive is still not enough, then the setup of the car won't be correct. Ratios may be too small, engine torque may be too low, there may be too much drag, etc.

I am currently working on this and will update when I find something. Thank you!

1 Like