LUADOC - Farming Simulator 19

VehicleMotor

Description
Class for vehicle motors
Functions

calculatePhysicalMaximumBackwardSpeed

Description
Returns physical maximum backward speed
Definition
calculatePhysicalMaximumBackwardSpeed()
Return Values
floatphysicalMaxBackwardSpeedphysical maximum backward speed
Code
438function VehicleMotor:calculatePhysicalMaximumBackwardSpeed()
439 return VehicleMotor.calculatePhysicalMaximumSpeed(self.minBackwardGearRatio, self.backwardGearRatios, self.maxRpm)
440end

calculatePhysicalMaximumForwardSpeed

Description
Returns physical maximum forward speed
Definition
calculatePhysicalMaximumForwardSpeed()
Return Values
floatphysicalMaxForwardSpeedphysical maximum forward speed
Code
431function VehicleMotor:calculatePhysicalMaximumForwardSpeed()
432 return VehicleMotor.calculatePhysicalMaximumSpeed(self.minForwardGearRatio, self.forwardGearRatios, self.maxRpm)
433end

calculatePhysicalMaximumSpeed

Description
Returns physical maximum speed
Definition
calculatePhysicalMaximumSpeed(float minGearRatio, table gearRatios, Integer maxRpm)
Arguments
floatminGearRatiomin gear ratio
tablegearRatiosgear ratios
IntegermaxRpmmax rpm
Return Values
floatphysicalMaxSpeedphysical maximum speed
Code
448function VehicleMotor.calculatePhysicalMaximumSpeed(minGearRatio, gearRatios, maxRpm)
449 local minRatio
450 if minGearRatio ~= nil then
451 minRatio = minGearRatio
452 else
453 minRatio = math.huge
454 for _, ratio in pairs(gearRatios) do
455 minRatio = math.min(minRatio, ratio)
456 end
457 end
458 return maxRpm * math.pi / (30 * minRatio)
459end

findGearChangeTargetGear

Description
Definition
findGearChangeTargetGear()
Code
603function VehicleMotor:findGearChangeTargetGear(curGear, prevGear, gearRatios, gearSign, acceleratorPedal, dt)
604 local newGear = curGear
605
606 local minAllowedRpm, maxAllowedRpm = self:getRequiredMotorRpmRange()
607
608 local differentialRpm = math.max(self.differentialRotSpeed * 30 / math.pi * gearSign, 0.0001)
609
610 -- find the gear that would give the max power
611 local maxPower = 0
612 local maxPowerGear = 0
613 for gear=1,#gearRatios do
614 local rpm = differentialRpm * gearRatios[gear]
615 if rpm <= maxAllowedRpm and rpm >= minAllowedRpm then
616 local power = self:getTorqueCurveValue(rpm) * rpm
617 if power >= maxPower then
618 maxPower = power
619 maxPowerGear = gear
620 end
621 end
622 end
623 if maxPowerGear ~= 0 then
624
625 local bestTradeoff = 0
626
627 -- find the gear ratio with the best tradeoff
628 for gear=#gearRatios,1,-1 do
629 local nextRpm = differentialRpm * gearRatios[gear]
630 if nextRpm <= maxAllowedRpm and nextRpm >= minAllowedRpm then
631 local nextPower = self:getTorqueCurveValue(nextRpm) * nextRpm
632
633 -- Choose the gear if it gets close enough to the max power
634 if nextPower >= maxPower*0.8 then
635 local powerFactor = (nextPower - 0.8*maxPower) / (maxPower*0.2) -- 0 when at 80% of maxPower, 1 when at maxPower
636 local rpmFactor = (maxAllowedRpm - nextRpm) / math.max(maxAllowedRpm-minAllowedRpm, 0.001)
637
638 if acceleratorPedal == 0 then
639 rpmFactor = 1-rpmFactor -- choose a high rpm when decelerating
640 else
641 rpmFactor = rpmFactor * 3
642 end
643 local newGearFactor = gear ~= prevGear and 0.5 or 0 -- prefer choosing a different gear than what we had before the gear change
644
645 local tradeoff = powerFactor + rpmFactor + newGearFactor
646
647 if tradeoff > bestTradeoff then
648 bestTradeoff = tradeoff
649 newGear = gear
650 --print(string.format("better final tradeoff %.2f with %d power: %.2f vs %.2f @ %d rpm %.2f prevGear %d factors: %.2f %.2f %.2f", tradeoff, gear, nextPower, maxPower, maxPowerGear, nextRpm, prevGear, powerFactor, rpmFactor, newGearFactor))
651 else
652 --print(string.format("worse final tradeoff %.2f with %d power: %.2f vs %.2f @ %d rpm %.2f prevGear %d factors: %.2f %.2f %.2f", tradeoff, gear, nextPower, maxPower, maxPowerGear, nextRpm, prevGear, powerFactor, rpmFactor, newGearFactor))
653 end
654 end
655 end
656 end
657 else
658 local minDiffGear = 0
659 local minDiff = math.huge
660 for gear=1,#gearRatios do
661 local rpm = differentialRpm * gearRatios[gear]
662 local diff = math.max(rpm - maxAllowedRpm, minAllowedRpm - rpm)
663 if diff < minDiff then
664 minDiff = diff
665 minDiffGear = gear
666 end
667 end
668 --print(string.format("use min diff gear: %d diff: %.2f", minDiffGear, minDiff))
669 newGear = minDiffGear
670 end
671 --if newGear ~= curGear then
672 -- print(string.format("Selected a different gear: %d vs %d", newGear, curGear))
673 --end
674 return newGear
675end

findGearChangeTargetGearPrediction

