LUADOC - Farming Simulator 17

Printable Version

WheelsUtil

Functions

registerTireType

Description
Register new tire type
Definition
registerTireType(string name, table frictionCoeffs, table frictionCoeffsWer)
Arguments
stringnamename of new tire type
tablefrictionCoeffsfriction coeffs
tablefrictionCoeffsWerfriction coeffs wet
Code
27function WheelsUtil.registerTireType(name, frictionCoeffs, frictionCoeffsWet)
28 local tireType = WheelsUtil.getTireType(name);
29 if tireType ~= nil then
30 print("Warning: Adding duplicate tire type '"..name.."'");
31 return;
32 end
33
34 local function getNoNilCoeffs(frictionCoeffs)
35 local localCoeffs = {};
36 if frictionCoeffs[1] == nil then
37 localCoeffs[1] = 1.15;
38 for i=2,WheelsUtil.NUM_GROUNDS do
39 if frictionCoeffs[i] ~= nil then
40 localCoeffs[1] = frictionCoeffs[i];
41 break;
42 end
43 end
44 else
45 localCoeffs[1] = frictionCoeffs[1];
46 end
47 for i=2,WheelsUtil.NUM_GROUNDS do
48 localCoeffs[i] = frictionCoeffs[i] or frictionCoeffs[i-1];
49 end
50 return localCoeffs
51 end
52
53 local tireType = {};
54 tireType.name = name;
55 tireType.frictionCoeffs = getNoNilCoeffs(frictionCoeffs);
56 tireType.frictionCoeffsWet = getNoNilCoeffs(frictionCoeffsWet or frictionCoeffs);
57 table.insert(WheelsUtil.tireTypes, tireType);
58end

getTireType

Description
Returns tire type index
Definition
getTireType(string name)
Arguments
stringnamename of tire type
Return Values
integeriindex of tire type
Code
64function WheelsUtil.getTireType(name)
65 for i, t in pairs(WheelsUtil.tireTypes) do
66 if t.name == name then
67 return i;
68 end
69 end
70 return nil;
71end

updateWheelsPhysics

