Reimplement tyre model to use separate longitudinal/lateral formulas, also use pacejka94

This commit is contained in:
sergeypdev 2025-04-27 21:24:25 +04:00
parent b0fb81d88c
commit a27a5ccde6
4 changed files with 445 additions and 99 deletions

View File

@ -1,22 +1,93 @@
// https://www.edy.es/dev/docs/pacejka-94-parameters-explained-a-comprehensive-guide/
package physics package physics
import "core:math" import "core:math"
Pacejka96_Params :: [11]f32 Pacejka94_Longitudinal_Params :: [14]f32
Pacejka94_Lateral_Params :: [18]f32
DEFAULT_PACEJKA96_PARAMS :: Pacejka96_Params{1.45, -150, 1500, 0, 400, -0.4, 0, 0, 0, 0, 0} PACEJKA94_LONGITUDINAL_PEAK_X :: 6.24
PACEJKA94_LONGITUDINAL_PARAMS :: Pacejka94_Longitudinal_Params {
1.5,
0,
1100,
0,
300,
0,
0,
0,
-2,
0,
0,
0,
0,
0,
}
PACEJKA94_LATERAL_PEAK_X :: 6.26
PACEJKA94_LATERAL_PARAMS :: Pacejka94_Lateral_Params {
1.4,
0,
1100,
1100,
10,
0,
0,
-2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
}
// X is slip ratio percentage [-100, 100] or slip angle in degrees, where positive angle is turning left // X is slip ratio percentage [-100, 100] or slip angle in degrees, where positive angle is turning left
// Output is the friction coefficient // Output is the friction coefficient
pacejka_96 :: proc(b: Pacejka96_Params, x: f32, f_z: f32, s_v: f32 = 0) -> f32 { pacejka_94_longitudinal :: proc(
b: Pacejka94_Longitudinal_Params,
x: f32,
f_z: f32,
s_v: f32 = 0,
) -> f32 {
f_z_sq := f_z * f_z
C := b[0] C := b[0]
D := (b[1] * f_z + b[2]) * f_z D := (b[1] * f_z + b[2]) * f_z
B := ((b[3] * f_z * f_z + b[4] * f_z) * math.exp(-b[5] * f_z)) / (C * D) BCD := (b[3] * f_z_sq + b[4] * f_z) * math.exp(-b[5] * f_z)
E := (b[6] * f_z * f_z + b[7] * f_z + b[8]) B := BCD / (C * D)
s_h := b[9] * f_z + b[10] H := b[9] * f_z + b[10]
E := (b[6] * f_z_sq + b[7] * f_z + b[8]) * (1.0 - b[13] * math.sign(x + H))
V := b[11] * f_z + b[12]
Bx1 := B * (x + H)
X := x + s_h F := D * math.sin(C * math.atan(Bx1 - E * (Bx1 - math.atan(Bx1)))) + V
y := D * math.sin(C * math.atan(B * X - E * (B * X - math.atan(B * X))))
Y := y + s_v return F / (f_z * 1000)
return Y / (f_z * 1000) }
pacejka_94_lateral :: proc(
a: Pacejka94_Lateral_Params,
slip_angle: f32,
f_z: f32,
camber_angle: f32,
) -> f32 {
camber_angle_sq := camber_angle * camber_angle
C := a[0]
D := f_z * (a[1] * f_z + a[2]) * (1.0 - a[15] * camber_angle_sq)
BCD := a[3] * math.sin(math.atan(f_z / a[4]) * 2.0) * (1.0 - a[5] * abs(camber_angle))
B := BCD / (C * D)
H := a[8] * f_z + a[9] + a[10] * camber_angle
E := (a[6] * f_z + a[7]) * (1.0 - (a[16] * camber_angle + a[17]) * math.sign(slip_angle + H))
V := a[11] * f_z + a[12] + (a[13] * f_z + a[14]) * camber_angle * f_z
Bx1 := B * (slip_angle + H)
F := D * math.sin(C * math.atan(Bx1 - E * (Bx1 - math.atan(Bx1)))) + V
return F / (f_z * 1000)
} }

View File

@ -789,45 +789,15 @@ pgs_solve_suspension :: proc(
// body_vel_at_contact_patch + (v.radius * v.w * forward) // body_vel_at_contact_patch + (v.radius * v.w * forward)
slip_ratio := slip_ratio :=
ground_vel == 0 ? 0 : clamp(wheel_spin_vel / ground_vel - 1, -1, 1) ground_vel == 0 ? 0 : clamp(wheel_spin_vel / ground_vel - 1, -1, 1) * 100.0
slip_angle := slip_angle :=
lg.angle_between(forward, body_vel_at_contact_patch) * math.DEG_PER_RAD lg.angle_between(forward, body_vel_at_contact_patch) * math.DEG_PER_RAD
SLIP_RATIO_PARAMS :: Pacejka96_Params {
1.7,
-150,
1500,
0,
700,
-0.8,
0,
0,
0,
0,
0,
}
SLIP_ANGLE_PARAMS :: Pacejka96_Params {
1.6,
-150,
1500,
0,
229,
-0.4,
0,
0,
0,
0,
0,
}
OPTIMAL_SLIP_RATIO :: f32(0.0078)
OPTIMAL_SLIP_ANGLE :: f32(5.5)
MAX_SLIP_LEN :: f32(2.0) MAX_SLIP_LEN :: f32(2.0)
slip_vec := Vec2 { slip_vec := Vec2 {
slip_angle / OPTIMAL_SLIP_ANGLE / MAX_SLIP_LEN, slip_angle / PACEJKA94_LATERAL_PEAK_X / MAX_SLIP_LEN,
slip_ratio / OPTIMAL_SLIP_RATIO / MAX_SLIP_LEN, slip_ratio / PACEJKA94_LONGITUDINAL_PEAK_X / MAX_SLIP_LEN,
} }
slip_len := lg.length(slip_vec) slip_len := lg.length(slip_vec)
@ -838,19 +808,20 @@ pgs_solve_suspension :: proc(
long_friction := long_friction :=
abs( abs(
pacejka_96( pacejka_94_longitudinal(
SLIP_RATIO_PARAMS, PACEJKA94_LONGITUDINAL_PARAMS,
slip_ratio * 100, slip_ratio,
max(abs(v.spring_impulse), 0.001) * inv_dt * 0.001, max(abs(v.spring_impulse), 0.001) * inv_dt * 0.001,
), ),
) * ) *
abs(slip_vec.y) abs(slip_vec.y)
lat_friction := lat_friction :=
abs( abs(
pacejka_96( pacejka_94_lateral(
SLIP_ANGLE_PARAMS, PACEJKA94_LATERAL_PARAMS,
slip_angle, slip_angle,
max(abs(v.spring_impulse), 0.001) * inv_dt * 0.001, max(abs(v.spring_impulse), 0.001) * inv_dt * 0.001,
0.0,
), ),
) * ) *
abs(slip_vec.x) abs(slip_vec.x)

137
research/pacejka94.ipynb Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long