Description
Definition
findGearChangeTargetGearPrediction()
Code
679function VehicleMotor:findGearChangeTargetGearPrediction(curGear, gearRatios, gearSign, gearChangeTimer, acceleratorPedal, dt)
680 local newGear = curGear
681
682 local minAllowedRpm, maxAllowedRpm = self:getRequiredMotorRpmRange()
683 --print(string.format("rpmRange [%.2f %.2f]", minAllowedRpm, maxAllowedRpm))
684 local gearRatio = gearRatios[curGear]
685
686 local differentialRotSpeed = math.max(self.differentialRotSpeed*gearSign, 0.0001)
687 local differentialRpm = differentialRotSpeed * 30 / math.pi
688 local clutchRpm = differentialRpm * gearRatio
689
690
691 -- 1. Predict the velocity of the vehicle after the gear change
692 local diffSpeedAfterChange
693 if math.abs(acceleratorPedal) < 0.0001 then
694 -- Assume that we will continue decelerating with 80% of the current deceleration
695 local brakeAcc = math.min(self.differentialRotAccelerationSmoothed*gearSign*0.8, 0)
696 diffSpeedAfterChange = math.max(differentialRotSpeed + brakeAcc * self.gearChangeTime*0.001, 0)
697 --print(string.format("brake expectedAcc: %.3f realAcc %.3f %.3f max: %.2f gr: %.2f speed: %.2f", brakeAcc, self.vehicle.lastSpeedAcceleration*1000*1000, self.differentialRotAccelerationSmoothed, maxExpectedAcc, gearRatio, self.vehicle.lastSpeedReal*1000))
698 else
699 -- Ignore wheels mass as it is usually negligible and the calculation below is not correct when the differential acceleration is not uniformely distributed
700 --[[local neededWheelsInertiaTorque = 0
701 local specWheels = self.vehicle.spec_wheels
702 for _, wheel in pairs(specWheels.wheels) do
703 local invRotInterita = 2.0 / (wheel.mass*wheel.radius * wheel.radius);
704 neededWheelsInertiaTorque = neededWheelsInertiaTorque + invRotInterita * self.differentialRotAcceleration * wheel.radius
705 end
706 neededWheelsInertiaTorque = neededWheelsInertiaTorque / (gearRatio*gearRatio)]]
707
708 local lastMotorRotSpeed = self.motorRotSpeed - self.motorRotAcceleration * (g_physicsDtLastValidNonInterpolated*0.001)
709 local lastDampedMotorRotSpeed = lastMotorRotSpeed / (1.0 + self.dampingRateFullThrottle/self.rotInertia*g_physicsDtLastValidNonInterpolated*0.001)
710
711
712 local neededInertiaTorque = (self.motorRotSpeed - lastDampedMotorRotSpeed)/(g_physicsDtLastValidNonInterpolated*0.001) * self.rotInertia
713
714 local lastMotorTorque = (self.motorAppliedTorque - self.motorExternalTorque - neededInertiaTorque)
715
716 --print(string.format("load: %.3f expected torque: %.3f neededPtoTorque %.3f neededInertiaTorque %.4f", self.motorAppliedTorque, self.motorAvailableTorque, self.motorExternalTorque, neededInertiaTorque))
717
718 local totalMass = self.vehicle:getTotalMass()
719 local expectedAcc = lastMotorTorque * gearRatio / totalMass -- differential rad/s^2
720
721 -- The the difference in acceleration is due to gravity and thus will pull back the vehicle when changing gears and some other reasons (non-accounted mass (e.g. trees), collisions, wheel damping, wheel mass, ...)
722 -- Use a fixed factor of 90% to separate the effect of the gravity
723 local uncalculatedAccFactor = 0.9
724 local gravityAcc = math.max(expectedAcc*uncalculatedAccFactor - math.max(self.differentialRotAcceleration*gearSign, 0), 0)
725
726 --print(string.format("expectedAcc: %.3f realAcc: %.3f %.3f gravityAcc: %.3f gr: %.2f mass %.1f speed: %.3f dt %.2fms", expectedAcc, self.vehicle.lastSpeedAcceleration*1000*1000, self.differentialRotAcceleration, gravityAcc, gearRatio, totalMass, self.vehicle.lastSpeedReal*1000, g_physicsDtLastValidNonInterpolated))
727
728 diffSpeedAfterChange = math.max(differentialRotSpeed - gravityAcc * self.gearChangeTime*0.001, 0)
729 end
730
731
732 -- 2. Find the gear that gives the maximum power in the valid rpm range after the gear change
733 -- If none is valid, store the gear that will get closest to the valid rpm range
734
735 -- TODO allow some clutch slippage to extend the possible rpm range (e.g. when accelerating and switching from gear 1 to gear 2)
736
737 local maxPower = 0
738 local maxPowerGear = 0
739 for gear=1,#gearRatios do
740 local rpm
741 if gear == curGear then
742 rpm = clutchRpm
743 else
744 rpm = diffSpeedAfterChange * gearRatios[gear] * 30 / math.pi
745 end
746 if rpm <= maxAllowedRpm and rpm >= minAllowedRpm then
747 local power = self:getTorqueCurveValue(rpm) * rpm
748 --print(string.format(" power %.2f @ %.d", power, gear))
749 if power >= maxPower then
750 maxPower = power
751 maxPowerGear = gear
752 end
753 end
754 end
755
756 --local curPower = self:getTorqueCurveValue(clutchRpm) * clutchRpm
757 --print(string.format("power %.2f @ %d rpms: %.2f %.2f drpm: %.2f", curPower, curGear, clutchRpm, diffSpeedAfterChange* gearRatio * 30 / math.pi, self.differentialRotAccelerationSmoothed * gearRatio * 30 / math.pi))
758
759 -- 3. Find the gear with the best tradeoff (lots of power with low rpm)
760 -- Or use the the gear will get closest to the valid rpm range if none of the gears are good
761 if maxPowerGear ~= 0 then
762
763 local bestTradeoff = 0
764
765 for gear=#gearRatios,1,-1 do
766 local nextRpm
767 if gear == curGear then
768 nextRpm = clutchRpm
769 else
770 nextRpm = diffSpeedAfterChange * gearRatios[gear] * 30 / math.pi
771 end
772 if nextRpm <= maxAllowedRpm and nextRpm >= minAllowedRpm then
773 local nextPower = self:getTorqueCurveValue(nextRpm) * nextRpm
774
775 -- Choose the gear if it gets close enough to the max power
776 if nextPower >= maxPower*0.8 then
777 local powerFactor = (nextPower - maxPower*0.8) / (maxPower*0.2) -- 0 when at 80% of maxPower, 1 when at maxPower
778 local curSpeedRpm = differentialRpm * gearRatios[gear]
779 local rpmFactor = MathUtil.clamp((maxAllowedRpm - curSpeedRpm) / math.max(maxAllowedRpm-minAllowedRpm, 0.001), 0, 1)
780 local gearChangeFactor
781 if gear == curGear then
782 gearChangeFactor = 1
783 else
784 gearChangeFactor = math.min(-gearChangeTimer / 2000, 0.9) -- the longer we wait, the less penality we add for gear changes
785 end
786
787 if math.abs(acceleratorPedal) < 0.0001 then
788 rpmFactor = 1-rpmFactor -- choose a high rpm when decelerating
789 else
790 rpmFactor = rpmFactor * 3
791 end
792
793 local tradeoff = powerFactor + rpmFactor + gearChangeFactor
794
795 if tradeoff > bestTradeoff then
796 bestTradeoff = tradeoff
797 newGear = gear
798 --print(string.format("better tradeoff %.2f with %d power: %.2f vs %.2f @ %d rpm %.2f/%.2f vs %.2f factors: %.2f %.2f %.2f", tradeoff, gear, nextPower, maxPower, maxPowerGear, nextRpm, curSpeedRpm, clutchRpm, powerFactor, rpmFactor, gearChangeFactor))
799 else
800 --print(string.format("worse tradeoff %.2f with %d power: %.2f vs %.2f @ %d rpm %.2f/%.2f vs %.2f factors: %.2f %.2f %.2f", tradeoff, gear, nextPower, maxPower, maxPowerGear, nextRpm, curSpeedRpm, clutchRpm, powerFactor, rpmFactor, gearChangeFactor))
801 end
802 end
803 end
804 end
805 else
806 local minDiffGear = 0
807 local minDiff = math.huge
808 for gear=1,#gearRatios do
809 local rpm = diffSpeedAfterChange * gearRatios[gear] * 30 / math.pi
810 local diff = math.max(rpm - maxAllowedRpm, minAllowedRpm - rpm)
811 if diff < minDiff then
812 --print(string.format("better min diff gear: %d diff: %.2f rpm: %.2f" , gear, diff, rpm))
813 minDiff = diff
814 minDiffGear = gear
815 end
816 end
817 newGear = minDiffGear
818 end
819 return newGear
820end

