{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreibiyyzsptsq5ypmqus5ustkv5fyxbhmy3zvefvutetv7zsbly4tou",
"uri": "at://did:plc:dxjzgxe7cvirxkwfjr2tjspt/app.bsky.feed.post/3ml2l2mieyro2"
},
"path": "/t/jolt-vehicle-tuning-guide/49569#post_14",
"publishedAt": "2026-05-04T19:10:26.000Z",
"site": "https://hub.jmonkeyengine.org",
"tags": [
"github.com/jrouwe/JoltPhysics",
"Jolt/Physics/Vehicle/WheeledVehicleController.cpp",
"3c1f4baad"
],
"textContent": "I went trough git history to find the root cause:\nInitially i had radians, then i added different cars and a json loader, the definitions have been in degrees, then i removed parts of the loader for debugging and copied over the degrees and i actually have written the doc wrong.\n\nAdditionally when using a curve instead of a fixed value, jolt expects degree and converts internally.\n\ngithub.com/jrouwe/JoltPhysics\n\n#### Jolt/Physics/Vehicle/WheeledVehicleController.cpp\n\n3c1f4baad\n\n\n\n\n\n\n 120. \t\tmLongitudinalSlip = abs((mAngularVelocity * settings->mRadius - relative_longitudinal_velocity) / relative_longitudinal_velocity_denom);\n\n\n 121. \t\tfloat longitudinal_slip_friction = settings->mLongitudinalFriction.GetValue(mLongitudinalSlip);\n\n\n 122.\n\n 123. \t\t// Calculate lateral friction based on slip angle\n\n\n 124. \t\tfloat relative_velocity_len = relative_velocity.Length();\n\n\n 125. \t\tmLateralSlip = relative_velocity_len < 1.0e-3f ? 0.0f : ACos(abs(relative_longitudinal_velocity) / relative_velocity_len);\n\n\n 126. \t\tfloat lateral_slip_angle = RadiansToDegrees(mLateralSlip);\n\n\n 127. \t\tfloat lateral_slip_friction = settings->mLateralFriction.GetValue(lateral_slip_angle);\n\n\n 128.\n\n 129. \t\t// Tire friction\n\n\n 130. \t\tVehicleConstraint::CombineFunction combine_friction = inConstraint.GetCombineFriction();\n\n\n 131. \t\tmCombinedLongitudinalFriction = longitudinal_slip_friction;\n\n\n 132. \t\tmCombinedLateralFriction = lateral_slip_friction;\n\n\n 133. \t\tcombine_friction(inWheelIndex, mCombinedLongitudinalFriction, mCombinedLateralFriction, *mContactBody, mContactSubShapeID);\n\n\n 134. \t}\n\n\n 135. \telse\n\n\n\n\n\nHere is the current pacejka simplification i use:\n\n\n /**\n * Pacejka \"Magic Formula\" — slip-angle only. Sampled at boot and fed\n * to Jolt as a piecewise-linear lookup.\n *\n * B controls how quickly grip builds with slip — higher B means the\n * tyre snaps into peak faster. Street tyres are soft (low B), slicks\n * are sharp (high B).\n *\n * C controls the post-peak shape — how much grip the tyre keeps\n * once it's past its best slip angle and starting to slide.\n *\n * D is the peak grip itself — the maximum μ the tyre can deliver.\n *\n * E controls how gently the curve approaches its peak — higher E\n * gives a wider plateau where the tyre stays near peak grip across a\n * range of slip angles.\n */\n static float pacejka(float slipAngleDeg, float b, float c, float d, float e) {\n double alpha = Math.toRadians(slipAngleDeg);\n double ba = b * alpha;\n double inner = ba - e * (ba - Math.atan(ba));\n return (float) (d * Math.sin(c * Math.atan(inner)));\n }\n\n\nand the logitudinalfriction curve is used to make RWD working better:\n\n\n // Longitudinal friction curve — peak μ at 6 % slip ratio, falling\n // off past peak to model kinetic-friction loss in deep wheelspin\n // and locked-wheel skids. Jolt's default (3 points capped at slip\n // 0.2) clamps flat at μ=1.0 past peak (LinearCurve.GetValue holds\n // the last Y), which keeps unrealistic grip during sustained\n // wheelspin — the extended tail down to μ=0.55 at slip 100 makes\n // sliding tyres actually feel like they've given up.\n var lon = w.getLongitudinalFriction();\n lon.clear();\n lon.addPoint(0f, 0f);\n lon.addPoint(0.06f, 1.8f);\n lon.addPoint(0.20f, 1.7f);\n lon.addPoint(0.50f, 1.4f);\n lon.addPoint(1.00f, 1.2f);\n lon.addPoint(3.00f, 0.85f);\n lon.addPoint(10.0f, 0.65f);\n lon.addPoint(100.0f, 0.55f);\n\n\nThe remaining issue is that even with a controller input, lateral grip is marginal when steering at higher speeds.\n\nIn the current state, MAX_SAT_LAT in the FrictionCircleTireCallback is a key configuration value. Physically correct would be 1. A burning out wheel has 0 lateral grip. There are other physics aspects (not simulated) that make the this not usable in game. 0.95 is a nice value for my current setup, with 0.6 for example you have arcade like car and with 0.9 it is slightly drift capable, but it does not breakout by accident or too much throttle.",
"title": "Jolt Vehicle Tuning Guide"
}