Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Vehicle/WheeledVehicleController.h
9912 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56#include <Jolt/Physics/Vehicle/VehicleConstraint.h>7#include <Jolt/Physics/Vehicle/VehicleController.h>8#include <Jolt/Physics/Vehicle/VehicleEngine.h>9#include <Jolt/Physics/Vehicle/VehicleTransmission.h>10#include <Jolt/Physics/Vehicle/VehicleDifferential.h>11#include <Jolt/Core/LinearCurve.h>1213JPH_NAMESPACE_BEGIN1415class PhysicsSystem;1617/// WheelSettings object specifically for WheeledVehicleController18class JPH_EXPORT WheelSettingsWV : public WheelSettings19{20JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheelSettingsWV)2122public:23/// Constructor24WheelSettingsWV();2526// See: WheelSettings27virtual void SaveBinaryState(StreamOut &inStream) const override;28virtual void RestoreBinaryState(StreamIn &inStream) override;2930float 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 m31float mAngularDamping = 0.2f; ///< Angular damping factor of the wheel: dw/dt = -c * w32float mMaxSteerAngle = DegreesToRadians(70.0f); ///< How much this wheel can steer (radians)33LinearCurve 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.34LinearCurve 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.35float mMaxBrakeTorque = 1500.0f; ///< How much torque (Nm) the brakes can apply to this wheel36float mMaxHandBrakeTorque = 4000.0f; ///< How much torque (Nm) the hand brake can apply to this wheel (usually only applied to the rear wheels)37};3839/// Wheel object specifically for WheeledVehicleController40class JPH_EXPORT WheelWV : public Wheel41{42public:43JPH_OVERRIDE_NEW_DELETE4445/// Constructor46explicit WheelWV(const WheelSettingsWV &inWheel);4748/// Override GetSettings and cast to the correct class49const WheelSettingsWV * GetSettings() const { return StaticCast<WheelSettingsWV>(mSettings); }5051/// Apply a torque (N m) to the wheel for a particular delta time52void ApplyTorque(float inTorque, float inDeltaTime)53{54mAngularVelocity += inTorque * inDeltaTime / GetSettings()->mInertia;55}5657/// Update the wheel rotation based on the current angular velocity58void Update(uint inWheelIndex, float inDeltaTime, const VehicleConstraint &inConstraint);5960float mLongitudinalSlip = 0.0f; ///< Velocity difference between ground and wheel relative to ground velocity61float mLateralSlip = 0.0f; ///< Angular difference (in radians) between ground and wheel relative to ground velocity62float mCombinedLongitudinalFriction = 0.0f; ///< Combined friction coefficient in longitudinal direction (combines terrain and tires)63float mCombinedLateralFriction = 0.0f; ///< Combined friction coefficient in lateral direction (combines terrain and tires)64float mBrakeImpulse = 0.0f; ///< Amount of impulse that the brakes can apply to the floor (excluding friction)65};6667/// Settings of a vehicle with regular wheels68///69/// The properties in this controller are largely based on "Car Physics for Games" by Marco Monster.70/// See: https://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html71class JPH_EXPORT WheeledVehicleControllerSettings : public VehicleControllerSettings72{73JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, WheeledVehicleControllerSettings)7475public:76// See: VehicleControllerSettings77virtual VehicleController * ConstructController(VehicleConstraint &inConstraint) const override;78virtual void SaveBinaryState(StreamOut &inStream) const override;79virtual void RestoreBinaryState(StreamIn &inStream) override;8081VehicleEngineSettings mEngine; ///< The properties of the engine82VehicleTransmissionSettings mTransmission; ///< The properties of the transmission (aka gear box)83Array<VehicleDifferentialSettings> mDifferentials; ///< List of differentials and their properties84float 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.85};8687/// Runtime controller class88class JPH_EXPORT WheeledVehicleController : public VehicleController89{90public:91JPH_OVERRIDE_NEW_DELETE9293/// Constructor94WheeledVehicleController(const WheeledVehicleControllerSettings &inSettings, VehicleConstraint &inConstraint);9596/// Typedefs97using Differentials = Array<VehicleDifferentialSettings>;9899/// Set input from driver100/// @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 pressed101/// @param inRight Value between -1 and 1 indicating desired steering angle (1 = right)102/// @param inBrake Value between 0 and 1 indicating how strong the brake pedal is pressed103/// @param inHandBrake Value between 0 and 1 indicating how strong the hand brake is pulled104void SetDriverInput(float inForward, float inRight, float inBrake, float inHandBrake) { mForwardInput = inForward; mRightInput = inRight; mBrakeInput = inBrake; mHandBrakeInput = inHandBrake; }105106/// Value between -1 and 1 for auto transmission and value between 0 and 1 indicating desired driving direction and amount the gas pedal is pressed107void SetForwardInput(float inForward) { mForwardInput = inForward; }108float GetForwardInput() const { return mForwardInput; }109110/// Value between -1 and 1 indicating desired steering angle (1 = right)111void SetRightInput(float inRight) { mRightInput = inRight; }112float GetRightInput() const { return mRightInput; }113114/// Value between 0 and 1 indicating how strong the brake pedal is pressed115void SetBrakeInput(float inBrake) { mBrakeInput = inBrake; }116float GetBrakeInput() const { return mBrakeInput; }117118/// Value between 0 and 1 indicating how strong the hand brake is pulled119void SetHandBrakeInput(float inHandBrake) { mHandBrakeInput = inHandBrake; }120float GetHandBrakeInput() const { return mHandBrakeInput; }121122/// Get current engine state123const VehicleEngine & GetEngine() const { return mEngine; }124125/// Get current engine state (writable interface, allows you to make changes to the configuration which will take effect the next time step)126VehicleEngine & GetEngine() { return mEngine; }127128/// Get current transmission state129const VehicleTransmission & GetTransmission() const { return mTransmission; }130131/// Get current transmission state (writable interface, allows you to make changes to the configuration which will take effect the next time step)132VehicleTransmission & GetTransmission() { return mTransmission; }133134/// Get the differentials this vehicle has135const Differentials & GetDifferentials() const { return mDifferentials; }136137/// Get the differentials this vehicle has (writable interface, allows you to make changes to the configuration which will take effect the next time step)138Differentials & GetDifferentials() { return mDifferentials; }139140/// Ratio max / min average wheel speed of each differential (measured at the clutch).141float GetDifferentialLimitedSlipRatio() const { return mDifferentialLimitedSlipRatio; }142void SetDifferentialLimitedSlipRatio(float inV) { mDifferentialLimitedSlipRatio = inV; }143144/// Get the average wheel speed of all driven wheels (measured at the clutch)145float GetWheelSpeedAtClutch() const;146147/// 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).148using TireMaxImpulseCallback = function<void(uint inWheelIndex, float &outLongitudinalImpulse, float &outLateralImpulse, float inSuspensionImpulse, float inLongitudinalFriction, float inLateralFriction, float inLongitudinalSlip, float inLateralSlip, float inDeltaTime)>;149const TireMaxImpulseCallback&GetTireMaxImpulseCallback() const { return mTireMaxImpulseCallback; }150void SetTireMaxImpulseCallback(const TireMaxImpulseCallback &inTireMaxImpulseCallback) { mTireMaxImpulseCallback = inTireMaxImpulseCallback; }151152#ifdef JPH_DEBUG_RENDERER153/// Debug drawing of RPM meter154void SetRPMMeter(Vec3Arg inPosition, float inSize) { mRPMMeterPosition = inPosition; mRPMMeterSize = inSize; }155#endif // JPH_DEBUG_RENDERER156157protected:158// See: VehicleController159virtual Wheel * ConstructWheel(const WheelSettings &inWheel) const override { JPH_ASSERT(IsKindOf(&inWheel, JPH_RTTI(WheelSettingsWV))); return new WheelWV(static_cast<const WheelSettingsWV &>(inWheel)); }160virtual bool AllowSleep() const override;161virtual void PreCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;162virtual void PostCollide(float inDeltaTime, PhysicsSystem &inPhysicsSystem) override;163virtual bool SolveLongitudinalAndLateralConstraints(float inDeltaTime) override;164virtual void SaveState(StateRecorder &inStream) const override;165virtual void RestoreState(StateRecorder &inStream) override;166#ifdef JPH_DEBUG_RENDERER167virtual void Draw(DebugRenderer *inRenderer) const override;168#endif // JPH_DEBUG_RENDERER169170// Control information171float 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 pressed172float mRightInput = 0.0f; ///< Value between -1 and 1 indicating desired steering angle173float mBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the brake pedal is pressed174float mHandBrakeInput = 0.0f; ///< Value between 0 and 1 indicating how strong the hand brake is pulled175176// Simulation information177VehicleEngine mEngine; ///< Engine state of the vehicle178VehicleTransmission mTransmission; ///< Transmission state of the vehicle179Differentials mDifferentials; ///< Differential states of the vehicle180float mDifferentialLimitedSlipRatio; ///< Ratio max / min average wheel speed of each differential (measured at the clutch).181float mPreviousDeltaTime = 0.0f; ///< Delta time of the last step182183// Callback that calculates the max impulse that the tire can apply to the ground184TireMaxImpulseCallback mTireMaxImpulseCallback =185[](uint, float &outLongitudinalImpulse, float &outLateralImpulse, float inSuspensionImpulse, float inLongitudinalFriction, float inLateralFriction, float, float, float)186{187outLongitudinalImpulse = inLongitudinalFriction * inSuspensionImpulse;188outLateralImpulse = inLateralFriction * inSuspensionImpulse;189};190191#ifdef JPH_DEBUG_RENDERER192// Debug settings193Vec3 mRPMMeterPosition { 0, 1, 0 }; ///< Position (in local space of the body) of the RPM meter when drawing the constraint194float mRPMMeterSize = 0.5f; ///< Size of the RPM meter when drawing the constraint195#endif // JPH_DEBUG_RENDERER196};197198JPH_NAMESPACE_END199200201