getAccelerationLimit

Description
Definition
getAccelerationLimit()
Code
972function VehicleMotor:getAccelerationLimit()
973 return self.accelerationLimit
974end

getBestGear

Description
Returns best gear
Definition
getBestGear(float acceleration, float wheelSpeedRpm, float accSafeMotorRpm, float requiredMotorPower, float requiredMotorRpm)
Arguments
floataccelerationacceleration
floatwheelSpeedRpmwheel speed rpm
floataccSafeMotorRpmacc save motor rpm
floatrequiredMotorPowerrequired wheel torque
floatrequiredMotorRpmrequired motor rpm
Return Values
floatbestGearbest gear
floatgearRatiogear ratio
Code
575function VehicleMotor:getBestGear(acceleration, wheelSpeedRpm, accSafeMotorRpm, requiredMotorPower, requiredMotorRpm)
576 if math.abs(acceleration) < 0.001 then
577 acceleration = 1
578 if wheelSpeedRpm < 0 then
579 acceleration = -1
580 end
581 end
582 if acceleration > 0 then
583 if self.minForwardGearRatio ~= nil then
584 local wheelSpeedRpm = math.max(wheelSpeedRpm, 0)
585 local bestGearRatio = self:getBestGearRatio(wheelSpeedRpm, self.minForwardGearRatio, self.maxForwardGearRatio, accSafeMotorRpm, requiredMotorPower, requiredMotorRpm)
586 return 1, bestGearRatio
587 else
588 return 1, self.forwardGearRatios[1]
589 end
590 else
591 if self.minBackwardGearRatio ~= nil then
592 local wheelSpeedRpm = math.max(-wheelSpeedRpm, 0)
593 local bestGearRatio = self:getBestGearRatio(wheelSpeedRpm, self.minBackwardGearRatio, self.maxBackwardGearRatio, accSafeMotorRpm, requiredMotorPower, requiredMotorRpm)
594 return -1, -bestGearRatio
595 else
596 return -1, -self.backwardGearRatios[1]
597 end
598 end
599end

getBestGearRatio

Description
Returns best gear ratio
Definition
getBestGearRatio(float wheelSpeedRpm, float minRatio, float maxRatio, float accSafeMotorRpm, float requiredMotorPower, float requiredMotorRpm)
Arguments
floatwheelSpeedRpmwheel speed rpm
floatminRatiomin ratio
floatmaxRatiomax ratio
floataccSafeMotorRpmacc save motor rpm
floatrequiredMotorPowerthe required motor power [kW] (can be bigger than what the motor can actually achieve)
floatrequiredMotorRpmfixed motor rpm to be used (if not 0)
Return Values
floatbestGearRatiobest gear ratio
Code
530function VehicleMotor:getBestGearRatio(wheelSpeedRpm, minRatio, maxRatio, accSafeMotorRpm, requiredMotorPower, requiredMotorRpm)
531
532 if requiredMotorRpm ~= 0 then
533 local gearRatio = math.max(requiredMotorRpm-accSafeMotorRpm, requiredMotorRpm*0.8) / math.max(wheelSpeedRpm, 0.001)
534 gearRatio = MathUtil.clamp(gearRatio, minRatio, maxRatio)
535 return gearRatio
536 end
537
538 -- Use a minimum wheel rpm to avoid that gearRatio is ignored
539 wheelSpeedRpm = math.max(wheelSpeedRpm, 0.0001)
540
541 local bestMotorPower = 0
542 local bestGearRatio = minRatio
543 --local bestRPM = 0
544 -- TODO make this more efficient
545 for gearRatio = minRatio, maxRatio, 0.5 do
546 local motorRpm = wheelSpeedRpm * gearRatio
547 if motorRpm > self.maxRpm - accSafeMotorRpm then
548 break
549 end
550 local motorPower = self:getTorqueCurveValue(math.max(motorRpm, self.minRpm)) * motorRpm *math.pi/30
551 if motorPower > bestMotorPower then
552 bestMotorPower = motorPower
553 bestGearRatio = gearRatio
554 --bestRPM = motorRpm
555 end
556
557 if motorPower >= requiredMotorPower then
558 break
559 end
560 end
561 --print(string.format("Selected best gear: %f, %.2fkW rpm %.2f wheel %.2f", bestGearRatio, bestMotorPower, bestRPM, wheelSpeedRpm,))
562
563 return bestGearRatio
564end

