Files
XCEngine/engine/third_party/physx/snippets/snippetvehiclecommon/serialization/BaseSerialization.cpp

914 lines
29 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 "BaseSerialization.h"
#include "SerializationCommon.h"
#include <fstream>
#include <sstream>
namespace snippetvehicle
{
bool readAxleDescription(const rapidjson::Document& config, PxVehicleAxleDescription& axleDesc)
{
if (!config.HasMember("AxleDescription"))
return false;
const PxU32 nbAxles = config["AxleDescription"].Size();
if (nbAxles > PxVehicleLimits::eMAX_NB_AXLES)
return false;
axleDesc.setToDefault();
//Read each axle in turn.
for (PxU32 i = 0; i < nbAxles; i++)
{
const rapidjson::Value& axle = config["AxleDescription"][i];
if (!axle.HasMember("WheelIds"))
return false;
const rapidjson::Value& wheelIds = axle["WheelIds"];
const PxU32 nbWheelIds = wheelIds.Size();
if(nbWheelIds > PxVehicleLimits::eMAX_NB_WHEELS)
return false;
PxU32 axleWheelIds[PxVehicleLimits::eMAX_NB_WHEELS];
for (PxU32 j = 0; j < nbWheelIds; j++)
{
axleWheelIds[j]= wheelIds[j].GetInt();
}
axleDesc.addAxle(nbWheelIds, axleWheelIds);
}
return true;
}
bool writeAxleDescription(const PxVehicleAxleDescription& axleDesc, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("AxleDescription");
writer.StartArray();
for(PxU32 i = 0; i < axleDesc.getNbAxles(); i++)
{
writer.StartObject();
writer.Key("WheelIds");
writer.StartArray();
for(PxU32 j = 0; j < axleDesc.getNbWheelsOnAxle(i); j++)
{
writer.Int(axleDesc.getWheelOnAxle(j, i));
}
writer.EndArray();
writer.EndObject();
}
writer.EndArray();
return true;
}
bool readFrame(const rapidjson::Document& config, PxVehicleFrame& frame)
{
if (!config.HasMember("Frame"))
return false;
if (!config["Frame"].HasMember("LngAxis"))
return false;
if (!config["Frame"].HasMember("LatAxis"))
return false;
if (!config["Frame"].HasMember("VrtAxis"))
return false;
const PxU32 lngAxis = config["Frame"]["LngAxis"].GetInt();
const PxU32 latAxis = config["Frame"]["LatAxis"].GetInt();
const PxU32 vrtAxis = config["Frame"]["VrtAxis"].GetInt();
if ((lngAxis == latAxis) || (lngAxis == vrtAxis) || (latAxis == vrtAxis))
{
return false;
}
frame.lngAxis = static_cast<PxVehicleAxes::Enum>(lngAxis);
frame.latAxis = static_cast<PxVehicleAxes::Enum>(latAxis);
frame.vrtAxis = static_cast<PxVehicleAxes::Enum>(vrtAxis);
return true;
}
bool writeFrame(const PxVehicleFrame& frame, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("Frame");
writer.StartObject();
writer.Key("LngAxis");
writer.Int(static_cast<PxU32>(frame.lngAxis));
writer.Key("LatAxis");
writer.Int(static_cast<PxU32>(frame.latAxis));
writer.Key("VrtAxis");
writer.Int(static_cast<PxU32>(frame.vrtAxis));
writer.EndObject();
return true;
}
bool readScale(const rapidjson::Document& config, PxVehicleScale& scale)
{
if (!config.HasMember("Scale"))
return false;
if (!config["Scale"].HasMember("Scale"))
return false;
scale.scale = static_cast<PxReal>(config["Scale"]["Scale"].GetDouble());
return true;
}
bool writeScale(const PxVehicleScale& scale, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("Scale");
writer.StartObject();
writer.Key("Scale");
writer.Double(static_cast<double>(scale.scale));
writer.EndObject();
return true;
}
bool readBrakeResponseParams
(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleBrakeCommandResponseParams& brakeResponseParams)
{
if (!config.HasMember("BrakeCommandResponseParams"))
return false;
if (!readCommandResponseParams(config["BrakeCommandResponseParams"], axleDesc, brakeResponseParams))
return false;
return true;
}
bool writeBrakeResponseParams
(const PxVehicleBrakeCommandResponseParams& brakeResponseParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("BrakeCommandResponseParams");
writer.StartObject();
writeCommandResponseParams(brakeResponseParams, axleDesc, writer);
writer.EndObject();
return true;
}
bool readHandbrakeResponseParams
(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleBrakeCommandResponseParams& handbrakeResponseParams)
{
if (!config.HasMember("HandbrakeCommandResponseParams"))
return false;
if (!readCommandResponseParams(config["HandbrakeCommandResponseParams"], axleDesc, handbrakeResponseParams))
return false;
return true;
}
bool writeHandbrakeResponseParams
(const PxVehicleBrakeCommandResponseParams& handrakeResponseParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("HandbrakeCommandResponseParams");
writer.StartObject();
writeCommandResponseParams(handrakeResponseParams, axleDesc, writer);
writer.EndObject();
return true;
}
bool readSteerResponseParams
(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleSteerCommandResponseParams& steerResponseParams)
{
if (!config.HasMember("SteerCommandResponseParams"))
return false;
if (!readCommandResponseParams(config["SteerCommandResponseParams"], axleDesc, steerResponseParams))
return false;
return true;
}
bool writeSteerResponseParams
(const PxVehicleSteerCommandResponseParams& steerResponseParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("SteerCommandResponseParams");
writer.StartObject();
writeCommandResponseParams(steerResponseParams, axleDesc, writer);
writer.EndObject();
return true;
}
bool readAckermannParams(const rapidjson::Document& config, PxVehicleAckermannParams& ackermannParams)
{
if (!config.HasMember("AckermannParams"))
return false;
const rapidjson::Value& corrections = config["AckermannParams"];
if (!corrections.HasMember("WheelBase"))
return false;
if (!corrections.HasMember("TrackWidth"))
return false;
if (!corrections.HasMember("Strength"))
return false;
ackermannParams.wheelBase = static_cast<PxReal>(corrections["WheelBase"].GetDouble());
ackermannParams.trackWidth = static_cast<PxReal>(corrections["TrackWidth"].GetDouble());
ackermannParams.strength = static_cast<PxReal>(corrections["Strength"].GetDouble());
if (!corrections.HasMember("WheelIds"))
return false;
const rapidjson::Value& wheelIds = corrections["WheelIds"];
const PxU32 nbWheelIds = wheelIds.Size();
if (nbWheelIds != 2)
return false;
for (PxU32 j = 0; j < 2; j++)
{
ackermannParams.wheelIds[j] = wheelIds[j].GetInt();
}
return true;
}
bool writeAckermannParams(const PxVehicleAckermannParams& ackermannParams, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("AckermannParams");
writer.StartObject();
writer.Key("WheelIds");
writer.StartArray();
writer.Int(ackermannParams.wheelIds[0]);
writer.Int(ackermannParams.wheelIds[1]);
writer.EndArray();
writer.Key("WheelBase");
writer.Double(static_cast<double>(ackermannParams.wheelBase));
writer.Key("TrackWidth");
writer.Double(static_cast<double>(ackermannParams.trackWidth));
writer.Key("Strength");
writer.Double(static_cast<double>(ackermannParams.strength));
writer.EndObject();
return true;
}
bool readRigidBodyParams
(const rapidjson::Document& config, PxVehicleRigidBodyParams& rigidBodyParams)
{
if (!config.HasMember("RigidBodyParams"))
return false;
if (!config["RigidBodyParams"].HasMember("Mass"))
return false;
if (!config["RigidBodyParams"].HasMember("MOI"))
return false;
rigidBodyParams.mass = static_cast<PxReal>(config["RigidBodyParams"]["Mass"].GetDouble());
if (!readVec3(config["RigidBodyParams"]["MOI"], rigidBodyParams.moi))
return false;
return true;
}
bool writeRigidBodyParams
(const PxVehicleRigidBodyParams& rigidBodyParams, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("RigidBodyParams");
writer.StartObject();
writer.Key("Mass");
writer.Double(static_cast<double>(rigidBodyParams.mass));
writer.Key("MOI");
writeVec3(rigidBodyParams.moi, writer);
writer.EndObject();
return true;
}
bool readSuspensionParams(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc, PxVehicleSuspensionParams* suspParams)
{
if (!config.HasMember("SuspensionParams"))
return false;
const rapidjson::Value& suspensions = config["SuspensionParams"];
const PxU32 nbSuspensions = suspensions.Size();
if (nbSuspensions != axleDesc.getNbWheels())
return false;
for (PxU32 i = 0; i < nbSuspensions; i++)
{
if(!suspensions[i].HasMember("WheelId"))
return false;
if (!suspensions[i].HasMember("SuspensionAttachment"))
return false;
if (!suspensions[i].HasMember("SuspensionTravelDir"))
return false;
if (!suspensions[i].HasMember("SuspensionTravelDist"))
return false;
if (!suspensions[i].HasMember("WheelAttachment"))
return false;
const PxU32 wheelId = suspensions[i]["WheelId"].GetInt();
PxVehicleSuspensionParams& sp = suspParams[wheelId];
if (!readTransform(suspensions[i]["SuspensionAttachment"], sp.suspensionAttachment))
return false;
if (!readVec3(suspensions[i]["SuspensionTravelDir"], sp.suspensionTravelDir))
return false;
sp.suspensionTravelDist = static_cast<PxReal>(suspensions[i]["SuspensionTravelDist"].GetDouble());
if (!readTransform(suspensions[i]["WheelAttachment"], sp.wheelAttachment))
return false;
}
return true;
}
bool writeSuspensionParams(const PxVehicleSuspensionParams* suspParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("SuspensionParams");
writer.StartArray();
for(PxU32 i = 0; i < axleDesc.nbWheels; i++)
{
writer.StartObject();
writer.Key("WheelId");
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
writer.Int(wheelId);
writer.Key("SuspensionAttachment");
writeTransform(suspParams[wheelId].suspensionAttachment, writer);
writer.Key("SuspensionTravelDir");
writeVec3(suspParams[wheelId].suspensionTravelDir, writer);
writer.Key("SuspensionTravelDist");
writer.Double(static_cast<double>(suspParams[wheelId].suspensionTravelDist));
writer.Key("WheelAttachment");
writeTransform(suspParams[wheelId].wheelAttachment, writer);
writer.EndObject();
}
writer.EndArray();
return true;
}
static const char* kLimitSuspensionExpansionVelocity = "LimitSuspensionExpansionVelocity";
bool readSuspensionStateCalculationParams(const rapidjson::Document& config, PxVehicleSuspensionStateCalculationParams& suspParams)
{
if (!config.HasMember("SuspensionStateCalculationParams"))
return false;
const rapidjson::Value& suspCalcParams = config["SuspensionStateCalculationParams"];
if (!suspCalcParams.HasMember("JounceCalculationType"))
return false;
if (!suspCalcParams.HasMember(kLimitSuspensionExpansionVelocity))
return false;
suspParams.suspensionJounceCalculationType = static_cast<PxVehicleSuspensionJounceCalculationType::Enum>(suspCalcParams["JounceCalculationType"].GetInt());
suspParams.limitSuspensionExpansionVelocity = suspCalcParams[kLimitSuspensionExpansionVelocity].GetBool();
return true;
}
bool writeSuspensionStateCalculationParams
(const PxVehicleSuspensionStateCalculationParams& suspParams,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("SuspensionStateCalculationParams");
writer.StartObject();
writer.Key("JounceCalculationType");
writer.Int(static_cast<PxU32>(suspParams.suspensionJounceCalculationType));
writer.Key(kLimitSuspensionExpansionVelocity);
writer.Bool(suspParams.limitSuspensionExpansionVelocity);
writer.EndObject();
return true;
}
bool readSuspensionComplianceParams(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc, PxVehicleSuspensionComplianceParams* suspCompParams)
{
if (!config.HasMember("SuspensionComplianceParams"))
return false;
const rapidjson::Value& suspensions = config["SuspensionComplianceParams"];
const PxU32 nbSuspensions = suspensions.Size();
if (nbSuspensions != axleDesc.getNbWheels())
return false;
for (PxU32 i = 0; i < nbSuspensions; i++)
{
if (!suspensions[i].HasMember("WheelId"))
return false;
if (!suspensions[i].HasMember("WheelToeAngle"))
return false;
if (!suspensions[i].HasMember("WheelCamberAngle"))
return false;
if (!suspensions[i].HasMember("SuspForceAppPoint"))
return false;
if (!suspensions[i].HasMember("SuspForceAppPoint"))
return false;
const PxU32 wheelId = suspensions[i]["WheelId"].GetInt();
if (!readFloatLookupTable(suspensions[i]["WheelToeAngle"], suspCompParams[wheelId].wheelToeAngle))
return false;
if (!readFloatLookupTable(suspensions[i]["WheelCamberAngle"], suspCompParams[wheelId].wheelCamberAngle))
return false;
if (!readVec3LookupTable(suspensions[i]["SuspForceAppPoint"], suspCompParams[wheelId].suspForceAppPoint))
return false;
if (!readVec3LookupTable(suspensions[i]["TireForceAppPoint"], suspCompParams[wheelId].tireForceAppPoint))
return false;
}
return true;
}
bool writeSuspensionComplianceParams
(const PxVehicleSuspensionComplianceParams* suspParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("SuspensionComplianceParams");
writer.StartArray();
for (PxU32 i = 0; i < axleDesc.nbWheels; i++)
{
writer.StartObject();
writer.Key("WheelId");
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
writer.Int(wheelId);
writer.Key("WheelToeAngle");
writeFloatLookupTable(suspParams[wheelId].wheelToeAngle, writer);
writer.Key("WheelCamberAngle");
writeFloatLookupTable(suspParams[wheelId].wheelCamberAngle, writer);
writer.Key("SuspForceAppPoint");
writeVec3LookupTable(suspParams[wheelId].suspForceAppPoint, writer);
writer.Key("TireForceAppPoint");
writeVec3LookupTable(suspParams[wheelId].tireForceAppPoint, writer);
writer.EndObject();
}
writer.EndArray();
return true;
}
bool readSuspensionForceParams(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleSuspensionForceParams* suspParams)
{
if (!config.HasMember("SuspensionForceParams"))
return false;
const rapidjson::Value& suspensions = config["SuspensionForceParams"];
const PxU32 nbSuspensions = suspensions.Size();
if (nbSuspensions != axleDesc.getNbWheels())
return false;
for (PxU32 i = 0; i < nbSuspensions; i++)
{
if (!suspensions[i].HasMember("WheelId"))
return false;
if (!suspensions[i].HasMember("Damping"))
return false;
if (!suspensions[i].HasMember("Stiffness"))
return false;
if (!suspensions[i].HasMember("SprungMass"))
return false;
const PxU32 wheelId = suspensions[i]["WheelId"].GetInt();
suspParams[wheelId].damping = static_cast<PxReal>(suspensions[i]["Damping"].GetDouble());
suspParams[wheelId].stiffness = static_cast<PxReal>(suspensions[i]["Stiffness"].GetDouble());
suspParams[wheelId].sprungMass = static_cast<PxReal>(suspensions[i]["SprungMass"].GetDouble());
}
return true;
}
bool writeSuspensionForceParams
(const PxVehicleSuspensionForceParams* suspParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("SuspensionForceParams");
writer.StartArray();
for (PxU32 i = 0; i < axleDesc.nbWheels; i++)
{
writer.StartObject();
writer.Key("WheelId");
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
writer.Int(wheelId);
writer.Key("Damping");
writer.Double(double(suspParams[wheelId].damping));
writer.Key("Stiffness");
writer.Double(double(suspParams[wheelId].stiffness));
writer.Key("SprungMass");
writer.Double(double(suspParams[wheelId].sprungMass));
writer.EndObject();
}
writer.EndArray();
return true;
}
bool readTireForceParams
(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleTireForceParams* tireParams)
{
if (!config.HasMember("TireForceParams"))
return false;
const rapidjson::Value& tires = config["TireForceParams"];
const PxU32 nbTires = tires.Size();
if (nbTires != axleDesc.getNbWheels())
return false;
for (PxU32 i = 0; i < nbTires; i++)
{
if (!tires[i].HasMember("WheelId"))
return false;
if (!tires[i].HasMember("LongitudinalStiffness"))
return false;
if (!tires[i].HasMember("LateralStiffnessX"))
return false;
if (!tires[i].HasMember("LateralStiffnessY"))
return false;
if (!tires[i].HasMember("CamberStiffness"))
return false;
if (!tires[i].HasMember("RestLoad"))
return false;
if (!tires[i].HasMember("FrictionVsSlip"))
return false;
if (!tires[i].HasMember("TireLoadFilter"))
return false;
const PxU32 wheelId = tires[i]["WheelId"].GetInt();
tireParams[wheelId].longStiff = static_cast<PxReal>(tires[i]["LongitudinalStiffness"].GetDouble());
tireParams[wheelId].latStiffX = static_cast<PxReal>(tires[i]["LateralStiffnessX"].GetDouble());
tireParams[wheelId].latStiffY = static_cast<PxReal>(tires[i]["LateralStiffnessY"].GetDouble());
tireParams[wheelId].camberStiff = static_cast<PxReal>(tires[i]["CamberStiffness"].GetDouble());
tireParams[wheelId].restLoad = static_cast<PxReal>(tires[i]["RestLoad"].GetDouble());
const rapidjson::Value& frictionVsSlip = tires[i]["FrictionVsSlip"];
if (frictionVsSlip.Size() != 3)
return false;
for (PxU32 j = 0; j < 3; j++)
{
const rapidjson::Value& element = tires[i]["FrictionVsSlip"][j];
if (element.Size() != 2)
return false;
tireParams[wheelId].frictionVsSlip[j][0] = static_cast<PxReal>(element[0].GetDouble());
tireParams[wheelId].frictionVsSlip[j][1] = static_cast<PxReal>(element[1].GetDouble());
}
const rapidjson::Value& tireLoadFilter = tires[i]["TireLoadFilter"];
if (tireLoadFilter.Size() != 2)
return false;
for (PxU32 j = 0; j < 2; j++)
{
const rapidjson::Value& element = tires[i]["TireLoadFilter"][j];
if (element.Size() != 2)
return false;
tireParams[wheelId].loadFilter[j][0] = static_cast<PxReal>(element[0].GetDouble());
tireParams[wheelId].loadFilter[j][1] = static_cast<PxReal>(element[1].GetDouble());
}
}
return true;
}
bool writeTireForceParams
(const PxVehicleTireForceParams* tireParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("TireForceParams");
writer.StartArray();
for (PxU32 i = 0; i < axleDesc.nbWheels; i++)
{
writer.StartObject();
writer.Key("WheelId");
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
writer.Int(wheelId);
writer.Key("LongitudinalStiffness");
writer.Double(static_cast<double>(tireParams[wheelId].longStiff));
writer.Key("LateralStiffnessX");
writer.Double(static_cast<double>(tireParams[wheelId].latStiffX));
writer.Key("LateralStiffnessY");
writer.Double(static_cast<double>(tireParams[wheelId].latStiffY));
writer.Key("CamberStiffness");
writer.Double(static_cast<double>(tireParams[wheelId].camberStiff));
writer.Key("RestLoad");
writer.Double(static_cast<double>(tireParams[wheelId].restLoad));
writer.Key("FrictionVsSlip");
writer.StartArray();
for(PxU32 k = 0; k < 3; k++)
{
writer.StartArray();
writer.Double(static_cast<double>(tireParams[wheelId].frictionVsSlip[k][0]));
writer.Double(static_cast<double>(tireParams[wheelId].frictionVsSlip[k][1]));
writer.EndArray();
}
writer.EndArray();
writer.Key("TireLoadFilter");
writer.StartArray();
for (PxU32 k = 0; k < 2; k++)
{
writer.StartArray();
writer.Double(static_cast<double>(tireParams[wheelId].loadFilter[k][0]));
writer.Double(static_cast<double>(tireParams[wheelId].loadFilter[k][1]));
writer.EndArray();
}
writer.EndArray();
writer.EndObject();
}
writer.EndArray();
return true;
}
bool readWheelParams
(const rapidjson::Document& config, const PxVehicleAxleDescription& axleDesc,
PxVehicleWheelParams* wheelParams)
{
if (!config.HasMember("WheelParams"))
return false;
const rapidjson::Value& wheels = config["WheelParams"];
const PxU32 nbWheels = wheels.Size();
if (nbWheels != axleDesc.getNbWheels())
return false;
for (PxU32 i = 0; i < nbWheels; i++)
{
if (!wheels[i].HasMember("WheelId"))
return false;
if (!wheels[i].HasMember("HalfWidth"))
return false;
if (!wheels[i].HasMember("Radius"))
return false;
if (!wheels[i].HasMember("Mass"))
return false;
if (!wheels[i].HasMember("MOI"))
return false;
if (!wheels[i].HasMember("DampingRate"))
return false;
const PxU32 wheelId = wheels[i]["WheelId"].GetInt();
wheelParams[wheelId].halfWidth = static_cast<PxReal>(wheels[i]["HalfWidth"].GetDouble());
wheelParams[wheelId].radius = static_cast<PxReal>(wheels[i]["Radius"].GetDouble());
wheelParams[wheelId].mass = static_cast<PxReal>(wheels[i]["Mass"].GetDouble());
wheelParams[wheelId].moi = static_cast<PxReal>(wheels[i]["MOI"].GetDouble());
wheelParams[wheelId].dampingRate = static_cast<PxReal>(wheels[i]["DampingRate"].GetDouble());
}
return true;
}
bool writeWheelParams
(const PxVehicleWheelParams* wheelParams, const PxVehicleAxleDescription& axleDesc,
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
{
writer.Key("WheelParams");
writer.StartArray();
for (PxU32 i = 0; i < axleDesc.nbWheels; i++)
{
writer.StartObject();
writer.Key("WheelId");
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
writer.Int(wheelId);
writer.Key("HalfWidth");
writer.Double(static_cast<double>(wheelParams[wheelId].halfWidth));
writer.Key("Radius");
writer.Double(static_cast<double>(wheelParams[wheelId].radius));
writer.Key("Mass");
writer.Double(static_cast<double>(wheelParams[wheelId].mass));
writer.Key("MOI");
writer.Double(static_cast<double>(wheelParams[wheelId].moi));
writer.Key("DampingRate");
writer.Double(static_cast<double>(wheelParams[wheelId].dampingRate));
writer.EndObject();
}
writer.EndArray();
return true;
}
bool readBaseParamsFromJsonFile(const char* directory, const char* filename,
BaseVehicleParams& baseParams)
{
rapidjson::Document config;
if (!openDocument(directory, filename, config))
return false;
//////////////////////////////
//Read the high level params
//////////////////////////////
PxMemSet(&baseParams.axleDescription, 0xff, sizeof(baseParams.axleDescription));
if (!readAxleDescription(config, baseParams.axleDescription))
return false;
PxMemSet(&baseParams.frame, 0xff, sizeof(baseParams.frame));
if (!readFrame(config, baseParams.frame))
return false;
PxMemSet(&baseParams.scale, 0xff, sizeof(baseParams.scale));
if (!readScale(config, baseParams.scale))
return false;
//////////////////////////////
//Read the rigid body params
/////////////////////////////
PxMemSet(&baseParams.rigidBodyParams, 0xff, sizeof(baseParams.rigidBodyParams));
if (!readRigidBodyParams(config, baseParams.rigidBodyParams))
return false;
//////////////////////////////
//Read the suspension state calculation params.
//////////////////////////////
PxMemSet(&baseParams.suspensionStateCalculationParams, 0xff, sizeof(baseParams.suspensionStateCalculationParams));
if (!readSuspensionStateCalculationParams(config, baseParams.suspensionStateCalculationParams))
return false;
///////////////////////////////
//Read the command responses
///////////////////////////////
PxMemSet(&baseParams.brakeResponseParams[0], 0xff, sizeof(baseParams.brakeResponseParams[0]));
if (!readBrakeResponseParams(config, baseParams.axleDescription, baseParams.brakeResponseParams[0]))
return false;
PxMemSet(&baseParams.brakeResponseParams[1], 0xff, sizeof(baseParams.brakeResponseParams[1]));
if (!readHandbrakeResponseParams(config, baseParams.axleDescription, baseParams.brakeResponseParams[1]))
return false;
PxMemSet(&baseParams.steerResponseParams, 0xff, sizeof(baseParams.steerResponseParams));
if (!readSteerResponseParams(config, baseParams.axleDescription, baseParams.steerResponseParams))
return false;
PxMemSet(&baseParams.ackermannParams, 0xff, sizeof(baseParams.ackermannParams));
if (!readAckermannParams(config, baseParams.ackermannParams[0]))
return false;
///////////////////////////////////
//Read the suspension params
///////////////////////////////////
PxMemSet(baseParams.suspensionParams, 0xff, sizeof(baseParams.suspensionParams));
if (!readSuspensionParams(config, baseParams.axleDescription, baseParams.suspensionParams))
return false;
PxMemSet(baseParams.suspensionComplianceParams, 0x00, sizeof(baseParams.suspensionComplianceParams));
if (!readSuspensionComplianceParams(config, baseParams.axleDescription, baseParams.suspensionComplianceParams))
return false;
PxMemSet(baseParams.suspensionForceParams, 0xff, sizeof(baseParams.suspensionForceParams));
if (!readSuspensionForceParams(config, baseParams.axleDescription, baseParams.suspensionForceParams))
return false;
///////////////////////////////////
//Read the tire params
///////////////////////////////////
PxMemSet(baseParams.tireForceParams, 0xff, sizeof(baseParams.tireForceParams));
if (!readTireForceParams(config, baseParams.axleDescription, baseParams.tireForceParams))
return false;
//////////////////////////
//Read the wheel params
//////////////////////////
PxMemSet(baseParams.wheelParams, 0xff, sizeof(baseParams.wheelParams));
if (!readWheelParams(config, baseParams.axleDescription, baseParams.wheelParams))
return false;
return true;
}
bool writeBaseParamsToJsonFile(const char* directory, const char* filename, const BaseVehicleParams& baseParams)
{
rapidjson::StringBuffer strbuf;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strbuf);
writer.StartObject();
//////////////////////////////
//Write the high level params
//////////////////////////////
writeAxleDescription(baseParams.axleDescription, writer);
writeFrame(baseParams.frame, writer);
writeScale(baseParams.scale, writer);
//////////////////////////////
//Write the rigid body params
/////////////////////////////
writeRigidBodyParams(baseParams.rigidBodyParams, writer);
//////////////////////////////
//Write the suspension state calculation params
//////////////////////////////
writeSuspensionStateCalculationParams(baseParams.suspensionStateCalculationParams, writer);
///////////////////////////////
//Write the command responses
///////////////////////////////
writeBrakeResponseParams(baseParams.brakeResponseParams[0], baseParams.axleDescription, writer);
writeHandbrakeResponseParams(baseParams.brakeResponseParams[1], baseParams.axleDescription, writer);
writeSteerResponseParams(baseParams.steerResponseParams, baseParams.axleDescription, writer);
writeAckermannParams(baseParams.ackermannParams[0], writer);
///////////////////////////////////
//Write the suspension params
///////////////////////////////////
writeSuspensionParams(baseParams.suspensionParams, baseParams.axleDescription, writer);
writeSuspensionComplianceParams(baseParams.suspensionComplianceParams, baseParams.axleDescription, writer);
writeSuspensionForceParams(baseParams.suspensionForceParams, baseParams.axleDescription, writer);
///////////////////////////////////
//Write the tire params
///////////////////////////////////
writeTireForceParams(baseParams.tireForceParams, baseParams.axleDescription, writer);
//////////////////////////
//Write the wheel params
//////////////////////////
writeWheelParams(baseParams.wheelParams, baseParams.axleDescription, writer);
writer.EndObject();
std::ofstream myfile;
myfile.open(std::string(directory) + "/" + filename);
myfile << strbuf.GetString() << std::endl;
myfile.close();
return true;
}
}//namespace snippetvehicle