• 14
• 12
• 9
• 10
• 13

How to create a suspension model with 2 springs?

This topic is 1398 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Basically I want to create a suspension that has 2 springs with 2 seprate compressions, one spring is actually for the tire.

I am keeping things simple, so its only the vertical action(raycast for example)

As far as I know and wich works quite well, is this method:

• create a raycast with a length of:
rayLength = suspensionTravel + radius; // (so it's basically something like 0.2 + 0.3 = 0.5)
rayHit = CreateRay(rayLength,suspensionPosition);
• calculate the compression like this:
prevCompression = compression;
compression = (suspensionTravel - (rayHit.distance - radius));
• calculate vertical force like this:
springVelocity = (compression - prevCompression)/timeStep;
springForce = springRate * compression; // springRate is something like 50000
damperForce = damperRate * springVelocity; // damperRate is something like 2500
totalSpringForce = springForce + damperForce;

Now I'd like to know how I'd add a secondary spring to the same raycast?
The difficult part for me, is to know how to calculate the secondary compression(tire deflection in this case) ?
And how to combine these 2 compressions, so that they would have theyr seprate functionality?

Share on other sites

For the tire deflection should I do something like this?

prevTireDeflection = tireDeflection;
tireDeflection = (radius - (rayHit.distance - (suspensionTravel + rimRadius)));

If this is the right way, then how to make it so that the tire 3d mesh can "sink" into the car to represent a flat tire etc. ?

Share on other sites

Sorry. Messed up the derivation and deleted a bunch of incorrect equations. In any case, the situation is as shown. The previous positions are immaterial. At any point in time, where D is the distance from the suspension arm to the ground (your raycast from the suspension arm to the ground), the point between the springs (spring and tire) is (momentarily) at rest and, because it's at rest, the force from spring1 = force from spring2.

I have to run - will update later if I can. Apologies.

[attachment=21736:two-springs.png]

D = x1 + x2

Given x1rest as the "rest" position for spring1, the force for spring1 is (x1rest - x1)*k1. Similarly for spring2.

(x1rest - x1)*k1 = (x2rest - x2)*k2

k1*x1 = k1*x1rest - (x2rest - x2)*k2

x1 = D - x2

k1 * (D-x2) = k1*x1rest - (x2rest-x2)*k2

Solve for x2, as k1, k2, D, x1rest and x2rest are known.

EDIT: gather knowns on one side of the equation as follows:

k1*D - k1*x1rest + k2*x2rest = k1*x2 + k2*x2 = (k1+k2)*x2

-or-

x2 = (k1*D - k1*x1rest + k2*x2rest) / (k1+k2)

x1 = D - x2, and you have the point between the tire and the spring, where x2 would be the "squashed" radius of the tire.

The upward force on the car (at the suspension point) is either k1*x1 or k2*x2.  If that upward force is less than the downward force (primarily due to m*g) then the car when "accelerate" downward, and D will decrease until k1*x1 = downward force.

To make the tire go flat, just decrease k2 (proportional to air pressure) and solve again.

Edited by Buckeye

Share on other sites

Thanks for the math Buckeye! But I have a few questions, mostly what's the "dynamical" ray length?
Here I see these:
D - maxLength/rayLength
x1 - springDeflection/compression/travel
x2 - tireDeflection
k1 - springRate
k2 - tireRate
x1rest - resting suspension position (half the actual spring length?)
x2rest - the rim radius ?

So using your algebra I get this:

rayLength = compression+tireDeflection; // should this be the actual ray length after the ray is created i.e. hit.distance?

totalSpringForce = springRate * rayLength;
staticSpringForce = springRate*springRestLen;

tireDeflection = (totalSpringForce  - staticSpringForce  + staticTireForce) / (springRate+tireRate);
compression = rayLength - tireDeflection; // tireDeflection should be the dynamic radius wich is close to the actual loaded radius

springForce = (springRestLen - compression)*springRate;
// springForce = tireForce ... if so, then I dont have to add them together to act on the rigid body right?
// and if one of the forces contains a static weight, I have to add it to the other aswell i.e. wheel mass?

upwardforce = springRate*compression; // the load on wheel

I added some questions to the comments but here are my other questions:

Are x1rest & x2rest the actual lengths(spring length and wheel radius (rim+sidewall)) or the resting positions?

Do I define the actual ray length as x1rest+x2rest or maxTravel+wheelRadius?

And what part of the math is for tire sidewall height?

Also, how could I make it so that tire pressure (wich would be a part of calculating tireRate) would change the wheel load, because right/under- &over-inflated tires behave differently, so I'm not sure that "springForce = tireForce" is always the case. Now I can think of a pressure ratio to multiply the actual wheel load, or is there another way to do this?

Edit:
I found this page, seems to be the same stuff, but more documented, I'll see what I can come up with...

Share on other sites

I'm having a little trouble translating your variable names to what they are in the "real world."

Hopefully I can expand a little.

In my equations:

D is the distance between the top of the suspension spring and the ground. That is, I assume the spring is attached to the chassis at the top. I assumed (perhaps incorrectly) that you cast a ray from the top of the spring to the ground.

D therefore represents the length of the compressed spring plus the distance between the center of the tire and the ground. Half of the "compressed" tire is shown at the bottom of the compressed spring.

[attachment=21740:spring-and-tire.png]