getBrakeForce

Description
Returns brake force
Definition
getBrakeForce()
Return Values
floatbrakeForcebrake force
Code
256function VehicleMotor:getBrakeForce()
257 return self.brakeForce
258end

getClutchRotSpeed

Description
Returns clutch rpm
Definition
getClutchRotSpeed()
Return Values
floatclutchRpmclutch rpm
Code
370function VehicleMotor:getClutchRotSpeed()
371 return self.differentialRotSpeed * self.gearRatio
372end

getCurMaxRpm

Description
Returns current max rpm
Definition
getCurMaxRpm()
Return Values
IntegermaxRpmcurrent max rpm
Code
931function VehicleMotor:getCurMaxRpm()
932 local maxRpm = self.maxRpm
933
934 local gearRatio = self:getGearRatio()
935 if gearRatio ~= 0 then
936 --local speedLimit = self.speedLimit * 0.277778
937 local speedLimit = math.min(self.speedLimit, math.max(self.speedLimitAcc, self.vehicle.lastSpeedReal*3600)) * 0.277778
938 if gearRatio > 0 then
939 speedLimit = math.min(speedLimit, self.maxForwardSpeed)
940 else
941 speedLimit = math.min(speedLimit, self.maxBackwardSpeed)
942 end
943
944 maxRpm = math.min(maxRpm, speedLimit * 30 / math.pi * math.abs(gearRatio))
945 end
946
947 maxRpm = math.min(maxRpm, self.rpmLimit)
948 return maxRpm
949end

getDampingRateFullThrottle

Description
Returns the damping rate of the motor if the acceleration pedal is 1
Definition
getDampingRateFullThrottle()
Return Values
floatdampingRatedamping rate [t m^2 s^-1]
Code
191function VehicleMotor:getDampingRateFullThrottle()
192 return self.dampingRateFullThrottle
193end

getDampingRateZeroThrottleClutchDisengaged

Description
Returns the damping rate of the motor if the acceleration pedal is 0 and the clutch is disengaged
Definition
getDampingRateZeroThrottleClutchDisengaged()
Return Values
floatdampingRatedamping rate [t m^2 s^-1]
Code
205function VehicleMotor:getDampingRateZeroThrottleClutchDisengaged()
206 return self.dampingRateZeroThrottleClutchDisengaged
207end

getDampingRateZeroThrottleClutchEngaged

Description
Returns the damping rate of the motor if the acceleration pedal is 0 and the clutch is engaged
Definition
getDampingRateZeroThrottleClutchEngaged()
Return Values
floatdampingRatedamping rate [t m^2 s^-1]
Code
198function VehicleMotor:getDampingRateZeroThrottleClutchEngaged()
199 return self.dampingRateZeroThrottleClutchEngaged
200end

getEqualizedMotorRpm

Description
Returns equalized motor rpm
Definition
getEqualizedMotorRpm()
Return Values
floatequalizedMotorRpmequalized motor rpm
Code
333function VehicleMotor:getEqualizedMotorRpm()
334 return self.equalizedMotorRpm
335end

getGearRatio

Description
Definition
getGearRatio()
Code
924function VehicleMotor:getGearRatio()
925 return self.gearRatio
926end

getLastMotorRpm

Description
Returns last motor rpm damped
Definition
getLastMotorRpm()
Return Values
floatlastMotorRpmlast motor rpm
Code
289function VehicleMotor:getLastMotorRpm()
290 return self.lastMotorRpm
291end

getLastRealMotorRpm

Description
Returns last motor rpm real
Definition
getLastRealMotorRpm()
Return Values
floatlastMotorRpmlast motor rpm
Code
296function VehicleMotor:getLastRealMotorRpm()
297 return self.lastRealMotorRpm
298end

getMaxClutchTorque

Description
Returns max clutch torque
Definition
getMaxClutchTorque()
Return Values
floatmaxClutchTorquemax clutch torque
Code
170function VehicleMotor:getMaxClutchTorque()
171 return self.maxClutchTorque
172end

getMaximumBackwardSpeed

Description
Returns maximum backward speed
Definition
getMaximumBackwardSpeed()
Return Values
floatmaxBackwardSpeedmaximum backward speed
Code
424function VehicleMotor:getMaximumBackwardSpeed()
425 return self.maxBackwardSpeed
426end

getMaximumForwardSpeed

Description
Returns maximum forward speed
Definition
getMaximumForwardSpeed()
Return Values
floatmaxForwardSpeedmaximum forward speed
Code
417function VehicleMotor:getMaximumForwardSpeed()
418 return self.maxForwardSpeed
419end

getMaxRpm

Description
Returns max rpm
Definition
getMaxRpm()
Return Values
floatmaxRpmmax rpm
Code
270function VehicleMotor:getMaxRpm()
271 return self.maxRpm
272end

getMinMaxGearRatio

Description
Returns currently selected minimum and maximum gear ratio Gear ratios for driving backwards are negative. Min/max always refers to the absolute value For regular gear box transmission, the minimum and maximum gear ratios are identical
Definition
getMinMaxGearRatio()
Return Values
floatminGearRatiominimum gear ratio
floatmaxGearRatiomaximum gear ratio
Code
918function VehicleMotor:getMinMaxGearRatio()
919 return self.minGearRatio, self.maxGearRatio
920end

getMinRpm

Description
Returns min rpm
Definition
getMinRpm()
Return Values
floatminRpmmin rpm
Code
263function VehicleMotor:getMinRpm()
264 return self.minRpm
265end

getMotorAppliedTorque

Description
Returns the last applied torque to the motor
Definition
getMotorAppliedTorque()
Return Values
floatappliedTorquetorque [kN]
Code
312function VehicleMotor:getMotorAppliedTorque()
313 return self.motorAppliedTorque
314end

getMotorAvailableTorque

