516 lines
23 KiB
C++
516 lines
23 KiB
C++
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#include "CustomTireVehicle.h"
|
|
|
|
|
|
namespace snippetvehicle
|
|
{
|
|
|
|
template<typename TFloat>
|
|
static void setExampleSharedParams(MFTireSharedParams<TFloat>& sharedParams, const TFloat lengthScale)
|
|
{
|
|
sharedParams.r0 = TFloat(0.3135) * lengthScale; // tire radius under no load (base unit is [m])
|
|
sharedParams.v0 = TFloat(16.7) * lengthScale; // reference velocity (=60km/h) (base unit is [m/s])
|
|
sharedParams.fz0 = TFloat(4000.0) * lengthScale; // nominal load (base unit is [N])
|
|
sharedParams.pi0 = TFloat(220000.0) / lengthScale; // nominal inflation pressure (=2.2 bar) (base unit is [Pa])
|
|
|
|
sharedParams.epsilonV = TFloat(0.01) * lengthScale;
|
|
sharedParams.slipReductionLowVelocity = TFloat(7.0) * lengthScale;
|
|
sharedParams.lambdaFz0 = TFloat(1.0);
|
|
sharedParams.lambdaK_alpha = TFloat(1.0);
|
|
sharedParams.aMu = TFloat(10.0);
|
|
sharedParams.zeta0 = TFloat(1.0);
|
|
sharedParams.zeta2 = TFloat(1.0);
|
|
|
|
mfTireComputeDerivedSharedParams(sharedParams);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleLongitudinalForcePureParams(MFTireLongitudinalForcePureParams<TFloat>& longitudinalForcePureParams, const TFloat lengthScale)
|
|
{
|
|
longitudinalForcePureParams.pK1 = TFloat(21.687);
|
|
longitudinalForcePureParams.pK2 = TFloat(13.728);
|
|
longitudinalForcePureParams.pK3 = TFloat(-0.4098);
|
|
longitudinalForcePureParams.pp1 = TFloat(-0.3485);
|
|
longitudinalForcePureParams.pp2 = TFloat(0.37824);
|
|
longitudinalForcePureParams.lambdaK = TFloat(1.0);
|
|
longitudinalForcePureParams.epsilon = TFloat(1.0) * lengthScale;
|
|
//---
|
|
longitudinalForcePureParams.pC1 = TFloat(1.579);
|
|
longitudinalForcePureParams.lambdaC = TFloat(1.0);
|
|
//---
|
|
longitudinalForcePureParams.pD1 = TFloat(1.0422);
|
|
longitudinalForcePureParams.pD2 = TFloat(-0.08285);
|
|
longitudinalForcePureParams.pD3 = TFloat(0.0);
|
|
longitudinalForcePureParams.pp3 = TFloat(-0.09603);
|
|
longitudinalForcePureParams.pp4 = TFloat(0.06518);
|
|
//---
|
|
longitudinalForcePureParams.pE1 = TFloat(0.11113);
|
|
longitudinalForcePureParams.pE2 = TFloat(0.3143);
|
|
longitudinalForcePureParams.pE3 = TFloat(0.0);
|
|
longitudinalForcePureParams.pE4 = TFloat(0.001719);
|
|
longitudinalForcePureParams.lambdaE = TFloat(1.0);
|
|
//---
|
|
longitudinalForcePureParams.pH1 = TFloat(2.1615e-4);
|
|
longitudinalForcePureParams.pH2 = TFloat(0.0011598);
|
|
longitudinalForcePureParams.lambdaH = TFloat(1.0);
|
|
//---
|
|
longitudinalForcePureParams.pV1 = TFloat(2.0283e-5);
|
|
longitudinalForcePureParams.pV2 = TFloat(1.0568e-4);
|
|
longitudinalForcePureParams.lambdaV = TFloat(1.0);
|
|
longitudinalForcePureParams.zeta1 = TFloat(1.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleLongitudinalForceCombinedParams(MFTireLongitudinalForceCombinedParams<TFloat>& longitudinalForceCombinedParams)
|
|
{
|
|
longitudinalForceCombinedParams.rB1 = TFloat(13.046);
|
|
longitudinalForceCombinedParams.rB2 = TFloat(9.718);
|
|
longitudinalForceCombinedParams.rB3 = TFloat(0.0);
|
|
longitudinalForceCombinedParams.lambdaAlpha = TFloat(1.0);
|
|
//---
|
|
longitudinalForceCombinedParams.rC1 = TFloat(0.9995);
|
|
//---
|
|
longitudinalForceCombinedParams.rE1 = TFloat(-0.4403);
|
|
longitudinalForceCombinedParams.rE2 = TFloat(-0.4663);
|
|
//---
|
|
longitudinalForceCombinedParams.rH1 = TFloat(-9.968e-5);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleLateralForcePureParams(MFTireLateralForcePureParams<TFloat>& lateralForcePureParams, const TFloat lengthScale)
|
|
{
|
|
lateralForcePureParams.pK1 = TFloat(15.324); // note: original source uses ISO sign convention and thus the value was negative
|
|
lateralForcePureParams.pK2 = TFloat(1.715);
|
|
lateralForcePureParams.pK3 = TFloat(0.3695);
|
|
lateralForcePureParams.pK4 = TFloat(2.0005);
|
|
lateralForcePureParams.pK5 = TFloat(0.0);
|
|
lateralForcePureParams.pp1 = TFloat(-0.6255);
|
|
lateralForcePureParams.pp2 = TFloat(-0.06523);
|
|
lateralForcePureParams.epsilon = TFloat(1.0) * lengthScale;
|
|
lateralForcePureParams.zeta3 = TFloat(1.0);
|
|
//---
|
|
lateralForcePureParams.pC1 = TFloat(1.338);
|
|
lateralForcePureParams.lambdaC = TFloat(1.0);
|
|
//---
|
|
lateralForcePureParams.pD1 = TFloat(0.8785);
|
|
lateralForcePureParams.pD2 = TFloat(-0.06452);
|
|
lateralForcePureParams.pD3 = TFloat(0.0);
|
|
lateralForcePureParams.pp3 = TFloat(-0.16666);
|
|
lateralForcePureParams.pp4 = TFloat(0.2811);
|
|
//---
|
|
lateralForcePureParams.pE1 = TFloat(-0.8057);
|
|
lateralForcePureParams.pE2 = TFloat(-0.6046);
|
|
lateralForcePureParams.pE3 = TFloat(0.09854);
|
|
lateralForcePureParams.pE4 = TFloat(-6.697);
|
|
lateralForcePureParams.pE5 = TFloat(0.0);
|
|
lateralForcePureParams.lambdaE = TFloat(1.0);
|
|
//---
|
|
lateralForcePureParams.pH1 = TFloat(-0.001806);
|
|
lateralForcePureParams.pH2 = TFloat(0.00352);
|
|
lateralForcePureParams.pK6 = TFloat(-0.8987);
|
|
lateralForcePureParams.pK7 = TFloat(-0.23303);
|
|
lateralForcePureParams.pp5 = TFloat(0.0);
|
|
lateralForcePureParams.lambdaH = TFloat(1.0);
|
|
lateralForcePureParams.epsilonK = TFloat(10.0) * lengthScale;
|
|
lateralForcePureParams.zeta4 = TFloat(1.0);
|
|
//---
|
|
lateralForcePureParams.pV1 = TFloat(-0.00661);
|
|
lateralForcePureParams.pV2 = TFloat(0.03592);
|
|
lateralForcePureParams.pV3 = TFloat(-0.162);
|
|
lateralForcePureParams.pV4 = TFloat(-0.4864);
|
|
lateralForcePureParams.lambdaV = TFloat(1.0);
|
|
lateralForcePureParams.lambdaK_gamma = TFloat(1.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleLateralForceCombinedParams(MFTireLateralForceCombinedParams<TFloat>& lateralForceCombinedParams)
|
|
{
|
|
lateralForceCombinedParams.rB1 = TFloat(10.622);
|
|
lateralForceCombinedParams.rB2 = TFloat(7.82);
|
|
lateralForceCombinedParams.rB3 = TFloat(0.002037);
|
|
lateralForceCombinedParams.rB4 = TFloat(0.0);
|
|
lateralForceCombinedParams.lambdaKappa = TFloat(1.0);
|
|
//---
|
|
lateralForceCombinedParams.rC1 = TFloat(1.0587);
|
|
//--
|
|
lateralForceCombinedParams.rE1 = TFloat(0.3148);
|
|
lateralForceCombinedParams.rE2 = TFloat(0.004867);
|
|
//---
|
|
lateralForceCombinedParams.rH1 = TFloat(0.009472);
|
|
lateralForceCombinedParams.rH2 = TFloat(0.009754);
|
|
//---
|
|
lateralForceCombinedParams.rV1 = TFloat(0.05187);
|
|
lateralForceCombinedParams.rV2 = TFloat(4.853e-4);
|
|
lateralForceCombinedParams.rV3 = TFloat(0.0);
|
|
lateralForceCombinedParams.rV4 = TFloat(94.63);
|
|
lateralForceCombinedParams.rV5 = TFloat(1.8914);
|
|
lateralForceCombinedParams.rV6 = TFloat(23.8);
|
|
lateralForceCombinedParams.lambdaV = TFloat(1.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleAligningTorquePurePneumaticTrailParams(MFTireAligningTorquePurePneumaticTrailParams<TFloat>& aligningTorquePurePneumaticTrailParams)
|
|
{
|
|
aligningTorquePurePneumaticTrailParams.qB1 = TFloat(12.035);
|
|
aligningTorquePurePneumaticTrailParams.qB2 = TFloat(-1.33);
|
|
aligningTorquePurePneumaticTrailParams.qB3 = TFloat(0.0);
|
|
aligningTorquePurePneumaticTrailParams.qB5 = TFloat(-0.14853);
|
|
aligningTorquePurePneumaticTrailParams.qB6 = TFloat(0.0);
|
|
//---
|
|
aligningTorquePurePneumaticTrailParams.qC1 = TFloat(1.2923);
|
|
//---
|
|
aligningTorquePurePneumaticTrailParams.qD1 = TFloat(0.09068);
|
|
aligningTorquePurePneumaticTrailParams.qD2 = TFloat(-0.00565);
|
|
aligningTorquePurePneumaticTrailParams.qD3 = TFloat(0.3778);
|
|
aligningTorquePurePneumaticTrailParams.qD4 = TFloat(0.0);
|
|
aligningTorquePurePneumaticTrailParams.pp1 = TFloat(-0.4408);
|
|
aligningTorquePurePneumaticTrailParams.lambdaT = TFloat(1.0);
|
|
aligningTorquePurePneumaticTrailParams.zeta5 = TFloat(1.0);
|
|
//---
|
|
aligningTorquePurePneumaticTrailParams.qE1 = TFloat(-1.7924);
|
|
aligningTorquePurePneumaticTrailParams.qE2 = TFloat(0.8975);
|
|
aligningTorquePurePneumaticTrailParams.qE3 = TFloat(0.0);
|
|
aligningTorquePurePneumaticTrailParams.qE4 = TFloat(0.2895);
|
|
aligningTorquePurePneumaticTrailParams.qE5 = TFloat(-0.6786);
|
|
//---
|
|
aligningTorquePurePneumaticTrailParams.qH1 = TFloat(0.0014333);
|
|
aligningTorquePurePneumaticTrailParams.qH2 = TFloat(0.0024087);
|
|
aligningTorquePurePneumaticTrailParams.qH3 = TFloat(0.24973);
|
|
aligningTorquePurePneumaticTrailParams.qH4 = TFloat(-0.21205);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleAligningTorquePureResidualTorqueParams(MFTireAligningTorquePureResidualTorqueParams<TFloat>& aligningTorquePureResidualTorqueParams)
|
|
{
|
|
aligningTorquePureResidualTorqueParams.qB9 = TFloat(34.5);
|
|
aligningTorquePureResidualTorqueParams.qB10 = TFloat(0.0);
|
|
aligningTorquePureResidualTorqueParams.zeta6 = TFloat(1.0);
|
|
//---
|
|
aligningTorquePureResidualTorqueParams.zeta7 = TFloat(1.0);
|
|
//---
|
|
aligningTorquePureResidualTorqueParams.qD6 = TFloat(0.0017015);
|
|
aligningTorquePureResidualTorqueParams.qD7 = TFloat(-0.002091);
|
|
aligningTorquePureResidualTorqueParams.qD8 = TFloat(-0.1428);
|
|
aligningTorquePureResidualTorqueParams.qD9 = TFloat(0.00915);
|
|
aligningTorquePureResidualTorqueParams.qD10 = TFloat(0.0);
|
|
aligningTorquePureResidualTorqueParams.qD11 = TFloat(0.0);
|
|
aligningTorquePureResidualTorqueParams.pp2 = TFloat(0.0);
|
|
aligningTorquePureResidualTorqueParams.lambdaR = TFloat(1.0);
|
|
aligningTorquePureResidualTorqueParams.lambdaK_gamma = TFloat(1.0);
|
|
aligningTorquePureResidualTorqueParams.zeta8 = TFloat(1.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleAligningTorqueCombinedParams(MFTireAligningTorqueCombinedParams<TFloat>& aligningTorqueCombinedParams)
|
|
{
|
|
aligningTorqueCombinedParams.sS1 = TFloat(0.00918);
|
|
aligningTorqueCombinedParams.sS2 = TFloat(0.03869);
|
|
aligningTorqueCombinedParams.sS3 = TFloat(0.0);
|
|
aligningTorqueCombinedParams.sS4 = TFloat(0.0);
|
|
aligningTorqueCombinedParams.lambdaS = TFloat(1.0);
|
|
}
|
|
|
|
//For completeness but not used in this example
|
|
/*template<typename TFloat>
|
|
static void setExampleOverturningCoupleParams(MFTireOverturningCoupleParams<TFloat>& overturningCoupleParams)
|
|
{
|
|
overturningCoupleParams.qS1 = TFloat(-0.007764);
|
|
overturningCoupleParams.qS2 = TFloat(1.1915);
|
|
overturningCoupleParams.qS3 = TFloat(0.013948);
|
|
overturningCoupleParams.qS4 = TFloat(4.912);
|
|
overturningCoupleParams.qS5 = TFloat(1.02);
|
|
overturningCoupleParams.qS6 = TFloat(22.83);
|
|
overturningCoupleParams.qS7 = TFloat(0.7104);
|
|
overturningCoupleParams.qS8 = TFloat(-0.023393);
|
|
overturningCoupleParams.qS9 = TFloat(0.6581);
|
|
overturningCoupleParams.qS10 = TFloat(0.2824);
|
|
overturningCoupleParams.qS11 = TFloat(5.349);
|
|
overturningCoupleParams.ppM1 = TFloat(0.0);
|
|
overturningCoupleParams.lambdaVM = TFloat(1.0);
|
|
overturningCoupleParams.lambdaM = TFloat(1.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleRollingResistanceMomentParams(MFTireRollingResistanceMomentParams<TFloat>& rollingResistanceMomentParams)
|
|
{
|
|
rollingResistanceMomentParams.qS1 = TFloat(0.00702);
|
|
rollingResistanceMomentParams.qS2 = TFloat(0.0);
|
|
rollingResistanceMomentParams.qS3 = TFloat(0.001515);
|
|
rollingResistanceMomentParams.qS4 = TFloat(8.514e-5);
|
|
rollingResistanceMomentParams.qS5 = TFloat(0.0);
|
|
rollingResistanceMomentParams.qS6 = TFloat(0.0);
|
|
rollingResistanceMomentParams.qS7 = TFloat(0.9008);
|
|
rollingResistanceMomentParams.qS8 = TFloat(-0.4089);
|
|
rollingResistanceMomentParams.lambdaM = TFloat(1.0);
|
|
}*/
|
|
|
|
template<typename TFloat>
|
|
static void setExampleFreeRotatingRadiusParams(MFTireFreeRotatingRadiusParams<TFloat>& freeRotatingRadiusParams)
|
|
{
|
|
freeRotatingRadiusParams.qre0 = TFloat(0.9974);
|
|
freeRotatingRadiusParams.qV1 = TFloat(7.742e-4);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleVerticalStiffnessParams(const TFloat r0, const TFloat fz0,
|
|
MFTireVerticalStiffnessParams<TFloat>& verticalStiffnessParams)
|
|
{
|
|
verticalStiffnessParams.qF1 = TFloat(14.435747);
|
|
verticalStiffnessParams.qF2 = TFloat(15.4);
|
|
verticalStiffnessParams.ppF1 = TFloat(0.7098);
|
|
verticalStiffnessParams.lambdaC = TFloat(1.0);
|
|
|
|
mfTireComputeDerivedVerticalTireStiffnessParams(r0, fz0,
|
|
verticalStiffnessParams);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleNormalLoadParams(MFTireNormalLoadParams<TFloat>& normalLoadParams)
|
|
{
|
|
normalLoadParams.qV2 = TFloat(0.04667);
|
|
normalLoadParams.qFc_longitudinal = TFloat(0.0);
|
|
normalLoadParams.qFc_lateral = TFloat(0.0);
|
|
normalLoadParams.qF3 = TFloat(0.0);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleEffectiveRollingRadiusParams(MFTireEffectiveRollingRadiusParams<TFloat>& effectiveRollingRadiusParams)
|
|
{
|
|
effectiveRollingRadiusParams.Freff = TFloat(0.07394);
|
|
effectiveRollingRadiusParams.Dreff = TFloat(0.25826);
|
|
effectiveRollingRadiusParams.Breff = TFloat(8.386);
|
|
}
|
|
|
|
template<typename TFloat>
|
|
static void setExampleTireData(const TFloat lengthScale,
|
|
const bool computeAligningMoment, MFTireDataT<TFloat>& tireData)
|
|
{
|
|
setExampleSharedParams(tireData.sharedParams, lengthScale);
|
|
setExampleFreeRotatingRadiusParams(tireData.freeRotatingRadiusParams);
|
|
setExampleVerticalStiffnessParams(tireData.sharedParams.r0, tireData.sharedParams.fz0,
|
|
tireData.verticalStiffnessParams);
|
|
setExampleEffectiveRollingRadiusParams(tireData.effectiveRollingRadiusParams);
|
|
setExampleNormalLoadParams(tireData.normalLoadParams);
|
|
setExampleLongitudinalForcePureParams(tireData.longitudinalForcePureParams, lengthScale);
|
|
setExampleLongitudinalForceCombinedParams(tireData.longitudinalForceCombinedParams);
|
|
setExampleLateralForcePureParams(tireData.lateralForcePureParams, lengthScale);
|
|
setExampleLateralForceCombinedParams(tireData.lateralForceCombinedParams);
|
|
setExampleAligningTorquePurePneumaticTrailParams(tireData.aligningTorquePurePneumaticTrailParams);
|
|
setExampleAligningTorquePureResidualTorqueParams(tireData.aligningTorquePureResidualTorqueParams);
|
|
setExampleAligningTorqueCombinedParams(tireData.aligningTorqueCombinedParams);
|
|
|
|
if (computeAligningMoment)
|
|
tireData.flags |= MFTireDataFlag::eALIGNING_MOMENT;
|
|
else
|
|
tireData.flags.clear(MFTireDataFlag::eALIGNING_MOMENT);
|
|
}
|
|
|
|
//Adjust those parameters that describe lateral asymmetry and as such lead more easily to drift.
|
|
//Can be useful when using the same dataset for all wheels.
|
|
template<typename TFloat>
|
|
static void makeTireSymmetric(MFTireDataT<TFloat>& tireData)
|
|
{
|
|
tireData.longitudinalForceCombinedParams.rH1 = TFloat(0.0);
|
|
|
|
tireData.lateralForcePureParams.pE3 = TFloat(0.0);
|
|
tireData.lateralForcePureParams.pH1 = TFloat(0.0);
|
|
tireData.lateralForcePureParams.pH2 = TFloat(0.0);
|
|
tireData.lateralForcePureParams.pV1 = TFloat(0.0);
|
|
tireData.lateralForcePureParams.pV2 = TFloat(0.0);
|
|
|
|
tireData.lateralForceCombinedParams.rB3 = TFloat(0.0);
|
|
tireData.lateralForceCombinedParams.rV1 = TFloat(0.0);
|
|
tireData.lateralForceCombinedParams.rV2 = TFloat(0.0);
|
|
|
|
tireData.aligningTorquePureResidualTorqueParams.qD6 = TFloat(0.0);
|
|
tireData.aligningTorquePureResidualTorqueParams.qD7 = TFloat(0.0);
|
|
|
|
tireData.aligningTorquePurePneumaticTrailParams.qD3 = TFloat(0.0);
|
|
tireData.aligningTorquePurePneumaticTrailParams.qE4 = TFloat(0.0);
|
|
tireData.aligningTorquePurePneumaticTrailParams.qH1 = TFloat(0.0);
|
|
tireData.aligningTorquePurePneumaticTrailParams.qH2 = TFloat(0.0);
|
|
|
|
tireData.aligningTorqueCombinedParams.sS1 = TFloat(0.0);
|
|
}
|
|
|
|
bool CustomTireVehicle::initialize(PxPhysics& physics, const PxCookingParams& cookingParams, PxMaterial& defaultMaterial,
|
|
bool addPhysXBeginEndComponents)
|
|
{
|
|
typedef MFTireConfig::Float TFloat;
|
|
|
|
if (!DirectDriveVehicle::initialize(physics, cookingParams, defaultMaterial, addPhysXBeginEndComponents))
|
|
return false;
|
|
|
|
//Set the custom parameters for the vehicle tires.
|
|
const PxTolerancesScale& tolerancesScale = physics.getTolerancesScale();
|
|
const bool computeAligningMoment = false; //Not used in this snippet
|
|
|
|
const PxU32 tireDataParameterSetCount = sizeof(mCustomTireParams) / sizeof(mCustomTireParams[0]);
|
|
for (PxU32 i = 0; i < tireDataParameterSetCount; i++)
|
|
{
|
|
//Note: in this example, the same parameter values are used for all wheels.
|
|
|
|
CustomTireParams& customTireParams = mCustomTireParams[i];
|
|
|
|
setExampleTireData<TFloat>(tolerancesScale.length, computeAligningMoment,
|
|
customTireParams.mfTireData);
|
|
customTireParams.maxNormalizedLoad = 3.0f; //For the given parameter set, larger loads than this resulted in values
|
|
//going out of the expected range in the Magic Formula Tire Model
|
|
|
|
makeTireSymmetric(customTireParams.mfTireData);
|
|
}
|
|
|
|
PX_ASSERT(mBaseParams.axleDescription.getAxle(0) == 0);
|
|
PX_ASSERT(mBaseParams.axleDescription.getAxle(1) == 0);
|
|
mTireParamsList[0] = mCustomTireParams + 0;
|
|
mTireParamsList[1] = mCustomTireParams + 0;
|
|
|
|
PX_ASSERT(mBaseParams.axleDescription.getAxle(2) == 1);
|
|
PX_ASSERT(mBaseParams.axleDescription.getAxle(3) == 1);
|
|
mTireParamsList[2] = mCustomTireParams + 1;
|
|
mTireParamsList[3] = mCustomTireParams + 1;
|
|
|
|
const PxReal chassisMass = 1630.0f;
|
|
const PxVec3 chassisMoi(2589.9f, 2763.1f, 607.0f);
|
|
const PxReal massScale = chassisMass / mBaseParams.rigidBodyParams.mass;
|
|
|
|
//Adjust some non custom parameters to match more closely with the wheel the custom tire model
|
|
//parameters were taken from.
|
|
const PxU32 wheelCount = mBaseParams.axleDescription.getNbWheels();
|
|
for (PxU32 i = 0; i < wheelCount; i++)
|
|
{
|
|
PxVehicleWheelParams& wp = mBaseParams.wheelParams[i];
|
|
wp.radius = PxReal(mTireParamsList[i]->mfTireData.sharedParams.r0);
|
|
wp.halfWidth = 0.5f * 0.205f;
|
|
wp.mass = 9.3f + 7.247f;
|
|
wp.moi = 0.736f + 0.5698f;
|
|
|
|
//Map the sprung masses etc. to the new total mass
|
|
PxVehicleSuspensionForceParams& sfp = mBaseParams.suspensionForceParams[i];
|
|
sfp.sprungMass *= massScale;
|
|
sfp.stiffness *= massScale;
|
|
|
|
//Adjust damping to a range that is not ultra extreme
|
|
const PxReal dampingRatio = 0.3f;
|
|
sfp.damping = dampingRatio * 2.0f * PxSqrt(sfp.sprungMass * sfp.stiffness);
|
|
}
|
|
|
|
mBaseParams.rigidBodyParams.mass = chassisMass;
|
|
mBaseParams.rigidBodyParams.moi = chassisMoi;
|
|
|
|
//Adjust some non custom parameters given that the model should be higher fidelity.
|
|
mBaseParams.suspensionStateCalculationParams.limitSuspensionExpansionVelocity = true;
|
|
mBaseParams.suspensionStateCalculationParams.suspensionJounceCalculationType = PxVehicleSuspensionJounceCalculationType::eSWEEP;
|
|
mPhysXParams.physxRoadGeometryQueryParams.roadGeometryQueryType = PxVehiclePhysXRoadGeometryQueryType::eSWEEP;
|
|
|
|
//Recreate PhysX actor and shapes since related properties changed
|
|
mPhysXState.destroy();
|
|
mPhysXState.create(mBaseParams, mPhysXParams, physics, cookingParams, defaultMaterial);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CustomTireVehicle::destroy()
|
|
{
|
|
DirectDriveVehicle::destroy();
|
|
}
|
|
|
|
void CustomTireVehicle::initComponentSequence(const bool addPhysXBeginEndComponents)
|
|
{
|
|
//Wake up the associated PxRigidBody if it is asleep and the vehicle commands signal an
|
|
//intent to change state.
|
|
//Read from the physx actor and write the state (position, velocity etc) to the vehicle.
|
|
if(addPhysXBeginEndComponents)
|
|
mComponentSequence.add(static_cast<PxVehiclePhysXActorBeginComponent*>(this));
|
|
|
|
//Read the input commands (throttle, brake etc) and forward them as torques and angles to the wheels on each axle.
|
|
mComponentSequence.add(static_cast<PxVehicleDirectDriveCommandResponseComponent*>(this));
|
|
|
|
//Work out which wheels have a non-zero drive torque and non-zero brake torque.
|
|
//This is used to determine if any tire is to enter the "sticky" regime that will bring the
|
|
//vehicle to rest.
|
|
mComponentSequence.add(static_cast<PxVehicleDirectDriveActuationStateComponent*>(this));
|
|
|
|
//Start a substep group that can be ticked multiple times per update.
|
|
//In this example, we perform multiple updates of the road geometry queries, suspensions,
|
|
//tires and wheels. Some tire models might need small time steps to be stable and running
|
|
//the road geometry queries every substep can reduce large discontinuities (for example
|
|
//having the wheel go from one frame with no ground contact to a highly compressed suspension
|
|
//in the next frame). Running substeps on a subset of the operations is computationally
|
|
//cheaper than simulating the entire sequence.
|
|
mComponentSequenceSubstepGroupHandle = mComponentSequence.beginSubstepGroup(16); //16 to get more or less a 1kHz update frequence, assuming main update is 60Hz
|
|
|
|
//Perform a scene query against the physx scene to determine the plane and friction under each wheel.
|
|
mComponentSequence.add(static_cast<PxVehiclePhysXRoadGeometrySceneQueryComponent*>(this));
|
|
|
|
//Update the suspension compression given the plane under each wheel.
|
|
//Update the kinematic compliance from the compression state of each suspension.
|
|
//Convert suspension state to suspension force and torque.
|
|
mComponentSequence.add(static_cast<PxVehicleSuspensionComponent*>(this));
|
|
|
|
//Compute the load on the tire, the friction experienced by the tire
|
|
//and the lateral/longitudinal slip angles.
|
|
//Convert load/friction/slip to tire force and torque.
|
|
//If the vehicle is to come rest then compute the "sticky" velocity constraints to apply to the
|
|
//vehicle.
|
|
mComponentSequence.add(static_cast<CustomTireComponent*>(this));
|
|
|
|
//Apply any velocity constraints to a data buffer that will be consumed by the physx scene
|
|
//during the next physx scene update.
|
|
mComponentSequence.add(static_cast<PxVehiclePhysXConstraintComponent*>(this));
|
|
|
|
//Apply the tire force, brake force and drive force to each wheel and
|
|
//forward integrate the rotation speed of each wheel.
|
|
mComponentSequence.add(static_cast<PxVehicleDirectDrivetrainComponent*>(this));
|
|
|
|
//Apply the suspension and tire forces to the vehicle's rigid body and forward
|
|
//integrate the state of the rigid body.
|
|
mComponentSequence.add(static_cast<PxVehicleRigidBodyComponent*>(this));
|
|
|
|
//Mark the end of the substep group.
|
|
mComponentSequence.endSubstepGroup();
|
|
|
|
//Update the rotation angle of the wheel by forwarding integrating the rotational
|
|
//speed of each wheel.
|
|
//Compute the local pose of the wheel in the rigid body frame after accounting
|
|
//suspension compression and compliance.
|
|
mComponentSequence.add(static_cast<PxVehicleWheelComponent*>(this));
|
|
|
|
//Write the local poses of each wheel to the corresponding shapes on the physx actor.
|
|
//Write the momentum change applied to the vehicle's rigid body to the physx actor.
|
|
//The physx scene can now try to apply that change to the physx actor.
|
|
//The physx scene will account for collisions and constraints to be applied to the vehicle
|
|
//that occur by applying the change.
|
|
if(addPhysXBeginEndComponents)
|
|
mComponentSequence.add(static_cast<PxVehiclePhysXActorEndComponent*>(this));
|
|
}
|
|
|
|
}//namespace snippetvehicle
|