Implementation help of pacejka longitudinal friction

Started by
11 comments, last by IdleBrick 1 year, 4 months ago

Hi, I was wondering if I could have some help with implementing pacejka longitudinal friction, I have successfully implemented pacejka lateral friction and it works how I need it to now its just longitudinal friction I need for doing burnouts in vehicles and I don't know how to implement it with the formulas I have found on the internet.

This is my pacejka function

pacejka = function(slip, surface)
	if surface then
		local x = slip
		local b = surface.Stiffness -- Stiffness
		local c = surface.Shape -- Shape
		local d = surface.Peak -- Peak
		local e = surface.Curve -- Curve

		return d * math.sin(c * math.atan(b * x - e * (b * x - math.atan(b * x))));
	end
	return 0
end

And here's a snippet of my implementation of lateral friction

local WheelVelocity = self.GetPointVelocity(self.Engine, attachPosition + attachDirection)
local RelativeWheelVel = force.WorldCFrame:VectorToObjectSpace(WheelVelocity)
		
self.angularVelocity[force.Name] = (RelativeWheelVel / (math.pi*2) * self.WheelRadius)
		
local lateralVelocity = RelativeWheelVel.X
local longitudinalVelocity = RelativeWheelVel.Z
		
local slipAngle = math.deg(math.atan2(lateralVelocity, math.abs(longitudinalVelocity * self.stopWheels)))
--local slipRatio = ((Weld.Part1.RotVelocity.Z * self.WheelRadius) - longitudinalVelocity) / math.max(math.abs(longitudinalVelocity), 0.00001)
		
local pacejkaLatValue = self.pacejka(slipAngle, self.wheelSurface[force.Name]);
--local pacejkaLongValue = self.pacejka(slipRatio * 100, self.wheelSurface[force.Name]);
		
local totalTireLoad = Length * (Mass * Grip)
local tireLoad = math.clamp((1-(-self.springLength[force.Name] / 6.9*(2.5))) * (Mass * Grip), 0, totalTireLoad)
		
--local longForce = (tireLoad* (pacejkaLongValue / 2)) / 4
local lateralForce = (tireLoad * pacejkaLatValue) / 4

drivForce.Force = Vector3.new(-lateralForce, 0, longtitudinalForce.Z)

Yes I have clamped my lateral friction so it doesn't have any weird behavior but just for the sake of keeping it short i have slightly edited my code to not include it

also, the longtitudinalForce shown in the code snippet is just my power calculation

the friction graph is displaying the friction only for the front left wheel.

Any help implementing longitudinal friction is appreciated!

None

Advertisement

Welcome, new person. Did you look for discussions on Pacejka functions in the forum? This one is about lateral velocity, but it might contain some nuggets for you: https://gamedev.net/forums/topic/711781-vehicle-physics-pacejka-lateral-velocity

-- Tom Sloper -- sloperama.com

@IdleBrick The longitudinal pacejka is pretty much the same, but with different parameters, and the input is not the slip angle but the slip ratio.
Your car movement looks quite fishy (especially during cornering) , are you sure you apply the forces at the right position? At the contact patch in the tire's coordinate frame.

Also longitudinal movement has no relation with power output. Forget the horsepower, it has nothing to do with physics.
Generally the engine generates some torque that goes down to the wheels and it only makes wheel rotation. As the wheel rotates slip(ratio) appears that goes into the pacejka formula, and the resulting force is the road reaction force that you can apply on the car.

Also the lateral force and tire load calculations look weird.
For the load you need the spring stiffness and the deflection.

IdleBrick said:
local lateralForce = (tireLoad * pacejkaLatValue) / 4

Keep in mind that all four wheels generate different amount of forces!

@bmarci I think the problem with the movement is where I'm applying the force because I'm applying it in the same place as where I'm applying my suspension force, I will look into changing that to the contact point of the tires as you suggested.

I Have managed to get longitudinal friction working by using the torque from the engine in the slipRatio formula and then doing the same as I did with lateral, One problem I have rn is using slipRatio for the visual wheels and making them spin based on the slip ratio, Rn I'm using the relative velocity for the spin of the wheels.

local DistanceMoved = ((RelativeVel.Z) / (self.WheelRadius / 0.5)) * dt -- dt is delta timing
if DistanceMoved ~= DistanceMoved then
	DistanceMoved = 0
end
local WheelRotation = self.wheelRot
WheelRotation = WheelRotation + DistanceMoved / (self.WheelRadius * 0.5)
WheelRotation = WheelRotation % (2 * math.pi)
self.wheelRot = WheelRotation

Yea for Tireload I couldn't find much this is definitely a better formula than my lousy formula.

If you have any idea on how I would go about that please let me know

None

@IdleBrick The way you rotate the wheel is not really the best. It'll always spin according to linear movement, so no burnouts or lock-ups possible.
The method you are looking for is something more “physical”, if you want to make doughnuts or handbrake turns ?

So the engine torque accelerates the wheel, like:
acceleration = torque / inertia

and
angular_velocity += acceleration * dt
angle += angular_velocity * dt

and from this angular velocity you get the actual wheel speed:
ground_speed = linear_velocity
wheelspeed = angularvelocity * radius

for tire load you can use this:
fz = susp_k * susp_x + wheel_weight

the susp_k is the suspension's spring rate and susp_x is the spring compression

bmarci said:
angular_velocity

But wouldn't the angular velocity just keep adding up with each cycle of the loop, Also another thing to note is I have my Torque capped to the first value on my torque curve table

None

IdleBrick said:
But wouldn't the angular velocity just keep adding up with each cycle of the loop

Yes, as long as it gets positive torque, as soon as you step off the throttle or start braking or just leave it free rolling the acceleration will be negative and the angular velocity will decrease as well.

bmarci said:

IdleBrick said:
But wouldn't the angular velocity just keep adding up with each cycle of the loop

Yes, as long as it gets positive torque, as soon as you step off the throttle or start braking or just leave it free rolling the acceleration will be negative and the angular velocity will decrease as well.

This mostly works until the vehicle is stopped by a wall or span out, Then the angular velocity will stay the same and be out of sync with how the car should be

None

IdleBrick said:
This mostly works until the vehicle is stopped by a wall or span out, Then the angular velocity will stay the same and be out of sync with how the car should be

Are you dealing with low speed instability?
The slip calculations become unstable below ~5m/s
The movement will be OK(ish) as huge forces will oscillate, but they will cancel each other out, but the wheel rotation can go crazy.
Search for “relaxation length" or “low speed tire damping” or similar, but be warned, this is a painful area :(

@bmarci Yea I have just tried looking it up and I can't find much, Managed to find a Wikipedia page on it but that's about it. Following the formula from Wikipedia I have been able to calculate cornering stiffness

local slipAngle = math.deg(math.atan2(lateralVelocity, math.abs(longitudinalVelocity * self.stopWheels)))
local slipRatio = ((self.angularVelocity[force.Name] * self.WheelRadius) - longitudinalVelocity) / math.max(math.abs(longitudinalVelocity), 0.00001)
		
local corneringForce = RelativeVel.Z / TurnRadius
local corneringStiffness = corneringForce / slipAngle

I haven't found anything on Lateral displacement. I don't know how I would implement both formulas into pacejka to have a force when not moving to stop cars with the same angular velocity as accelerating. It all a bit of a headache :(

None

This topic is closed to new replies.

Advertisement