The term x1rest is the uncompressed length of the spring. That is, if you let any spring relax (no compression or stretching), it will be of a certain length. That is the "rest" or "relaxed" length of the spring. If you push or pull on the spring (compress it or stretch it), it takes force to do so. That force = -k * dx,  where k is the spring constant, and dx is the displacement from the relaxed length, in either direction from the rest length. The force is shown as negative because the force will be in the opposite direction of the movement. It always resists being compressed or stretched. E.g., if a relaxed spring is one meter long, and you compress it to a length of 90 centimeters, the force it takes to do that is: F = -k * 10cm.

I am always characterizing the tire (from the center of the wheel to the ground) as a spring. If you inflate a tire to some pressure, it will have a certain radius. That equivalent to the equivalent spring's relaxed length. If you try to compress the tire, it takes force which I am modeling as a spring. The force = -k * dx, where k is modeled as proportional to the tire pressure, and dx is the difference in the relaxed radius and the compressed radius.

Hope that helps a bit.

Edited by Buckeye

Share on other sites

I cant get it working, the vertical force sticks the car to the ground or pushes it away intensely, causing it "pumping" on the surface

heres my code sofar:

		float x1,x2;	// position
float v1,v2;	// velocity
float F1,F2;	// force
float D1,D2;	// damper
float L1,L2;	// how much is stretched

float w1,w2;	// width
float k1,k2;	// spring constant (springRate)
float b1,b2;	// damping constant (friction)
float R1,R2;	// rest length of springs

w1 = maxTravel; // block 1 width, should this be the static spring length or not?
w2 = 0;
R1 = 0.08f;
R2 = 0.0f;
k1 = 55000.0f;
k2 = 111000.0f;
b1 = 2000;
b2 = 1000;

//x1
lastCompression = compression;
compression = (hitDistance - tireDeflection);

//x2
lastTireDeflection = tireDeflection;
tireDeflection = (k1*hitDistance - k1*R1 + k2*R2) / (k1+k2);

L1 = compression - R1;
L2 = tireDeflection - compression - w1 - R2; // from http://www.myphysicslab.com/dbl_spring1.html

F1 = -k1 * L1;
F2 = -k2 * L2;
v1 = (compression - lastCompression) / deltaTime;
v2 = (tireDeflection - lastTireDeflection) / deltaTime;
D1 = v1 * b1;
D2 = v2 * b2;
force = -(F1+D1)+(F2+D2); // F1 negative = car jumps, F1 positive = car sticks



I suspect the problem is in L2 or tireDeflection...

Share on other sites

It would help if you describe what each of your variables represents. maxTravel? compression? hitDistance? Without knowing how you determine/define those, it's difficult to compare to the model. Can you describe how you're relating variables to my equations, for instance, D = x1 + x2, etc.?

Also, it hasn't been mentioned before, but you'll probably have to model the shock absorber, also. Without damping, you'll likely get oscillation. That is, if you deflect a spring and let it go, it'll bounce up-and-down forever. And damping is where your velocity will come into play. The shocks provide a resistive force proportional to velocity2. EDIT: It looks like you're applying it as proportional to v, rather than v2. And you're not checking the sign of the velocity. In general, the direction of the motion shouldn't come into play, only the magnitude - which would be taken care of with the square.

Also, ensure the signs of all your factors are correct.

force = -(F1+D1)+(F2+D2)

That's sort of confusing. One factor is negated, and the other is not. I suggest you check that you're equations are correct as they should both be applied similarly.

Edited by Buckeye

Share on other sites

maxTravel is the spring static length, 0.2 for example

rayLength is the total ray length, radius+maxTravel 0.3+0.2=0.5 etc.
compression is x1 in your code

tireDeflection is x2 in your code
hitDistance is the distance where ray has a contact, from suspension position to contact point(road) should be D in your code? Or should it be inverse (raylength-hitDistance)?

And I have dampers for both springs, D1 and D2 are the dampers, b1 and b2 are the damping coefficients.

v1 and v2 are the spring velocities.

The thing is that I can get one spring work just fine when I use inverted "D" (raylength-hitDistance) and positive spring rates, it works just fine with a single spring, but when I make it a double spring, it gets messed up tires jump around like they have 1000psi in them. If I lower the tire spring rate (k2) nothing changes, there is no "inflation" effect... I just get rid of the tire spring...

Share on other sites

hitDistance is the distance where ray has a contact, from suspension position to contact point(road) should be D in your code? Or should it be inverse (raylength-hitDistance)?

EDIT: D in my code is the distance from the top of the suspension spring to the bottom of the tire. I'm avoiding using your terms as I'm not sure what you mean by "suspension position."

            compression = (hitDistance - tireDeflection);

//x2
lastTireDeflection = tireDeflection;
tireDeflection = (k1*hitDistance - k1*R1 + k2*R2) / (k1+k2);

?? You're using tireDeflection in your compression equation before you calculate it.

Also, you've defined R2 = 0. Are you using R1 and R2 as the static lengths?

EDIT2:

v1 and v2 are the spring velocities.

..which, as you calculate them, may be negative or positive. Not good. Shock absorber resistance is proportional to the magniture of the square of the velocity, and is not dependent on the direction of travel.

EDIT3: It appears you're using the equations I posted without understanding the sequence. What I posted is not copy-and-paste - it's a derivation. Big difference.

Edited by Buckeye

Share on other sites

Sorry, by suspension position I mean the body contact position.

The tireDeflection was used before calculation because its in a loop and it doesnt make a huge difference in this case, the last frame will be used (the variables are globaly deffined)

R1 and R2 are static currently yes, should they be dynamic?