Description
Updates wheel physics
Definition
updateWheelsPhysics(float dt, float currentSpeed, float acceleration, boolean doHandbrake, boolean requiredDriveMode)
Arguments
floatdttime since last call in ms
floatcurrentSpeedcurrent speed
floataccelerationacceleration
booleandoHandbrakedo handbrake
booleanrequiredDriveModerequired drive mode
Code
137function WheelsUtil.updateWheelsPhysics(self, dt, currentSpeed, acceleration, doHandbrake, requiredDriveMode)
138 local accelerationPedal = 0;
139 local brakePedal = 0;
140
141 if not g_currentMission.missionInfo.stopAndGoBraking then
142
143 self.hasStopped = Utils.getNoNil(self.hasStopped, false);
144 self.nextMovingDirection = Utils.getNoNil(self.nextMovingDirection, 0);
145
146 if math.abs(acceleration) < 0.001 and math.abs(self.lastSpeedAcceleration) < 0.0001 and math.abs(self.lastSpeedReal) < 0.0001 and math.abs(self.lastMovedDistance) < 0.001 then
147 self.hasStopped = true;
148 accelerationPedal = 0;
149 brakePedal = 1;
150 elseif math.abs(self.lastSpeedReal) > 0.0001 then
151 self.hasStopped = false;
152 end
153
154 if self.hasStopped and math.abs(acceleration) > 0.001 then
155 self.nextMovingDirection = acceleration;
156 end
157 if self.nextMovingDirection * acceleration > 0.001 then
158 accelerationPedal = acceleration;
159 brakePedal = 0;
160 elseif not self.hasStopped then
161 accelerationPedal = 0;
162 if self.nextMovingDirection == 0 then
163 brakePedal = 1;
164 else
165 --brakePedal = math.abs(acceleration);
166
167 if math.abs(acceleration) < 0.001 then
168 if currentSpeed < self.motor.lowBrakeForceSpeedLimit or doHandbrake then
169 if math.abs(self.rotatedTime) < 0.01 or self.articulatedAxis == nil then
170 brakePedal = 1;
171 end
172 else
173 brakePedal = self.motor.lowBrakeForceScale;
174 end
175 else
176 brakePedal = math.abs(acceleration);
177 end
178
179 end
180 end
181
182 else
183
184 local brakeAcc = false;
185 if (self.movingDirection*currentSpeed*Utils.sign(acceleration*self.reverserDirection)) < -0.0003 then -- 0.0003 * 3600 = 1.08 km/h
186 -- do we want to accelerate in the opposite direction of the vehicle speed?
187 brakeAcc = true;
188 end;
189
190 if math.abs(acceleration) < 0.001 then
191 accelerationPedal = 0;
192
193 if currentSpeed < self.motor.lowBrakeForceSpeedLimit or doHandbrake then
194 if math.abs(self.rotatedTime) < 0.01 or self.articulatedAxis == nil then
195 brakePedal = 1;
196 end;
197 else
198 brakePedal = self.motor.lowBrakeForceScale;
199 end;
200 else
201 if not brakeAcc then
202 accelerationPedal = acceleration;
203 brakePedal = 0;
204 else
205 accelerationPedal = 0;
206 brakePedal = math.abs(acceleration);
207 end;
208 end;
209
210 end
211
212 local automaticBrake = self.motor.lowBrakeForceScale == brakePedal;
213
214 if g_currentMission.missionInfo.stopAndGoBraking then
215 self:setBrakeLightsVisibility(not automaticBrake and math.abs(brakePedal) > 0 and currentSpeed > 0.0006);
216 else
217 self:setBrakeLightsVisibility(not automaticBrake and math.abs(brakePedal) > 0 and not self.hasStopped);
218 end
219
220 self:setReverseLightsVisibility(self.movingDirection < 0 and (currentSpeed > 0.0006 or accelerationPedal < 0) and self.reverserDirection == 1);
221
222 self.motor:updateMotorRpm(dt);
223 self.motor:updateGear(accelerationPedal, dt);
224
225 local absAccelerationPedal = math.abs(accelerationPedal);
226 local wheelDriveTorque = 0;
227
228 if next(self.differentials) ~= nil and self.motorizedNode ~= nil then
229 --print(string.format("set vehicle props: %.2fkN %.1frpm ratio: %.1f", self.motor:getTorque(accelerationPedal, false), self.motor:getCurMaxRpm(), self.motor:getGearRatio()));
230 local maxRotSpeed = self.motor:getCurMaxRpm() * math.pi / 30;
231 local torque = self.motor:getTorque(accelerationPedal * self.reverserDirection, false);
232
233 setVehicleProps(self.motorizedNode, torque, maxRotSpeed, self.motor:getGearRatio() * self.reverserDirection, self.motor:getMaxClutchTorque(), self.motor:getRotInertia(), self.motor:getDampingRate());
234 else
235 local numTouching = 0;
236 local numNotTouching = 0;
237 local numHandbrake = 0;
238
239 for _, wheel in pairs(self.wheels) do
240 if wheel.driveMode >= requiredDriveMode then
241 if doHandbrake and wheel.hasHandbrake then
242 numHandbrake = numHandbrake +1;
243 else
244 if wheel.hasGroundContact then
245 numTouching = numTouching+1;
246 else
247 numNotTouching = numNotTouching+1;
248 end
249 end
250 end
251 end
252
253 if numTouching > 0 and absAccelerationPedal > 0.01 then
254 local axisTorque, brakePedalMotor = WheelsUtil.getWheelTorque(self, accelerationPedal);
255 if axisTorque ~= 0 then
256 wheelDriveTorque = axisTorque / (numTouching+numNotTouching); --*0.7);
257 else
258 brakePedal = brakePedalMotor;
259 end
260 end
261 end
262
263 local doBrake = brakePedal > 0;
264 for _, implement in pairs(self.attachedImplements) do
265 if implement.object ~= nil then
266 if doBrake then
267 implement.object:onBrake(brakePedal);
268 else
269 implement.object:onReleaseBrake();
270 end
271 end
272 end
273
274 for _, wheel in pairs(self.wheels) do
275 WheelsUtil.updateWheelPhysics(self, wheel, doHandbrake, wheelDriveTorque, brakePedal, requiredDriveMode, dt)
276 end
277
278end