Description
Returns the last total available motor torque
Definition
getMotorAvailableTorque()
Return Values
floattorqueexternal torque [kN]
Code
326function VehicleMotor:getMotorAvailableTorque()
327 return self.motorAvailableTorque
328end

getMotorExternalTorque

Description
Returns the last applied external torque (torque used by external power consumers like the PTO)
Definition
getMotorExternalTorque()
Return Values
floatexternalTorqueexternal torque [kN]
Code
319function VehicleMotor:getMotorExternalTorque()
320 return self.motorExternalTorque
321end

getMotorRotationAccelerationLimit

Description
Definition
getMotorRotationAccelerationLimit()
Code
992function VehicleMotor:getMotorRotationAccelerationLimit()
993 return self.motorRotationAccelerationLimit
994end

getMotorRotSpeed

Description
Returns non clamped motor rpm
Definition
getMotorRotSpeed()
Return Values
floatnonClampedMotorRpmnon clamped motor rpm
Code
362function VehicleMotor:getMotorRotSpeed()
363 return self.motorRotSpeed
364end

getNonClampedMotorRpm

Description
Returns non clamped motor rpm
Definition
getNonClampedMotorRpm()
Return Values
floatnonClampedMotorRpmnon clamped motor rpm
Code
355function VehicleMotor:getNonClampedMotorRpm()
356 return self.motorRotSpeed * 30 / math.pi
357end

getPeakTorque

Description
Returns max torque
Definition
getPeakTorque()
Return Values
floatmaxMotorTorquemax motor torque
Code
249function VehicleMotor:getPeakTorque()
250 return self.peakMotorTorque
251end

getPtoMotorRpmRatio

Description
Returns pto motor rpm ratio
Definition
getPtoMotorRpmRatio()
Return Values
floatptoMotorRpmRatiopto motor rpm ratio
Code
348function VehicleMotor:getPtoMotorRpmRatio()
349 return self.ptoMotorRpmRatio
350end

getRequiredMotorRpmRange

Description
Returns the currently required motor rpm range (e.g. defined by the activated pto)
Definition
getRequiredMotorRpmRange()
Return Values
floatminRequiredRpmmin required rpm
floatminRequiredRpmmax required rpm
Code
278function VehicleMotor:getRequiredMotorRpmRange()
279 local motorPtoRpm = math.min(PowerConsumer.getMaxPtoRpm(self.vehicle)*self.ptoMotorRpmRatio, self.maxRpm)
280 if motorPtoRpm ~= 0 then
281 return motorPtoRpm, motorPtoRpm
282 end
283 return self.minRpm, self.maxRpm
284end

getRotInertia

Description
Returns rotation inertia
Definition
getRotInertia()
Return Values
floatrotInertiarotation inertia
Code
177function VehicleMotor:getRotInertia()
178 return self.rotInertia
179end

getSpeedLimit

Description
Definition
getSpeedLimit()
Code
960function VehicleMotor:getSpeedLimit()
961 return self.speedLimit
962end

getTorque

Description
Returns torque of the motor at the current rpm with the given accelerator pedal
Definition
getTorque(float acceleration)
Arguments
floataccelerationacceleration
Return Values
floattorquetorque
Code
385function VehicleMotor:getTorque(acceleration)
386 -- Note: the torque curve is undefined outside the min/max rpm range. Clamping makes the curve flat at the outside range
387 local torque = self:getTorqueCurveValue(MathUtil.clamp(self.motorRotSpeed * 30/math.pi, self.minRpm, self.maxRpm))
388 torque = torque * math.abs(acceleration)
389 return torque
390end

getTorqueAndSpeedValues

Description
Definition
getTorqueAndSpeedValues()
Code
403function VehicleMotor:getTorqueAndSpeedValues()
404 local rotationSpeeds = {}
405 local torques = {}
406 for _,v in ipairs(self:getTorqueCurve().keyframes) do
407 table.insert(rotationSpeeds, v.time*math.pi/30)
408 table.insert(torques, self:getTorqueCurveValue(v.time))
409 end
410
411 return torques, rotationSpeeds
412end

getTorqueCurve

Description
Returns torque curve
Definition
getTorqueCurve()
Return Values
tabletorqueCurvetorque curve
Code
377function VehicleMotor:getTorqueCurve()
378 return self.torqueCurve
379end

getTorqueCurveValue

Description
Returns torque of the motor at the given rpm
Definition
getTorqueCurveValue(float rpm)
Arguments
floatrpmrpm
Return Values
floattorquetorque
Code
396function VehicleMotor:getTorqueCurveValue(rpm)
397 local damage = 1 - (self.vehicle:getVehicleDamage() * VehicleMotor.DAMAGE_TORQUE_REDUCTION)
398 return self:getTorqueCurve():get(rpm) * damage
399end

new

