// 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 "EngineDrivetrainSerialization.h" #include "SerializationCommon.h" #include #include namespace snippetvehicle { bool readAutoboxParams(const rapidjson::Document& config, PxVehicleAutoboxParams& autoboxParams) { if(!config.HasMember("AutoboxParams")) return false; if(!config["AutoboxParams"].HasMember("UpRatios")) return false; if (!config["AutoboxParams"].HasMember("DownRatios")) return false; if (!config["AutoboxParams"].HasMember("Latency")) return false; const rapidjson::Value& upRatios = config["AutoboxParams"]["UpRatios"]; for(PxU32 i = 0; i < upRatios.Size(); i++) { autoboxParams.upRatios[i] = static_cast(upRatios[i].GetDouble()); } const rapidjson::Value& downRatios = config["AutoboxParams"]["DownRatios"]; for (PxU32 i = 0; i < downRatios.Size(); i++) { autoboxParams.downRatios[i] = static_cast(downRatios[i].GetDouble()); } autoboxParams.latency = static_cast(config["AutoboxParams"]["Latency"].GetDouble()); return true; } bool writeAutoboxParams(const PxVehicleAutoboxParams& autoboxParams, rapidjson::PrettyWriter& writer) { writer.Key("AutoboxParams"); writer.StartObject(); writer.Key("UpRatios"); writer.StartArray(); for(PxU32 i = 0; i < PxVehicleGearboxParams::eMAX_NB_GEARS; i++) { writer.Double(static_cast(autoboxParams.upRatios[i])); } writer.EndArray(); writer.Key("DownRatios"); writer.StartArray(); for (PxU32 i = 0; i < PxVehicleGearboxParams::eMAX_NB_GEARS; i++) { writer.Double(static_cast(autoboxParams.downRatios[i])); } writer.EndArray(); writer.Key("Latency"); writer.Double(static_cast(autoboxParams.latency)); writer.EndObject(); return true; } bool readClutchCommandResponseParams(const rapidjson::Document& config, PxVehicleClutchCommandResponseParams& clutchCommandResponseParams) { if(!config.HasMember("ClutchCommandResponseParams")) return false; if(!config["ClutchCommandResponseParams"].HasMember("MaxResponse")) return false; clutchCommandResponseParams.maxResponse = static_cast(config["ClutchCommandResponseParams"]["MaxResponse"].GetDouble()); return true; } bool writeClutchCommandResponseParams(const PxVehicleClutchCommandResponseParams& clutchCommandResponseParams, rapidjson::PrettyWriter& writer) { writer.Key("ClutchCommandResponseParams"); writer.StartObject(); writer.Key("MaxResponse"); writer.Double(static_cast(clutchCommandResponseParams.maxResponse)); writer.EndObject(); return true; } bool readEngineParams(const rapidjson::Document& config, PxVehicleEngineParams& engineParams) { if(!config.HasMember("EngineParams")) return false; if(!config["EngineParams"].HasMember("TorqueCurve")) return false; if (!config["EngineParams"].HasMember("MOI")) return false; if (!config["EngineParams"].HasMember("PeakTorque")) return false; if (!config["EngineParams"].HasMember("IdleOmega")) return false; if (!config["EngineParams"].HasMember("MaxOmega")) return false; if (!config["EngineParams"].HasMember("DampingRateFullThrottle")) return false; if (!config["EngineParams"].HasMember("DampingRateZeroThrottleClutchEngaged")) return false; if (!config["EngineParams"].HasMember("DampingRateZeroThrottleClutchDisengaged")) return false; if(!readFloatLookupTable(config["EngineParams"]["TorqueCurve"], engineParams.torqueCurve)) return false; engineParams.moi = static_cast(config["EngineParams"]["MOI"].GetDouble()); engineParams.peakTorque = static_cast(config["EngineParams"]["PeakTorque"].GetDouble()); engineParams.idleOmega = static_cast(config["EngineParams"]["IdleOmega"].GetDouble()); engineParams.maxOmega = static_cast(config["EngineParams"]["MaxOmega"].GetDouble()); engineParams.dampingRateFullThrottle = static_cast(config["EngineParams"]["DampingRateFullThrottle"].GetDouble()); engineParams.dampingRateZeroThrottleClutchEngaged = static_cast(config["EngineParams"]["DampingRateZeroThrottleClutchEngaged"].GetDouble()); engineParams.dampingRateZeroThrottleClutchDisengaged = static_cast(config["EngineParams"]["DampingRateZeroThrottleClutchDisengaged"].GetDouble()); return true; } bool writeEngineParams(const PxVehicleEngineParams& engineParams, rapidjson::PrettyWriter& writer) { writer.Key("EngineParams"); writer.StartObject(); writer.Key("TorqueCurve"); writeFloatLookupTable(engineParams.torqueCurve, writer); writer.Key("MOI"); writer.Double(static_cast(engineParams.moi)); writer.Key("PeakTorque"); writer.Double(static_cast(engineParams.peakTorque)); writer.Key("IdleOmega"); writer.Double(static_cast(engineParams.idleOmega)); writer.Key("MaxOmega"); writer.Double(static_cast(engineParams.maxOmega)); writer.Key("DampingRateFullThrottle"); writer.Double(static_cast(engineParams.dampingRateFullThrottle)); writer.Key("DampingRateZeroThrottleClutchEngaged"); writer.Double(double(engineParams.dampingRateZeroThrottleClutchEngaged)); writer.Key("DampingRateZeroThrottleClutchDisengaged"); writer.Double(double(engineParams.dampingRateZeroThrottleClutchDisengaged)); writer.EndObject(); return true; } bool readGearboxParams(const rapidjson::Document& config, PxVehicleGearboxParams& gearboxParams) { if (!config.HasMember("GearboxParams")) return false; if (!config["GearboxParams"].HasMember("NeutralGear")) return false; if (!config["GearboxParams"].HasMember("Ratios")) return false; if (!config["GearboxParams"].HasMember("FinalRatio")) return false; if (!config["GearboxParams"].HasMember("SwitchTime")) return false; gearboxParams.neutralGear = config["GearboxParams"]["NeutralGear"].GetInt(); gearboxParams.finalRatio = static_cast(config["GearboxParams"]["FinalRatio"].GetDouble()); gearboxParams.switchTime = static_cast(config["GearboxParams"]["SwitchTime"].GetDouble()); const rapidjson::Value& ratios = config["GearboxParams"]["Ratios"]; for(PxU32 i = 0; i < ratios.Size(); i++) { gearboxParams.ratios[i] = static_cast(ratios[i].GetDouble()); } gearboxParams.nbRatios = ratios.Size(); return true; } bool writeGearboxParams(const PxVehicleGearboxParams& gearboxParams, rapidjson::PrettyWriter& writer) { writer.Key("GearboxParams"); writer.StartObject(); writer.Key("NeutralGear"); writer.Int(gearboxParams.neutralGear); writer.Key("FinalRatio"); writer.Double(static_cast(gearboxParams.finalRatio)); writer.Key("SwitchTime"); writer.Double(static_cast(gearboxParams.switchTime)); writer.Key("Ratios"); writer.StartArray(); for(PxU32 i = 0; i < gearboxParams.nbRatios; i++) { writer.Double(static_cast(gearboxParams.ratios[i])); } writer.EndArray(); writer.EndObject(); return true; } bool readMultiWheelDiffParams(const rapidjson::Value& config, PxVehicleMultiWheelDriveDifferentialParams& multiWheelDiffParams) { if (!config.HasMember("TorqueRatios")) return false; if (!config.HasMember("AveWheelSpeedRatios")) return false; const rapidjson::Value& aveWheelSpeedRatios = config["AveWheelSpeedRatios"]; const rapidjson::Value& torqueRatios = config["TorqueRatios"]; if (aveWheelSpeedRatios.Size() != torqueRatios.Size()) return false; for (PxU32 i = 0; i < aveWheelSpeedRatios.Size(); i++) { multiWheelDiffParams.aveWheelSpeedRatios[i] = static_cast(aveWheelSpeedRatios[i].GetDouble()); multiWheelDiffParams.torqueRatios[i] = static_cast(torqueRatios[i].GetDouble()); } return true; } void writeMultiWheelDiffParams (const PxVehicleMultiWheelDriveDifferentialParams& multiWheelDiffParams, rapidjson::PrettyWriter& writer) { writer.Key("TorqueRatios"); writer.StartArray(); for (PxU32 i = 0; i < PxVehicleLimits::eMAX_NB_WHEELS; i++) { writer.Double(static_cast(multiWheelDiffParams.torqueRatios[i])); } writer.EndArray(); writer.Key("AveWheelSpeedRatios"); writer.StartArray(); for (PxU32 i = 0; i < PxVehicleLimits::eMAX_NB_WHEELS; i++) { writer.Double(static_cast(multiWheelDiffParams.aveWheelSpeedRatios[i])); } writer.EndArray(); } bool readMultiWheelDifferentialParams(const rapidjson::Document& config, PxVehicleMultiWheelDriveDifferentialParams& multiWheelDifferentialParams) { multiWheelDifferentialParams.setToDefault(); if (!config.HasMember("MultiWheelDifferentialParams")) return false; if (!readMultiWheelDiffParams(config["MultiWheelDifferentialParams"], multiWheelDifferentialParams)) return false; return true; } bool writeMultiWheelDifferentialParams (const PxVehicleMultiWheelDriveDifferentialParams& multiWheelDifferentialParams, rapidjson::PrettyWriter& writer) { writer.Key("MultiWheelDifferentialParams"); writer.StartObject(); writeMultiWheelDiffParams(multiWheelDifferentialParams, writer); writer.EndObject(); return true; } bool readFourWheelDifferentialParams(const rapidjson::Document& config, PxVehicleFourWheelDriveDifferentialParams& fourWheelDifferentialParams) { fourWheelDifferentialParams.setToDefault(); if (!config.HasMember("FourWheelDifferentialParams")) return false; if (!readMultiWheelDiffParams(config["FourWheelDifferentialParams"], static_cast(fourWheelDifferentialParams))) return false; if (!config["FourWheelDifferentialParams"].HasMember("FrontWheelIds")) return false; if (!config["FourWheelDifferentialParams"].HasMember("RearWheelIds")) return false; if (!config["FourWheelDifferentialParams"].HasMember("CenterBias")) return false; if (!config["FourWheelDifferentialParams"].HasMember("CenterTarget")) return false; if (!config["FourWheelDifferentialParams"].HasMember("FrontBias")) return false; if (!config["FourWheelDifferentialParams"].HasMember("FrontTarget")) return false; if (!config["FourWheelDifferentialParams"].HasMember("RearBias")) return false; if (!config["FourWheelDifferentialParams"].HasMember("RearTarget")) return false; if (!config["FourWheelDifferentialParams"].HasMember("Rate")) return false; const rapidjson::Value& frontWheelIds = config["FourWheelDifferentialParams"]["FrontWheelIds"]; if(frontWheelIds.Size() != 2) return false; fourWheelDifferentialParams.frontWheelIds[0] = frontWheelIds[0].GetInt(); fourWheelDifferentialParams.frontWheelIds[1] = frontWheelIds[1].GetInt(); const rapidjson::Value& rearWheelIds = config["FourWheelDifferentialParams"]["RearWheelIds"]; if (rearWheelIds.Size() != 2) return false; fourWheelDifferentialParams.rearWheelIds[0] = rearWheelIds[0].GetInt(); fourWheelDifferentialParams.rearWheelIds[1] = rearWheelIds[1].GetInt(); fourWheelDifferentialParams.centerBias = static_cast(config["FourWheelDifferentialParams"]["CenterBias"].GetDouble()); fourWheelDifferentialParams.centerTarget = static_cast(config["FourWheelDifferentialParams"]["CenterTarget"].GetDouble()); fourWheelDifferentialParams.frontBias = static_cast(config["FourWheelDifferentialParams"]["FrontBias"].GetDouble()); fourWheelDifferentialParams.frontTarget = static_cast(config["FourWheelDifferentialParams"]["FrontTarget"].GetDouble()); fourWheelDifferentialParams.rearBias = static_cast(config["FourWheelDifferentialParams"]["RearBias"].GetDouble()); fourWheelDifferentialParams.rearTarget = static_cast(config["FourWheelDifferentialParams"]["RearTarget"].GetDouble()); fourWheelDifferentialParams.rate = static_cast(config["FourWheelDifferentialParams"]["Rate"].GetDouble()); return true; } bool writeFourWheelDifferentialParams(const PxVehicleFourWheelDriveDifferentialParams& fourWheelDifferentialParams, rapidjson::PrettyWriter& writer) { writer.Key("FourWheelDifferentialParams"); writer.StartObject(); writeMultiWheelDiffParams(static_cast(fourWheelDifferentialParams), writer); writer.Key("FrontWheelIds"); writer.StartArray(); writer.Int(fourWheelDifferentialParams.frontWheelIds[0]); writer.Int(fourWheelDifferentialParams.frontWheelIds[1]); writer.EndArray(); writer.Key("RearWheelIds"); writer.StartArray(); writer.Int(fourWheelDifferentialParams.rearWheelIds[0]); writer.Int(fourWheelDifferentialParams.rearWheelIds[1]); writer.EndArray(); writer.Key("CenterBias"); writer.Double(static_cast(fourWheelDifferentialParams.centerBias)); writer.Key("CenterTarget"); writer.Double(static_cast(fourWheelDifferentialParams.centerTarget)); writer.Key("FrontBias"); writer.Double(static_cast(fourWheelDifferentialParams.frontBias)); writer.Key("FrontTarget"); writer.Double(static_cast(fourWheelDifferentialParams.frontTarget)); writer.Key("RearBias"); writer.Double(static_cast(fourWheelDifferentialParams.rearBias)); writer.Key("RearTarget"); writer.Double(static_cast(fourWheelDifferentialParams.rearTarget)); writer.Key("Rate"); writer.Double(static_cast(fourWheelDifferentialParams.rate)); writer.EndObject(); return true; } bool readTankDifferentialParams(const rapidjson::Document& config, PxVehicleTankDriveDifferentialParams& tankDifferentialParams) { tankDifferentialParams.setToDefault(); if (!config.HasMember("TankDifferentialParams")) return false; if(!readMultiWheelDiffParams(config["TankDifferentialParams"], static_cast(tankDifferentialParams))) return false; if (!config["TankDifferentialParams"].HasMember("TankTracks")) return false; const rapidjson::Value& tankTracks = config["TankDifferentialParams"]["TankTracks"]; for (PxU32 i = 0; i < tankTracks.Size(); i++) { const rapidjson::Value& tankTrack = tankTracks[i]; PxU32 wheelIds[PxVehicleLimits::eMAX_NB_WHEELS]; PxU32 nbWheels = 0; for (PxU32 j = 0; j < tankTrack.Size(); j++) { wheelIds[nbWheels] = static_cast(tankTrack[j].GetInt()); nbWheels++; } tankDifferentialParams.addTankTrack(nbWheels, wheelIds, i); } return true; } bool writeTankDifferentialParams(const PxVehicleTankDriveDifferentialParams& tankDifferentialParams, rapidjson::PrettyWriter& writer) { writer.Key("TankDifferentialParams"); writer.StartObject(); writeMultiWheelDiffParams(static_cast(tankDifferentialParams), writer); writer.Key("TankTracks"); writer.StartArray(); for (PxU32 i = 0; i < tankDifferentialParams.nbTracks; i++) { writer.StartArray(); for (PxU32 j = 0; j < tankDifferentialParams.getNbWheelsInTrack(i); j++) { writer.Int(static_cast(tankDifferentialParams.getWheelInTrack(j, i))); } writer.EndArray(); } writer.EndArray(); writer.EndObject(); return true; } bool reaClutchParams(const rapidjson::Document& config, PxVehicleClutchParams& clutchParams) { if (!config.HasMember("ClutchParams")) return false; if (!config["ClutchParams"].HasMember("AccuracyMode")) return false; if (!config["ClutchParams"].HasMember("EstimateIterations")) return false; clutchParams.accuracyMode = static_cast(config["ClutchParams"]["AccuracyMode"].GetInt()); clutchParams.estimateIterations = config["ClutchParams"]["EstimateIterations"].GetInt(); return true; } bool writeClutchParams(const PxVehicleClutchParams& clutchParams, rapidjson::PrettyWriter& writer) { writer.Key("ClutchParams"); writer.StartObject(); writer.Key("AccuracyMode"); writer.Int(static_cast(clutchParams.accuracyMode)); writer.Key("EstimateIterations"); writer.Int(clutchParams.estimateIterations); writer.EndObject(); return true; } bool readEngineDrivetrainParamsFromJsonFile(const char* directory, const char* filename, EngineDrivetrainParams& engineDrivetrainParams) { rapidjson::Document config; if (!openDocument(directory, filename, config)) return false; if(!readAutoboxParams(config, engineDrivetrainParams.autoboxParams)) return false; if(!readClutchCommandResponseParams(config, engineDrivetrainParams.clutchCommandResponseParams)) return false; if (!readEngineParams(config, engineDrivetrainParams.engineParams)) return false; if (!readGearboxParams(config, engineDrivetrainParams.gearBoxParams)) return false; if (!readMultiWheelDifferentialParams(config, engineDrivetrainParams.multiWheelDifferentialParams)) return false; if (!readFourWheelDifferentialParams(config, engineDrivetrainParams.fourWheelDifferentialParams)) return false; if (!readTankDifferentialParams(config, engineDrivetrainParams.tankDifferentialParams)) return false; if (!reaClutchParams(config, engineDrivetrainParams.clutchParams)) return false; return true; } bool writeEngineDrivetrainParamsToJsonFile(const char* directory, const char* filename, const EngineDrivetrainParams& engineDrivetrainParams) { rapidjson::StringBuffer strbuf; rapidjson::PrettyWriter writer(strbuf); writer.StartObject(); writeAutoboxParams(engineDrivetrainParams.autoboxParams, writer); writeClutchCommandResponseParams(engineDrivetrainParams.clutchCommandResponseParams, writer); writeEngineParams(engineDrivetrainParams.engineParams, writer); writeGearboxParams(engineDrivetrainParams.gearBoxParams, writer); writeMultiWheelDifferentialParams(engineDrivetrainParams.multiWheelDifferentialParams, writer); writeFourWheelDifferentialParams(engineDrivetrainParams.fourWheelDifferentialParams, writer); writeTankDifferentialParams(engineDrivetrainParams.tankDifferentialParams, writer); writeClutchParams(engineDrivetrainParams.clutchParams, writer); writer.EndObject(); std::ofstream myfile; myfile.open(std::string(directory) + "/" + filename); myfile << strbuf.GetString() << std::endl; myfile.close(); return true; } }//namespace snippetvehicle