getWheelTorque

Description
Returns wheel torque
Definition
getWheelTorque(float accelerationPedal)
Arguments
floataccelerationPedalacceleration of pedal
Return Values
floatwheelTorquewheel torque
Code
284function WheelsUtil.getWheelTorque(self, accelerationPedal)
285 local torque, brakePedal = self.motor:getTorque(accelerationPedal, true);
286 torque = torque * math.abs(accelerationPedal);
287
288 return torque * self.motor:getGearRatio(), brakePedal;
289end

updateWheelPhysics

Description
Update wheel physics
Definition
updateWheelPhysics(table wheel, boolean handbrake, float motorTorque, float brakePedal, boolean requiredDriveMode, float dt)
Arguments
tablewheelwheel
booleanhandbrakehandbrake
floatmotorTorquemotor torque
floatbrakePedalbrake pedal
booleanrequiredDriveModerequired drive mode
floatdttime since last call in ms
Code
299function WheelsUtil.updateWheelPhysics(self, wheel, handbrake, motorTorque, brakePedal, requiredDriveMode, dt)
300
301 local brakeForce = brakePedal*self.motor:getBrakeForce();
302 if handbrake and wheel.hasHandbrake then
303 brakeForce = self.motor:getBrakeForce();
304 end
305
306 if motorTorque ~= 0 then
307 if wheel.driveMode < requiredDriveMode then
308 motorTorque = 0;
309 elseif not wheel.hasGroundContact then
310 motorTorque = motorTorque*0.7;
311 end
312 end
313
314 local steeringAngle = wheel.steeringAngle;
315
316 if self.isAddedToPhysics then
317 setWheelShapeProps(wheel.node, wheel.wheelShape, motorTorque, brakeForce*wheel.brakeFactor, steeringAngle, wheel.rotationDamping);
318 end
319end

updateWheelHasGroundContact

Description
Update check if wheel has ground contact
Definition
updateWheelHasGroundContact(table wheel)
Arguments
tablewheelwheel
Code
324function WheelsUtil.updateWheelHasGroundContact(wheel)
325
326 local x,_,_ = getWheelShapeContactPoint(wheel.node, wheel.wheelShape)
327 wheel.hasGroundContact = x~=nil;
328 --return wheel.hasGroundContact;
329end

updateWheelSteeringAngle

Description
Update wheel steering angle
Definition
updateWheelSteeringAngle(table wheel, float dt)
Arguments
tablewheelwheel
floatdttime since last call in ms
Code
335function WheelsUtil.updateWheelSteeringAngle(self, wheel, dt)
336 local steeringAngle = wheel.steeringAngle;
337 local rotatedTime = self.rotatedTime;
338 if wheel.steeringAxleScale ~= 0 then
339 steeringAngle = Utils.clamp(self.steeringAxleAngle * wheel.steeringAxleScale, wheel.steeringAxleRotMin, wheel.steeringAxleRotMax);
340 elseif wheel.versatileYRot and self:getIsVersatileYRotActive(wheel) then
341 if self.isServer then
342 if wheel.forceVersatility or wheel.hasGroundContact then
343 steeringAngle = Utils.getVersatileRotation(wheel.repr, wheel.node, dt, wheel.positionX, wheel.positionY, wheel.positionZ, wheel.steeringAngle, wheel.rotMin, wheel.rotMax);
344 end
345 end
346 elseif wheel.rotSpeed ~= nil and wheel.rotMax ~= nil and wheel.rotMin ~= nil then
347 if rotatedTime > 0 or wheel.rotSpeedNeg == nil then
348 steeringAngle = rotatedTime * wheel.rotSpeed;
349 else
350 steeringAngle = rotatedTime * wheel.rotSpeedNeg;
351 end
352 if steeringAngle > wheel.rotMax then
353 steeringAngle = wheel.rotMax;
354 elseif steeringAngle < wheel.rotMin then
355 steeringAngle = wheel.rotMin;
356 end
357 if self.updateSteeringAngle ~= nil then
358 steeringAngle = self:updateSteeringAngle(wheel, dt, steeringAngle);
359 end
360 end
361 wheel.steeringAngle = steeringAngle;
362end