Description
Creating new motor
Definition
new(Integer minRpm, Integer maxRpm, float maxForwardSpeed, float maxBackwardSpeed, table torqueCurve, float brakeForce, float forwardGearRatios, float backwardGearRatios, float minForwardGearRatio, float maxForwardGearRatio, float minBackwardGearRatio, float maxBackwardGearRatio, Integer ptoMotorRpmRatio)
Arguments
IntegerminRpmmin rpm
IntegermaxRpmmax rpm
floatmaxForwardSpeedmax forward speed
floatmaxBackwardSpeedmax backward speed
tabletorqueCurvetorque curve (AnimCurve)
floatbrakeForcebrake force
floatforwardGearRatioslist of gear ratios to use when driving forwards (in decreasing order)
floatbackwardGearRatioslist of gear ratios to use when driving backwards (in decreasing order)
floatminForwardGearRatiomin forward gear ratio
floatmaxForwardGearRatiomax forward gear ratio
floatminBackwardGearRatiomin backward gear ratio
floatmaxBackwardGearRatiomax backward gear ratio
IntegerptoMotorRpmRatiopto motor rpm ratio
Return Values
tablemotorInstancemotor instance
Code
33function VehicleMotor:new(vehicle, minRpm, maxRpm, maxForwardSpeed, maxBackwardSpeed, torqueCurve, brakeForce, forwardGearRatios, backwardGearRatios, minForwardGearRatio, maxForwardGearRatio, minBackwardGearRatio, maxBackwardGearRatio, ptoMotorRpmRatio, minSpeed)
34
35 local self = {}
36 setmetatable(self, VehicleMotor_mt)
37
38 self.vehicle = vehicle
39 self.minRpm = minRpm
40 self.maxRpm = maxRpm
41 self.minSpeed = minSpeed
42 self.maxForwardSpeed = maxForwardSpeed -- speed in m/s
43 self.maxBackwardSpeed = maxBackwardSpeed
44
45 self.maxClutchTorque = 5 -- amount of torque that can be transferred from motor to clutch/wheels [t m s^-2]
46
47 self.torqueCurve = torqueCurve
48 self.brakeForce = brakeForce
49
50 self.gear = 0
51 self.minGearRatio = 0
52 self.maxGearRatio = 0
53
54 self.forwardGearRatios = forwardGearRatios
55 self.backwardGearRatios = backwardGearRatios
56 self.minForwardGearRatio = minForwardGearRatio
57 self.maxForwardGearRatio = maxForwardGearRatio
58 self.minBackwardGearRatio = minBackwardGearRatio
59 self.maxBackwardGearRatio = maxBackwardGearRatio
60
61 self.manualTargetGear = nil
62 self.targetGear = 0
63 self.previousGear = 0
64 self.gearChangeTimer = -1
65 self.gearChangeTime = 250
66 self.autoGearChangeTimer = -1
67 self.autoGearChangeTime = 1000
68
69 self.lastRealMotorRpm = 0
70 self.lastMotorRpm = 0
71
72 self.rpmLimit = math.huge
73 self.speedLimit = math.huge -- Speed limit in km/h
74 self.speedLimitAcc = math.huge
75
76 self.accelerationLimit = 2 -- m s^-2
77
78 self.motorRotationAccelerationLimit = (maxRpm - minRpm)*math.pi/30 / 2 -- rad s^-2 default accelerate from min rpm to max rpm in 2 sec
79
80 self.equalizedMotorRpm = 0
81
82 self.requiredMotorPower = 0
83
84 if self.maxForwardSpeed == nil then
85 self.maxForwardSpeed = self:calculatePhysicalMaximumForwardSpeed()
86 end
87 if self.maxBackwardSpeed == nil then
88 self.maxBackwardSpeed = self:calculatePhysicalMaximumBackwardSpeed()
89 end
90
91 self.peakMotorTorque = self.torqueCurve:getMaximum()
92
93 -- Calculate peak power. Assume we have a linear interpolation on the torque values
94 -- For each segment, find the maximum power (D[torque(x, i) * x] == 0) and take the maximum segment
95 -- D[ ((x-x0) / (x1-x0) (y1-y0) + y0) x] == 0
96 -- -> (x1 y0 - x0 y1) / (2 (y0 - y1)) if y0 != y1
97 self.peakMotorPower = 0
98 self.peakMotorPowerRotSpeed = 0
99 local numKeyFrames = #self.torqueCurve.keyframes
100 if numKeyFrames >= 2 then
101 for i=2,numKeyFrames do
102 local v0 = self.torqueCurve.keyframes[i-1]
103 local v1 = self.torqueCurve.keyframes[i]
104 local torque0 = self.torqueCurve:getFromKeyframes(v0, v0, i-1, i-1, 0)
105 local torque1 = self.torqueCurve:getFromKeyframes(v1, v1, i, i, 0)
106 local rpm, torque
107 if math.abs(torque0 - torque1) > 0.0001 then
108 rpm = (v1.time * torque0 - v0.time * torque1) / (2.0 * (torque0 - torque1))
109 rpm = math.min(math.max(rpm, v0.time), v1.time)
110 torque = self.torqueCurve:getFromKeyframes(v0, v1, i-1, i, (v1.time - rpm) / (v1.time - v0.time))
111 else
112 rpm = v0.time
113 torque = torque0
114 end
115 local power = torque * rpm
116 if power > self.peakMotorPower then
117 self.peakMotorPower = power
118 self.peakMotorPowerRotSpeed = rpm
119 end
120 end
121 -- Convert from rpm to rad/s
122 self.peakMotorPower = self.peakMotorPower * math.pi/30
123 self.peakMotorPowerRotSpeed = self.peakMotorPowerRotSpeed * math.pi/30
124 else
125 local v = self.torqueCurve.keyframes[1]
126 local rotSpeed = v.time*math.pi/30
127 local torque = self.torqueCurve:getFromKeyframes(v, v, i, i, 0)
128 self.peakMotorPower = rotSpeed*torque
129 self.peakMotorPowerRotSpeed = rotSpeed
130 end
131
132 self.ptoMotorRpmRatio = ptoMotorRpmRatio
133
134 self.rotInertia = self.peakMotorTorque / 600 -- Rotational inertia of the motor, mostly defined by the flywheel [t m^2]
135 self.dampingRateFullThrottle = 0.00015 -- Damping rate of the motor if the acceleration pedal is 1 [t m^2 s^-1]
136 self.dampingRateZeroThrottleClutchEngaged = 0.001 -- Damping rate of the motor if the acceleration pedal is 0 and the clutch is engaged [t m^2 s^-1]
137 self.dampingRateZeroThrottleClutchDisengaged = 0.001 -- Damping rate of the motor if the acceleration pedal is 0 and the clutch is disengaged [t m^2 s^-1]
138
139
140
141 -- Motor properties as read from the physics engine
142 self.gearRatio = 0
143 self.motorRotSpeed = 0 -- motor rotation speed [rad/s]
144 self.motorRotAcceleration = 0 -- motor rotation acceleration [rad/s^2]
145 self.motorRotAccelerationSmoothed = 0 -- motor rotation acceleration smoothed [rad/s^2]
146
147 self.motorAvailableTorque = 0 -- torque that was available to the physics simulation [kN == t m/s^2]
148 self.motorAppliedTorque = 0 -- torque that was applied (<= available), can be smaller when acceleration/speed is limited [kN == t m/s^2]
149 self.motorExternalTorque = 0 -- torque that was removed from the motor and was not applied to the wheels (e.g. PTO) [kN == t m/s^2]
150
151 self.differentialRotSpeed = 0 -- rotation speed of the main differential [rad/s]
152 self.differentialRotAcceleration = 0 -- rotation accleration of the main differential [rad/s^2]
153 self.differentialRotAccelerationSmoothed = 0 -- smoothed rotation accleration of the main differential [rad/s^2]
154
155 return self
156end

