Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Vehicle/WheeledVehicleController.h
9912 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Physics/Vehicle/VehicleConstraint.h>
8
#include <Jolt/Physics/Vehicle/VehicleController.h>
9
#include <Jolt/Physics/Vehicle/VehicleEngine.h>
10
#include <Jolt/Physics/Vehicle/VehicleTransmission.h>
11
#include <Jolt/Physics/Vehicle/VehicleDifferential.h>
12
#include <Jolt/Core/LinearCurve.h>
13
14
JPH_NAMESPACE_BEGIN
15
16
class PhysicsSystem;
17
18
/// WheelSettings object specifically for WheeledVehicleController
19
class JPH_EXPORT WheelSettingsWV : public WheelSettings
20
{
21
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheelSettingsWV)
22
23
public:
24
/// Constructor
25
WheelSettingsWV();
26
27
// See: WheelSettings
28
virtual void SaveBinaryState(StreamOut &inStream) const override;
29
virtual void RestoreBinaryState(StreamIn &inStream) override;
30
31
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
32
float mAngularDamping = 0.2f; ///< Angular damping factor of the wheel: dw/dt = -c * w
33
float mMaxSteerAngle = DegreesToRadians(70.0f); ///< How much this wheel can steer (radians)
34
LinearCurve mLongitudinalFriction; ///< On the Y-axis: friction in the forward direction of the tire. Friction is normally between 0 (no friction) and 1 (full friction) although friction can be a little bit higher than 1 because of the profile of a tire. On the X-axis: the slip ratio (fraction) defined as (omega_wheel * r_wheel - v_longitudinal) / |v_longitudinal|. You can see slip ratio as the amount the wheel is spinning relative to the floor: 0 means the wheel has full traction and is rolling perfectly in sync with the ground, 1 is for example when the wheel is locked and sliding over the ground.
35
LinearCurve mLateralFriction; ///< On the Y-axis: friction in the sideways direction of the tire. Friction is normally between 0 (no friction) and 1 (full friction) although friction can be a little bit higher than 1 because of the profile of a tire. On the X-axis: the slip angle (degrees) defined as angle between relative contact velocity and tire direction.
36
float mMaxBrakeTorque = 1500.0f; ///< How much torque (Nm) the brakes can apply to this wheel
37
float mMaxHandBrakeTorque = 4000.0f; ///< How much torque (Nm) the hand brake can apply to this wheel (usually only applied to the rear wheels)
38
};
39
40
/// Wheel object specifically for WheeledVehicleController
41
class JPH_EXPORT WheelWV : public Wheel
42
{
43
public:
44
JPH_OVERRIDE_NEW_DELETE
45
46
/// Constructor
47
explicit WheelWV(const WheelSettingsWV &inWheel);
48
49
/// Override GetSettings and cast to the correct class
50
const WheelSettingsWV * GetSettings() const { return StaticCast<WheelSettingsWV>(mSettings); }
51
52
/// Apply a torque (N m) to the wheel for a particular delta time
53
void ApplyTorque(float inTorque, float inDeltaTime)
54
{
55
mAngularVelocity += inTorque * inDeltaTime / GetSettings()->mInertia;
56
}
57
58
/// Update the wheel rotation based on the current angular velocity
59
void Update(uint inWheelIndex, float inDeltaTime, const VehicleConstraint &inConstraint);
60
61
float mLongitudinalSlip = 0.0f; ///< Velocity difference between ground and wheel relative to ground velocity
62
float mLateralSlip = 0.0f; ///< Angular difference (in radians) between ground and wheel relative to ground velocity
63
float mCombinedLongitudinalFriction = 0.0f; ///< Combined friction coefficient in longitudinal direction (combines terrain and tires)
64
float mCombinedLateralFriction = 0.0f; ///< Combined friction coefficient in lateral direction (combines terrain and tires)
65
float mBrakeImpulse = 0.0f; ///< Amount of impulse that the brakes can apply to the floor (excluding friction)
66
};
67
68
/// Settings of a vehicle with regular wheels
69
///
70
/// The properties in this controller are largely based on "Car Physics for Games" by Marco Monster.
71
/// See: https://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html
72
class JPH_EXPORT WheeledVehicleControllerSettings : public VehicleControllerSettings
73
{
74
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheeledVehicleControllerSettings)
75
76
public:
77
// See: VehicleControllerSettings
78
virtual VehicleController * ConstructController(VehicleConstraint &inConstraint) const override;
79
virtual void SaveBinaryState(StreamOut &inStream) const override;
80
virtual void RestoreBinaryState(StreamIn &inStream) override;
81
82
VehicleEngineSettings mEngine; ///< The properties of the engine
83
VehicleTransmissionSettings mTransmission; ///< The properties of the transmission (aka gear box)
84
Array<VehicleDifferentialSettings> mDifferentials; ///< List of differentials and their properties
85
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.
86
};
87
88
/// Runtime controller class
89
class JPH_EXPORT WheeledVehicleController : public VehicleController
90
{
91
public:
92
JPH_OVERRIDE_NEW_DELETE
93
94
/// Constructor
95
WheeledVehicleController(const WheeledVehicleControllerSettings &inSettings, VehicleConstraint &inConstraint);
96
97
/// Typedefs
98
using Differentials = Array<VehicleDifferentialSettings>;
99
100
/// Set input from driver
101
/// @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
102
/// @param inRight Value between -1 and 1 indicating desired steering angle (1 = right)
103
/// @param inBrake Value between 0 and 1 indicating how strong the brake pedal is pressed
104
/// @param inHandBrake Value between 0 and 1 indicating how strong the hand brake is pulled
105
void SetDriverInput(float inForward, float inRight, float inBrake, float inHandBrake) { mForwardInput = inForward; mRightInput = inRight; mBrakeInput = inBrake; mHandBrakeInput = inHandBrake; }
106
107
/// 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
108
void SetForwardInput(float inForward) { mForwardInput = inForward; }
109
float GetForwardInput() const { return mForwardInput; }
110
111
/// Value between -1 and 1 indicating desired steering angle (1 = right)
112
void SetRightInput(float inRight) { mRightInput = inRight; }
113
float GetRightInput() const { return mRightInput; }
114
115
/// Value between 0 and 1 indicating how strong the brake pedal is pressed
116
void SetBrakeInput(float inBrake) { mBrakeInput = inBrake; }
117
float GetBrakeInput() const { return mBrakeInput; }
118
119
/// Value between 0 and 1 indicating how strong the hand brake is pulled
120
void SetHandBrakeInput(float inHandBrake) { mHandBrakeInput = inHandBrake; }
121
float GetHandBrakeInput() const { return mHandBrakeInput; }
122
123
/// Get current engine state
124
const VehicleEngine & GetEngine() const { return mEngine; }
125
126
/// Get current engine state (writable interface, allows you to make changes to the configuration which will take effect the next time step)
127
VehicleEngine & GetEngine() { return mEngine; }
128
129
/// Get current transmission state
130
const VehicleTransmission & GetTransmission() const { return mTransmission; }
131
132
/// Get current transmission state (writable interface, allows you to make changes to the configuration which will take effect the next time step)
133
VehicleTransmission & GetTransmission() { return mTransmission; }
134
135
/// Get the differentials this vehicle has
136
const Differentials & GetDifferentials() const { return mDifferentials; }
137
138
/// Get the differentials this vehicle has (writable interface, allows you to make changes to the configuration which will take effect the next time step)
139
Differentials & GetDifferentials() { return mDifferentials; }
140
141
/// Ratio max / min average wheel speed of each differential (measured at the clutch).
142
float GetDifferentialLimitedSlipRatio() const { return mDifferentialLimitedSlipRatio; }
143
void SetDifferentialLimitedSlipRatio(float inV) { mDifferentialLimitedSlipRatio = inV; }
144
145
/// Get the average wheel speed of all driven wheels (measured at the clutch)
146
float GetWheelSpeedAtClutch() const;
147
148
/// Calculate max tire impulses by combining friction, slip, and suspension impulse. Note that the actual applied impulse may be lower (e.g. when the vehicle is stationary on a horizontal surface the actual impulse applied will be 0).
149
using TireMaxImpulseCallback = function<void(uint inWheelIndex, float &outLongitudinalImpulse, float &outLateralImpulse, float inSuspensionImpulse, float inLongitudinalFriction, float inLateralFriction, float inLongitudinalSlip, float inLateralSlip, float inDeltaTime)>;
150
const TireMaxImpulseCallback&GetTireMaxImpulseCallback() const { return mTireMaxImpulseCallback; }
151
void SetTireMaxImpulseCallback(const TireMaxImpulseCallback &inTireMaxImpulseCallback) { mTireMaxImpulseCallback = inTireMaxImpulseCallback; }
152
153
#ifdef JPH_DEBUG_RENDERER
154
/// Debug drawing of RPM meter
155
void SetRPMMeter(Vec3Arg inPosition, float inSize) { mRPMMeterPosition = inPosition; mRPMMeterSize = inSize; }
156
#endif // JPH_DEBUG_RENDERER
157
158
protected:
159
// See: VehicleController
160
virtual Wheel * ConstructWheel(const WheelSettings &inWheel) const override { JPH_ASSERT(IsKindOf(&inWheel, JPH_RTTI(WheelSettingsWV))); return new WheelWV(static_cast<const WheelSettingsWV &>(inWheel)); }
161
virtual bool AllowSleep() const override;
162
virtual void PreCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;
163
virtual void PostCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;
164
virtual bool SolveLongitudinalAndLateralConstraints(float inDeltaTime) override;
165
virtual void SaveState(StateRecorder &inStream) const override;
166
virtual void RestoreState(StateRecorder &inStream) override;
167
#ifdef JPH_DEBUG_RENDERER
168
virtual void Draw(DebugRenderer *inRenderer) const override;
169
#endif // JPH_DEBUG_RENDERER
170
171
// Control information
172
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
173
float mRightInput = 0.0f; ///< Value between -1 and 1 indicating desired steering angle
174
float mBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the brake pedal is pressed
175
float mHandBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the hand brake is pulled
176
177
// Simulation information
178
VehicleEngine mEngine; ///< Engine state of the vehicle
179
VehicleTransmission mTransmission; ///< Transmission state of the vehicle
180
Differentials mDifferentials; ///< Differential states of the vehicle
181
float mDifferentialLimitedSlipRatio; ///< Ratio max / min average wheel speed of each differential (measured at the clutch).
182
float mPreviousDeltaTime = 0.0f; ///< Delta time of the last step
183
184
// Callback that calculates the max impulse that the tire can apply to the ground
185
TireMaxImpulseCallback mTireMaxImpulseCallback =
186
[](uint, float &outLongitudinalImpulse, float &outLateralImpulse, float inSuspensionImpulse, float inLongitudinalFriction, float inLateralFriction, float, float, float)
187
{
188
outLongitudinalImpulse = inLongitudinalFriction * inSuspensionImpulse;
189
outLateralImpulse = inLateralFriction * inSuspensionImpulse;
190
};
191
192
#ifdef JPH_DEBUG_RENDERER
193
// Debug settings
194
Vec3 mRPMMeterPosition { 0, 1, 0 }; ///< Position (in local space of the body) of the RPM meter when drawing the constraint
195
float mRPMMeterSize = 0.5f; ///< Size of the RPM meter when drawing the constraint
196
#endif // JPH_DEBUG_RENDERER
197
};
198
199
JPH_NAMESPACE_END
200
201