computeRpmFromWheels

Description
Compute rpm from wheels
Definition
computeRpmFromWheels()
Return Values
floatrpmrpm
Code
367function WheelsUtil.computeRpmFromWheels(self)
368 local wheelSpeed = 0;
369 local numWheels = 0;
370 for _, wheel in pairs(self.wheels) do
371 local axleSpeed = getWheelShapeAxleSpeed(wheel.node, wheel.wheelShape); -- rad/sec
372 if wheel.hasGroundContact then
373 wheelSpeed = wheelSpeed + axleSpeed * wheel.radius;
374 numWheels = numWheels+1;
375 end
376 end
377
378 if numWheels > 0 then
379 return wheelSpeed*30/(math.pi*numWheels);
380 end
381 return 0;
382end

computeRpmFromSpeed

Description
Compute rpm from speed
Definition
computeRpmFromSpeed()
Return Values
floatrpmrpm
Code
387function WheelsUtil.computeRpmFromSpeed(self)
388 -- v = w*r => w = v/r
389 -- w = 2pi*rpm / 60
390 -- rpm = 60 * v/r/(2pi)
391 return (self.lastSpeedReal*30000 / math.pi);
392end

updateWheelsGraphics

Description
Update wheel graphics
Definition
updateWheelsGraphics(float dt)
Arguments
floatdttime since last call in ms
Code
397function WheelsUtil.updateWheelsGraphics(self, dt)
398 if self.isServer then
399 self.hasWheelGroundContact = false;
400 end
401
402 for _, wheel in pairs(self.wheels) do
403 WheelsUtil.updateWheelSteeringAngle(self, wheel, dt);
404 if self.isServer and self.isAddedToPhysics then
405 WheelsUtil.updateWheelHasGroundContact(wheel);
406 if wheel.hasGroundContact then
407 self.hasWheelGroundContact = true;
408 end
409
410 if wheel.updateWheel then
411 local x,y,z, xDrive, suspensionLength = getWheelShapePosition(wheel.node, wheel.wheelShape);
412 xDrive = xDrive + wheel.xDriveOffset
413 WheelsUtil.updateWheelGraphics(self, wheel, x, y, z, xDrive, suspensionLength);
414
415 --fill netinfo (on server)
416 wheel.netInfo.x = x;
417 wheel.netInfo.y = y;
418 wheel.netInfo.z = z;
419 wheel.netInfo.xDrive = xDrive;
420 wheel.netInfo.suspensionLength = suspensionLength;
421 else
422 wheel.updateWheel = true
423 end
424 else
425 -- client code
426 local x, y, z = wheel.netInfo.x, wheel.netInfo.y, wheel.netInfo.z;
427 local xDrive = wheel.netInfo.xDrive;
428 local suspensionLength = wheel.netInfo.suspensionLength
429 WheelsUtil.updateWheelGraphics(self, wheel, x, y, z, xDrive, suspensionLength);
430 end
431 end
432end

updateWheelGraphics