setAccelerationLimit

Description
Definition
setAccelerationLimit()
Code
966function VehicleMotor:setAccelerationLimit(accelerationLimit)
967 self.accelerationLimit = accelerationLimit
968end

setAutoGearChangeTime

Description
Sets the time that needs to pass since the last gear change until an automatic gear change is allowed
Definition
setAutoGearChangeTime(float autoGearChangeTime)
Arguments
floatautoGearChangeTimeautomatic gear change time [ms]
Code
241function VehicleMotor:setAutoGearChangeTime(autoGearChangeTime)
242 self.autoGearChangeTime = autoGearChangeTime
243 self.autoGearChangeTimer = math.min(self.autoGearChangeTimer, autoGearChangeTime)
244end

setDampingRateFullThrottle

Description
Sets the damping rate of the motor if the acceleration pedal is 1
Definition
setDampingRateFullThrottle(float dampingRate)
Arguments
floatdampingRatenew damping rate [t m^2 s^-1]
Code
212function VehicleMotor:setDampingRateFullThrottle(dampingRate)
213 self.dampingRateFullThrottle = dampingRate
214end

setDampingRateZeroThrottleClutchDisengaged

Description
Sets the damping rate of the motor if the acceleration pedal is 0 and the clutch is disengaged
Definition
setDampingRateZeroThrottleClutchDisengaged(float dampingRate)
Arguments
floatdampingRatenew damping rate [t m^2 s^-1]
Code
226function VehicleMotor:setDampingRateZeroThrottleClutchDisengaged(dampingRate)
227 self.dampingRateZeroThrottleClutchDisengaged = dampingRate
228end

setDampingRateZeroThrottleClutchEngaged

Description
Sets the damping rate of the motor if the acceleration pedal is 0 and the clutch is engaged
Definition
setDampingRateZeroThrottleClutchEngaged(float dampingRate)
Arguments
floatdampingRatenew damping rate [t m^2 s^-1]
Code
219function VehicleMotor:setDampingRateZeroThrottleClutchEngaged(dampingRate)
220 self.dampingRateZeroThrottleClutchEngaged = dampingRate
221end

setEqualizedMotorRpm

Description
Sets equalized motor rpm
Definition
setEqualizedMotorRpm(float equalizedMotorRpm)
Arguments
floatequalizedMotorRpmequalized motor rpm
Code
340function VehicleMotor:setEqualizedMotorRpm(rpm)
341 self.equalizedMotorRpm = rpm
342 self:setLastRpm(rpm)
343end

setGearChangeTime

Description
Sets the time it takes change gears
Definition
setGearChangeTime(float gearChangeTime)
Arguments
floatgearChangeTimegear change time [ms]
Code
233function VehicleMotor:setGearChangeTime(gearChangeTime)
234 self.gearChangeTime = gearChangeTime
235 self.gearChangeTimer = math.min(self.gearChangeTimer, gearChangeTime)
236end

setLastRpm

Description
Sets last motor rpm
Definition
setLastRpm(float lastRpm)
Arguments
floatlastRpmnew last motor rpm
Code
303function VehicleMotor:setLastRpm(lastRpm)
304 self.lastRealMotorRpm = lastRpm
305
306 self.lastMotorRpm = self.lastMotorRpm * 0.95 + self.lastRealMotorRpm * 0.05
307end

setLowBrakeForce

Description
Set low brake force
Definition
setLowBrakeForce(float lowBrakeForceScale, float lowBrakeForceSpeedLimit)
Arguments
floatlowBrakeForceScalelow brake force scale
floatlowBrakeForceSpeedLimitlow brake force speed limit
Code
162function VehicleMotor:setLowBrakeForce(lowBrakeForceScale, lowBrakeForceSpeedLimit)
163 self.lowBrakeForceScale = lowBrakeForceScale
164 self.lowBrakeForceSpeedLimit = lowBrakeForceSpeedLimit
165end

setMotorRotationAccelerationLimit

Description
Definition
setMotorRotationAccelerationLimit()
Code
986function VehicleMotor:setMotorRotationAccelerationLimit(limit)
987 self.motorRotationAccelerationLimit = limit
988end

setRotInertia

Description
Sets rotation inertia
Definition
setRotInertia(float rotInertia)
Arguments
floatrotInertiarotation inertia
Code
184function VehicleMotor:setRotInertia(rotInertia)
185 self.rotInertia = rotInertia
186end

setRpmLimit

Description
Sets rpm limit
Definition
setRpmLimit(float limit)
Arguments
floatlimitnew limit
Code
979function VehicleMotor:setRpmLimit(rpmLimit)
980 self.rpmLimit = rpmLimit
981end

setSpeedLimit

Description
Sets speed limit
Definition
setSpeedLimit(float limit)
Arguments
floatlimitnew limit
Code
954function VehicleMotor:setSpeedLimit(limit)
955 self.speedLimit = math.max(limit, self.minSpeed)
956end

update

