WheeledVehicleController.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Physics/Vehicle/VehicleConstraint.h>
  6. #include <Jolt/Physics/Vehicle/VehicleController.h>
  7. #include <Jolt/Physics/Vehicle/VehicleEngine.h>
  8. #include <Jolt/Physics/Vehicle/VehicleTransmission.h>
  9. #include <Jolt/Physics/Vehicle/VehicleDifferential.h>
  10. #include <Jolt/Core/LinearCurve.h>
  11. JPH_NAMESPACE_BEGIN
  12. class PhysicsSystem;
  13. /// WheelSettings object specifically for WheeledVehicleController
  14. class JPH_EXPORT WheelSettingsWV : public WheelSettings
  15. {
  16. public:
  17. JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheelSettingsWV)
  18. /// Constructor
  19. WheelSettingsWV();
  20. // See: WheelSettings
  21. virtual void SaveBinaryState(StreamOut &inStream) const override;
  22. virtual void RestoreBinaryState(StreamIn &inStream) override;
  23. float mInertia = 0.9f; ///< Moment of inertia (kg m^2), for a cylinder this would be 0.5 * M * R^2 which is 0.9 for a wheel with a mass of 20 kg and radius 0.3 m
  24. float mAngularDamping = 0.2f; ///< Angular damping factor of the wheel: dw/dt = -c * w
  25. float mMaxSteerAngle = DegreesToRadians(70.0f); ///< How much this wheel can steer (radians)
  26. LinearCurve mLongitudinalFriction; ///< Friction in forward direction of tire as a function of the slip ratio (fraction): (omega_wheel * r_wheel - v_longitudinal) / |v_longitudinal|
  27. LinearCurve mLateralFriction; ///< Friction in sideway direction of tire as a function of the slip angle (degrees): angle between relative contact velocity and vehicle direction
  28. float mMaxBrakeTorque = 1500.0f; ///< How much torque (Nm) the brakes can apply to this wheel
  29. float mMaxHandBrakeTorque = 4000.0f; ///< How much torque (Nm) the hand brake can apply to this wheel (usually only applied to the rear wheels)
  30. };
  31. /// Wheel object specifically for WheeledVehicleController
  32. class JPH_EXPORT WheelWV : public Wheel
  33. {
  34. public:
  35. JPH_OVERRIDE_NEW_DELETE
  36. /// Constructor
  37. explicit WheelWV(const WheelSettingsWV &inWheel);
  38. /// Override GetSettings and cast to the correct class
  39. const WheelSettingsWV * GetSettings() const { return static_cast<const WheelSettingsWV *>(mSettings.GetPtr()); }
  40. /// Apply a torque (N m) to the wheel for a particular delta time
  41. void ApplyTorque(float inTorque, float inDeltaTime)
  42. {
  43. mAngularVelocity += inTorque * inDeltaTime / GetSettings()->mInertia;
  44. }
  45. /// Update the wheel rotation based on the current angular velocity
  46. void Update(float inDeltaTime, const VehicleConstraint &inConstraint);
  47. float mLongitudinalSlip = 0.0f; ///< Velocity difference between ground and wheel relative to ground velocity
  48. float mCombinedLongitudinalFriction = 0.0f; ///< Combined friction coefficient in longitudinal direction (combines terrain and tires)
  49. float mCombinedLateralFriction = 0.0f; ///< Combined friction coefficient in lateral direction (combines terrain and tires)
  50. float mBrakeImpulse = 0.0f; ///< Amount of impulse that the brakes can apply to the floor (excluding friction)
  51. };
  52. /// Settings of a vehicle with regular wheels
  53. ///
  54. /// The properties in this controller are largely based on "Car Physics for Games" by Marco Monster.
  55. /// See: https://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html
  56. class JPH_EXPORT WheeledVehicleControllerSettings : public VehicleControllerSettings
  57. {
  58. public:
  59. JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheeledVehicleControllerSettings)
  60. // See: VehicleControllerSettings
  61. virtual VehicleController * ConstructController(VehicleConstraint &inConstraint) const override;
  62. virtual void SaveBinaryState(StreamOut &inStream) const override;
  63. virtual void RestoreBinaryState(StreamIn &inStream) override;
  64. VehicleEngineSettings mEngine; ///< The properties of the engine
  65. VehicleTransmissionSettings mTransmission; ///< The properties of the transmission (aka gear box)
  66. Array<VehicleDifferentialSettings> mDifferentials; ///< List of differentials and their properties
  67. float mDifferentialLimitedSlipRatio = 1.4f; ///< Ratio max / min average wheel speed of each differential (measured at the clutch). When the ratio is exceeded all torque gets distributed to the differential with the minimal average velocity. This allows implementing a limited slip differential between differentials. Set to FLT_MAX for an open differential. Value should be > 1.
  68. };
  69. /// Runtime controller class
  70. class JPH_EXPORT WheeledVehicleController : public VehicleController
  71. {
  72. public:
  73. JPH_OVERRIDE_NEW_DELETE
  74. /// Constructor
  75. WheeledVehicleController(const WheeledVehicleControllerSettings &inSettings, VehicleConstraint &inConstraint);
  76. /// Typedefs
  77. using Differentials = Array<VehicleDifferentialSettings>;
  78. /// Set input from driver
  79. /// @param inForward Value between -1 and 1 for auto transmission and value between 0 and 1 indicating desired driving direction and amount the gas pedal is pressed
  80. /// @param inRight Value between -1 and 1 indicating desired steering angle (1 = right)
  81. /// @param inBrake Value between 0 and 1 indicating how strong the brake pedal is pressed
  82. /// @param inHandBrake Value between 0 and 1 indicating how strong the hand brake is pulled
  83. void SetDriverInput(float inForward, float inRight, float inBrake, float inHandBrake) { mForwardInput = inForward; mRightInput = inRight; mBrakeInput = inBrake; mHandBrakeInput = inHandBrake; }
  84. /// Get current engine state
  85. const VehicleEngine & GetEngine() const { return mEngine; }
  86. /// Get current engine state (writable interface, allows you to make changes to the configuration which will take effect the next time step)
  87. VehicleEngine & GetEngine() { return mEngine; }
  88. /// Get current transmission state
  89. const VehicleTransmission & GetTransmission() const { return mTransmission; }
  90. /// Get current transmission state (writable interface, allows you to make changes to the configuration which will take effect the next time step)
  91. VehicleTransmission & GetTransmission() { return mTransmission; }
  92. /// Get the differentials this vehicle has
  93. const Differentials & GetDifferentials() const { return mDifferentials; }
  94. /// Get the differentials this vehicle has (writable interface, allows you to make changes to the configuration which will take effect the next time step)
  95. Differentials & GetDifferentials() { return mDifferentials; }
  96. /// Ratio max / min average wheel speed of each differential (measured at the clutch).
  97. float GetDifferentialLimitedSlipRatio() const { return mDifferentialLimitedSlipRatio; }
  98. void SetDifferentialLimitedSlipRatio(float inV) { mDifferentialLimitedSlipRatio = inV; }
  99. /// Get the average wheel speed of all driven wheels (measured at the clutch)
  100. float GetWheelSpeedAtClutch() const;
  101. #ifdef JPH_DEBUG_RENDERER
  102. /// Debug drawing of RPM meter
  103. void SetRPMMeter(Vec3Arg inPosition, float inSize) { mRPMMeterPosition = inPosition; mRPMMeterSize = inSize; }
  104. #endif // JPH_DEBUG_RENDERER
  105. protected:
  106. // See: VehicleController
  107. virtual Wheel * ConstructWheel(const WheelSettings &inWheel) const override { JPH_ASSERT(IsKindOf(&inWheel, JPH_RTTI(WheelSettingsWV))); return new WheelWV(static_cast<const WheelSettingsWV &>(inWheel)); }
  108. virtual bool AllowSleep() const override;
  109. virtual void PreCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;
  110. virtual void PostCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;
  111. virtual bool SolveLongitudinalAndLateralConstraints(float inDeltaTime) override;
  112. virtual void SaveState(StateRecorder &inStream) const override;
  113. virtual void RestoreState(StateRecorder &inStream) override;
  114. #ifdef JPH_DEBUG_RENDERER
  115. virtual void Draw(DebugRenderer *inRenderer) const override;
  116. #endif // JPH_DEBUG_RENDERER
  117. // Control information
  118. float mForwardInput = 0.0f; ///< Value between -1 and 1 for auto transmission and value between 0 and 1 indicating desired driving direction and amount the gas pedal is pressed
  119. float mRightInput = 0.0f; ///< Value between -1 and 1 indicating desired steering angle
  120. float mBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the brake pedal is pressed
  121. float mHandBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the hand brake is pulled
  122. // Simluation information
  123. VehicleEngine mEngine; ///< Engine state of the vehicle
  124. VehicleTransmission mTransmission; ///< Transmission state of the vehicle
  125. Differentials mDifferentials; ///< Differential states of the vehicle
  126. float mDifferentialLimitedSlipRatio; ///< Ratio max / min average wheel speed of each differential (measured at the clutch).
  127. float mPreviousDeltaTime = 0.0f; ///< Delta time of the last step
  128. #ifdef JPH_DEBUG_RENDERER
  129. // Debug settings
  130. Vec3 mRPMMeterPosition { 0, 1, 0 }; ///< Position (in local space of the body) of the RPM meter when drawing the constraint
  131. float mRPMMeterSize = 0.5f; ///< Size of the RPM meter when drawing the constraint
  132. #endif // JPH_DEBUG_RENDERER
  133. };
  134. JPH_NAMESPACE_END