Description
Update wheel graphics
Definition
updateWheelGraphics(table wheel, float x, float y, float z, float x, float suspensionLength)
Arguments
tablewheelwheel
floatxx position
floatyy position
floatzz position
floatxx drive rotation
floatsuspensionLengthlength of suspension
Code
442function WheelsUtil.updateWheelGraphics(self, wheel, x, y, z, xDrive, suspensionLength)
443 local steeringAngle = wheel.steeringAngle;
444 if not wheel.showSteeringAngle then
445 steeringAngle = 0;
446 end
447
448 local dirX, dirY, dirZ = 0, -1, 0
449 if wheel.repr == wheel.driveNode then
450 setRotation(wheel.repr, xDrive, steeringAngle, 0);
451 else
452 dirX, dirY, dirZ = localDirectionToLocal(wheel.repr, getParent(wheel.repr), 0, -1, 0);
453 setRotation(wheel.repr, 0, steeringAngle, 0);
454 setRotation(wheel.driveNode, xDrive, 0, 0);
455 end
456
457 if wheel.wheelTire ~= nil then
458 local x, y, z, _ = getShaderParameter(wheel.wheelTire, "morphPosition");
459 local deformation = Utils.clamp((wheel.deltaY+0.04-suspensionLength)*0.7, 0, wheel.maxDeformation)
460
461 setShaderParameter(wheel.wheelTire, "morphPosition", x, y, z, deformation, false);
462
463 if wheel.additionalWheels ~= nil then
464 for _, additionalWheel in pairs(wheel.additionalWheels) do
465 local x, y, z, _ = getShaderParameter(additionalWheel.wheelTire, "morphPosition");
466 setShaderParameter(additionalWheel.wheelTire, "morphPosition", x, y, z, deformation, false);
467 end
468 end
469
470 suspensionLength = suspensionLength+deformation
471 end
472
473 suspensionLength = suspensionLength - wheel.deltaY
474 setTranslation(wheel.repr, wheel.startPositionX + dirX*suspensionLength, wheel.startPositionY + dirY*suspensionLength, wheel.startPositionZ + dirZ*suspensionLength);
475
476 if wheel.steeringNode ~= nil then
477 local refAngle = wheel.steeringNodeMaxRot;
478 local refTrans = wheel.steeringNodeMaxTransX
479 local refRot = wheel.steeringNodeMaxRotY;
480 if steeringAngle < 0 then
481 refAngle = wheel.steeringNodeMinRot;
482 refTrans = wheel.steeringNodeMinTransX;
483 refRot = wheel.steeringNodeMinRotY;
484 end
485 local steering = 0;
486 if refAngle ~= 0 then
487 steering = steeringAngle / refAngle;
488 end
489
490 if wheel.steeringNodeMinTransX ~= nil then
491 local x,y,z = getTranslation(wheel.steeringNode);
492 x = refTrans * steering;
493 setTranslation(wheel.steeringNode, x, y, z);
494 end
495 if wheel.steeringNodeMinRotY ~= nil then
496 local rotX,rotY,rotZ = getRotation(wheel.steeringNode);
497 rotY = refRot * steering;
498 setRotation(wheel.steeringNode, rotX, rotY, rotZ);
499 end
500 end
501
502 if wheel.fenderNode ~= nil then
503 local angleDif = 0;
504 if steeringAngle > wheel.fenderRotMax then
505 angleDif = wheel.fenderRotMax - steeringAngle;
506 elseif steeringAngle < wheel.fenderRotMin then
507 angleDif = wheel.fenderRotMin - steeringAngle;
508 end
509 setRotation(wheel.fenderNode, 0, angleDif, 0);
510 end
511end

getTireFriction

Description
Returns tire friction
Definition
getTireFriction(integer tireType, integer groundType, float wetScale)
Arguments
integertireTypetire type index
integergroundTypeground type index
floatwetScalewet scale
Return Values
floattireFrictiontire friction
Code
519function WheelsUtil.getTireFriction(tireType, groundType, wetScale)
520 if wetScale == nil then
521 wetScale = 0;
522 end
523 local coeff = WheelsUtil.tireTypes[tireType].frictionCoeffs[groundType];
524 local coeffWet = WheelsUtil.tireTypes[tireType].frictionCoeffsWet[groundType];
525 return coeff + (coeffWet-coeff)*wetScale;
526end

getGroundType

Description
Get ground type
Definition
getGroundType(boolean isField, boolean isRoad, float depth)
Arguments
booleanisFieldis on field
booleanisRoadis on road
floatdepthdepth of terrain
Return Values
integergroundTypeground type
Code
534function WheelsUtil.getGroundType(isField, isRoad, depth)
535 -- terrain softness:
536 -- [ 0, 0.1]: road
537 -- [0.1, 0.8]: hard terrain
538 -- [0.8, 1 ]: soft terrain
539 if isField then
540 return WheelsUtil.GROUND_FIELD
541 elseif isRoad or depth < 0.1 then
542 return WheelsUtil.GROUND_ROAD;
543 else
544 if depth > 0.8 then
545 return WheelsUtil.GROUND_SOFT_TERRAIN;
546 else
547 return WheelsUtil.GROUND_HARD_TERRAIN;
548 end
549 end
550end