Description
Update the state of the motor (sync with physics simulation)
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
464function VehicleMotor:update(dt)
465 local vehicle = self.vehicle
466 if next(vehicle.spec_motorized.differentials) ~= nil and vehicle.spec_motorized.motorizedNode ~= nil then
467 -- Only update the physics values if a physics simulation was performed
468 if g_physicsDtNonInterpolated > 0.0 then
469 local lastMotorRotSpeed = self.motorRotSpeed;
470 local lastDiffRotSpeed = self.differentialRotSpeed
471 self.motorRotSpeed, self.differentialRotSpeed, self.gearRatio = getMotorRotationSpeed(vehicle.spec_motorized.motorizedNode)
472
473 self.motorAvailableTorque, self.motorAppliedTorque, self.motorExternalTorque = getMotorTorque(vehicle.spec_motorized.motorizedNode)
474
475
476 local motorRotAcceleration = (self.motorRotSpeed - lastMotorRotSpeed) / (g_physicsDtNonInterpolated*0.001)
477 self.motorRotAcceleration = motorRotAcceleration
478 self.motorRotAccelerationSmoothed = 0.8 * self.motorRotAccelerationSmoothed + 0.2 * motorRotAcceleration
479
480 local diffRotAcc = (self.differentialRotSpeed - lastDiffRotSpeed) / (g_physicsDtNonInterpolated*0.001)
481 self.differentialRotAcceleration = diffRotAcc
482 self.differentialRotAccelerationSmoothed = 0.8 * self.differentialRotAccelerationSmoothed + 0.2 * diffRotAcc
483
484 --print(string.format("update rpms: %.2f %.2f acc: %.2f", self.motorRotSpeed*30/math.pi, self.differentialRotSpeed*self.gearRatio*30/math.pi, motorRotAcceleration))
485 end
486
487 self.requiredMotorPower = math.huge
488
489 else
490 local _, gearRatio = self:getMinMaxGearRatio()
491 self.differentialRotSpeed = WheelsUtil.computeDifferentialRotSpeedNonMotor(vehicle)
492 self.motorRotSpeed = math.max(math.abs(self.differentialRotSpeed * gearRatio), 0)
493 self.gearRatio = gearRatio
494 end
495
496 -- the clamped motor rpm always is higher-equal than the required rpm by the pto
497 --local ptoRpm = math.min(PowerConsumer.getMaxPtoRpm(self.vehicle)*self.ptoMotorRpmRatio, self.maxRpm)
498 -- smoothing for raise/fall of ptoRpm
499 if self.lastPtoRpm == nil then
500 self.lastPtoRpm = self.minRpm
501 end
502 local ptoRpm = PowerConsumer.getMaxPtoRpm(self.vehicle)*self.ptoMotorRpmRatio
503 if ptoRpm > self.lastPtoRpm then
504 self.lastPtoRpm = math.min(ptoRpm, self.lastPtoRpm + self.maxRpm*dt/2000)
505 elseif ptoRpm < self.lastPtoRpm then
506 self.lastPtoRpm = math.max(self.minRpm, self.lastPtoRpm - self.maxRpm*dt/1000)
507 end
508 local ptoRpm = math.min(self.lastPtoRpm, self.maxRpm)
509
510 local clampedMotorRpm = math.max(self.motorRotSpeed*30/math.pi, ptoRpm, self.minRpm)
511
512 self:setLastRpm(clampedMotorRpm)
513
514 -- client will recieve this value from the server
515 if self.vehicle.isServer then
516 self.equalizedMotorRpm = clampedMotorRpm
517 end
518end

updateGear

Description
Update gear
Definition
updateGear(float acceleratorPedal)
Arguments
floatacceleratorPedalacceleratorPedal
Return Values
floatadjustedAcceleratorPedalthe adjusted accelerator pedal for the current gear situation (e.g. 0 while switching gears)
Code
826function VehicleMotor:updateGear(acceleratorPedal, dt)
827 local adjAcceleratorPedal = acceleratorPedal
828 if self.gearChangeTimer >= 0 then
829 self.gearChangeTimer = self.gearChangeTimer - dt;
830 if self.gearChangeTimer < 0 then
831 if self.targetGear > 0 then
832 -- give the logic another chance to choose a better gear at the time when the gear change should happen
833 self.gear = self:findGearChangeTargetGear(self.targetGear, self.previousGear, self.forwardGearRatios, 1, acceleratorPedal, dt)
834 self.minGearRatio = self.forwardGearRatios[self.gear]
835 else
836 self.gear = -self:findGearChangeTargetGear(-self.targetGear, -self.previousGear, self.backwardGearRatios, -1, acceleratorPedal, dt)
837 self.minGearRatio = -self.backwardGearRatios[-self.gear]
838 end
839 self.maxGearRatio = self.minGearRatio
840 end
841 adjAcceleratorPedal = 0
842 else
843 local gearSign = 0
844 if acceleratorPedal > 0 then
845 if self.minForwardGearRatio ~= nil then
846 self.minGearRatio = self.minForwardGearRatio
847 self.maxGearRatio = self.maxForwardGearRatio
848 else
849 gearSign = 1
850 end
851 elseif acceleratorPedal < 0 then
852 if self.minBackwardGearRatio ~= nil then
853 self.minGearRatio = -self.minBackwardGearRatio
854 self.maxGearRatio = -self.maxBackwardGearRatio
855 else
856 gearSign = -1
857 end
858 else
859 if self.maxGearRatio > 0 then
860 if self.minForwardGearRatio == nil then
861 gearSign = 1
862 end
863 elseif self.maxGearRatio < 0 then
864 if self.minBackwardGearRatio == nil then
865 gearSign = -1
866 end
867 end
868 end
869
870 self.autoGearChangeTimer = self.autoGearChangeTimer - dt
871 local newGear = self.gear
872 if g_manualGearShift then
873 if self.manualTargetGear ~= nil then
874 newGear = self.manualTargetGear
875 self.manualTargetGear = nil
876 end
877 else
878 if gearSign > 0 then
879 if self.gear <= 0 then
880 newGear = 1
881 else
882 if self.autoGearChangeTimer <= 0 then
883 newGear = self:findGearChangeTargetGearPrediction(self.gear, self.forwardGearRatios, 1, self.autoGearChangeTimer, acceleratorPedal, dt)
884 end
885 newGear = math.min(math.max(newGear, 1), #self.forwardGearRatios)
886 end
887 elseif gearSign < 0 then
888 if self.gear >= 0 then
889 newGear = -1
890 else
891 if self.autoGearChangeTimer <= 0 then
892 newGear = -self:findGearChangeTargetGearPrediction(-self.gear, self.backwardGearRatios, -1, self.autoGearChangeTimer, acceleratorPedal, dt)
893 end
894 newGear = math.max(math.min(newGear, -1), -#self.backwardGearRatios)
895 end
896 end
897 end
898 if newGear ~= self.gear then
899 self.targetGear = newGear
900 self.previousGear = self.gear
901 self.gear = 0
902 self.minGearRatio = 0
903 self.maxGearRatio = 0
904 self.autoGearChangeTimer = self.autoGearChangeTime
905 self.gearChangeTimer = self.gearChangeTime
906 adjAcceleratorPedal = 0
907 end
908 end
909 return adjAcceleratorPedal
910end