KSP-KOS / KOS

Fully programmable autopilot mod for KSP. Originally By Nivekk
Other
695 stars 229 forks source link

request to add some missing atmosphere information #2373

Closed nuggreat closed 5 years ago

nuggreat commented 5 years ago

There are 3 things that would help with calculating some of the ideal gas equations that KSP uses to model it's atmospheres

The first is the molecular weight of that gas that makes up a given atmosphere This value is needed to calculate the density of an atmosphere For kerbin this value should be about 28.9644 g/mol and for duna it should be about 42 g/mol

The second is the called the adiabatic index or heat capacity ratio depending on source This value is needed to calculate the speed of sound in at a given atmospheric temperature For kerbin this value should be about 1.4 and duna it should be about 1.2

Also if possible the ability to get the temperature of a given position would be extremely useful for atmospheric calculations if not as essential as the first 2

The reasons theses values are needed is currently they are only available though an external source like the KSP forums or wiki and for modded star systems like galileo planet pack the bodies might have completely different atmospheres from stock and might not be easy to find the information on there atmospheres

Dunbaratu commented 5 years ago

I happened to have the IDE open and I found these things in the KSP classes, which might work:

double CelestialBody.atmosphereMolarMass (Not Molecular Mass, but it should be convertable)

double CelestialBody.atmosphereAdiabaticIndex

double CelestialBody.GetTemperature(double altitude) (presumably, outputs a temperature at a given altitude.)

nuggreat commented 5 years ago

molar mass is molecular mass so that is likely exactly the info needed for that

any temp data is better than none but ideally position linked data would be best as the temperature is effected by the sun so something that takes time of day and latitude into account is better

from what I have seen in my reading about the KSP atmosphere model all bodies have a altitude linked temperature curve of some kind (likely given by this call) that is used as the baseline to then be modified by the local time of day and latitude

Dunbaratu commented 5 years ago

Is there a good place I can link to for documenting this so I don't have to write up an explanation myself, which I'm sure I'd screw up? (Somewhere I can point to in the user docs page explaining the suffix).

nuggreat commented 5 years ago

The molar mass is related to the specific gas constant and which in turn is related to the idea gas law and needed to calculate atmospheric density given pressure and temperature.

The AdiabaticIndex has to do with how compressible a gas is and thus is required for calculating the speed of sound in a given medium.

The temperature is self explanatory it would be best if it was in kelvin otherwise for it will need to be converted into kelvin for the gas calculations.

The specific equations I would like thees values for are as follows.

r = specific gas constant, unit: J/(kg*k) R = Gas constant, value: 8.3144598, unit: J/(mol*K) m = molar mass, unit: kg/mol

r = R / m

d = atmospheric dencity, unit: kg/m^3 p = atmospheric pressure, unit: kPa t = temprature, unit: K

d = p / (r * t)

c = speed of sound, unit: m/s a = Adiabatic Index, unit less i think

c = SQRT(a r t)

The importance of the speed of sound is because the coefficient of drag for a craft is not constant and changes depending on the current mach number (craftSpeed/SpeedOfSound). So for accurate drag prediction I need to be able to predict the change in the coefficient of drag and I can only do that with the calculated speed of sound for a specific temperature and atmospheric composition,.

The molar mass is important to the drag force calculation because said calculation is directly proportional to the density of the atmosphere for a given pressure and temperature.

Dunbaratu commented 5 years ago

For temperature I just found what I think is a better API call that might take all those things into account:

It's called Body.GetFullTemperature().

It comes in two variants:

Presumably the Vector pos version gets the full answer because it contains both of the two pieces of information together, if we presume that's how this works. (The position vector could be used by the game to know both the altitude and where you are in the day/night cycle)

The other variant might be nice to provide to people, but I'd also have to find out how atmoSunBasedTempOffset is calculated to do that. I think the Vector version would be sufficient for what you need. With that I could do two calls in kOS, like so:

SHIP:ATMOTEMP Returns the atmosphere's temperature at the ship's current position. If ship is in vacuum, it would maybe return 0 Kelvin? (I hope the stock KSP API behavior when given an altitude above atmo height makes sense here and I don't have to fudge it).

BODY:ATM:TEMPAT(position_vector) Returns the atmosphere's temperature at a given XYZ position in ship-raw coords.

nuggreat commented 5 years ago

With out checking the actual numbers we get the 3dPos one that looks exactly like what I would want from the temperature calls.

As for there what they are returning the ship centered one could be checked against the temprature found in the aroGUI found in alt+f12 > physics > aero > display aero data GUI and if that matches i would just assume it works for any position.

The airoGUI also reports 4 deg K when in space as said GUI is info for flight and it's temps have as far as i can tell always been accurate i would assume this is also what the API will return.

If I was to guess this is a reference to the anomalous temp value of 4.2 deg K that lead to discovering the cosmic microwave background.

The only other thing I can think that might be of use would be to add the molar/ideal/universal gas constant to the set of kOS constants that can be accessed.

This constant is most often referred to by using "R" where it shows gas equations like such as PV=nRT

Dunbaratu commented 5 years ago

I could not find universal gas constant in the physics globals that KSP provides, but I could find Avragado's constant, and Boltzmann's constant in there, which the formulas say can be used to derive the universal gas constant.

I'll expose them as globals.

Dunbaratu commented 5 years ago

@nuggreat - as long as I'm adding things to Constants and my hands are in that code, here's a list of all the things on KSP's own PhysicsGlobals list that I could add support for. Are any of these useful?

They're not really documented so you have to guess from the name alone what they do and what units they're in.


public class PhysicsGlobals : MonoBehaviour
{
    public const double EngineDefaultAtmDensity = 1.2250000238418579;
    public static double GraviticForceMultiplier;
    public static double GravitationalAcceleration;
    public static SurfaceCurvesList SurfaceCurves;
    public VesselRanges VesselRangesDefault;

    public PhysicsGlobals();

    public static float BuildingImpactDamageMaxVelocityMult { get; set; }
    public static bool BuildingImpactDamageUseMomentum { get; set; }
    public static float BuildingEasingInvulnerableTime { get; set; }
    public static int OrbitDriftFramesToWait { get; set; }
    public static double OrbitDriftSqrThreshold { get; set; }
    public static double OrbitDriftAltThreshold { get; set; }
    public static bool ApplyDragToNonPhysicsParts { get; set; }
    public static bool ApplyDragToNonPhysicsPartsAtParentCoM { get; set; }
    public static float DragMultiplier { get; set; }
    public static float AngularDragMultiplier { get; set; }
    public static float DragCubeMultiplier { get; set; }
    public static float MaxAngularVelocity { get; set; }
    public static string KerbalEVADragCubeString { get; set; }
    public static ConfigNode KerbalEVADragCube { get; }
    public static float KerbalCrewMass { get; set; }
    public static double KerbalGOffset { get; set; }
    public static double KerbalGPower { get; set; }
    public static double KerbalGDecayPower { get; set; }
    public static float BodyLiftMultiplier { get; set; }
    public static float RigidJointBreakTorqueFactor { get; set; }
    public static float JointBreakTorqueFactor { get; set; }
    public static float JointForce { get; set; }
    public static double BuoyancyWaterDragPartVelGreaterVesselMult { get; set; }
    public static double BuoyancyWaterDragTimer { get; set; }
    public static double BuoyancyWaterDragMultMinForMinDot { get; set; }
    public static double BuoyancyWaterAngularDragScalar { get; set; }
    public static double BuoyancyAngularDragMinControlSqrMag { get; set; }
    public static float BuoyancyWaterAngularDragSlow { get; set; }
    public static float BuoyancyWaterDragSlow { get; set; }
    public static double BuoyancyWaterDragExtraRBDragAboveDot { get; set; }
    public static float RigidJointBreakForceFactor { get; set; }
    public static double BuoyancyScaleAboveDepth { get; set; }
    public static float BuoyancyMinCrashMult { get; set; }
    public static float BuoyancyCrashToleranceMult { get; set; }
    public static double BuoyancyRange { get; set; }
    public static float BuoyancyKerbals { get; set; }
    public static double BuoyancyKerbalsRagdoll { get; set; }
    public static float CameraDepthToUnlock { get; set; }
    public static float JointBreakForceFactor { get; set; }
    public static double KerbalGBraveMult { get; set; }
    public static double BuoyancyDefaultVolume { get; set; }
    public static double KerbalGBadMult { get; set; }
    public static double KerbalGThresholdLOC { get; set; }
    public static double KerbalGThresholdWarn { get; set; }
    public static float LiftMultiplier { get; set; }
    public static float LiftDragMultiplier { get; set; }
    public static Dictionary<string, LiftingSurfaceCurve> LiftingSurfaceCurves { get; }
    public static LiftingSurfaceCurve BodyLiftCurve { get; set; }
    public static float AeroFXStartThermalFX { get; set; }
    public static float AeroFXFullThermalFX { get; set; }
    public static double AeroFXVelocityExponent { get; set; }
    public static double AeroFXDensityExponent1 { get; set; }
    public static FloatCurve DragCurvePseudoReynolds { get; }
    public static double AeroFXDensityScalar1 { get; set; }
    public static double AeroFXDensityScalar2 { get; set; }
    public static float AeroFXMachFXFadeStart { get; set; }
    public static float AeroFXMachFXFadeEnd { get; set; }
    public static double AeroFXDensityFadeStart { get; set; }
    public static string AutoStrutTechRequired { get; set; }
    public static Part.ShowRigidAttachmentOption ShowRigidJointTweakable { get; set; }
    public static float StagingCooldownTimer { get; set; }
    public static VesselTargetModes CelestialBodyTargetingMode { get; set; }
    public static double AeroFXDensityExponent2 { get; set; }
    public static double KerbalGClamp { get; set; }
    public static FloatCurve DragCurveCdPower { get; }
    public static FloatCurve DragCurveMultiplier { get; }
    public static double BuoyancyWaterDragMinVelMultCOBOff { get; set; }
    public static double KerbalGLOCTimeMult { get; set; }
    public static double KerbalGLOCMaxTimeIncrement { get; set; }
    public static double KerbalGLOCBaseTime { get; set; }
    public static bool KerbalGClampGExperienced { get; set; }
    public static double CommNetQTimesVelForBlackoutMin { get; set; }
    public static double CommNetQTimesVelForBlackoutMax { get; set; }
    public static double CommNetTempForBlackout { get; set; }
    public static FloatCurve DragCurveCd { get; }
    public static double CommNetDensityForBlackout { get; set; }
    public static double CommNetDotForBlackoutMax { get; set; }
    public static double CommNetBlackoutThreshold { get; set; }
    public static bool ApplyDrag { get; set; }
    public static bool DragUsesAcceleration { get; set; }
    public static bool DragCubesUseSpherical { get; set; }
    public static FloatCurve DragCurveTip { get; }
    public static FloatCurve DragCurveSurface { get; }
    public static FloatCurve DragCurveTail { get; }
    public static double CommNetDotForBlackoutMin { get; set; }
    public static double BuoyancyWaterDragMinVelMult { get; set; }
    public static double BuoyancyWaterDragScalarLerpDotMult { get; set; }
    public static double BuoyancyWaterLiftScalarEnd { get; set; }
    public static double NewtonianDensityExponent { get; set; }
    public static double NewtonianConvectionFactorBase { get; set; }
    public static double NewtonianConvectionFactorTotal { get; set; }
    public static double NewtonianVelocityExponent { get; set; }
    public static Gradient BlackBodyRadiation { get; }
    public static float BlackBodyRadiationMin { get; set; }
    public static float BlackBodyRadiationMax { get; set; }
    public static double MachConvectionVelocityExponent { get; set; }
    public static float BlackBodyRadiationAlphaMult { get; set; }
    public static bool ThermalColorsDebug { get; set; }
    public static float TemperatureGaugeThreshold { get; set; }
    public static float TemperatureGaugeHighlightThreshold { get; set; }
    public static double RadiationFactor { get; set; }
    public static double MachConvectionFactor { get; set; }
    public static double BuoyancyWaterDragMinVel { get; set; }
    public static double ConvectionFactorSplashed { get; set; }
    public static bool ThermalDataDisplay { get; set; }
    public static double MachConvectionDensityExponent { get; set; }
    public static double SolarInsolationAtHome { get; set; }
    public static double SolarLuminosityAtHome { get; set; }
    public static PhysicsGlobals Instance { get; }
    public static string PhysicsDatabaseFilename { get; set; }
    public static bool AeroDataDisplay { get; set; }
    public static bool AeroForceDisplay { get; set; }
    public static bool AeroGUIDisplay { get; set; }
    public static float AeroForceDisplayScale { get; set; }
    public static bool AutoStrutDisplay { get; set; }
    public static bool RoboticJointDataDisplay { get; set; }
    public static double IdealGasConstant { get; }
    public static double BoltzmannConstant { get; }
    public static double StefanBoltzmanConstant { get; }
    public static double AvogadroConstant { get; }
    public static double KpaToAtmospheres { get; }
    public static bool ThermoGUIDisplay { get; set; }
    public static double ThermalMaxIntegrationWarp { get; set; }
    public static double SpaceTemperature { get; set; }
    public static double SolarLuminosity { get; }
    public static double FullToCrossSectionLerpStart { get; set; }
    public static double NewtonianMachTempLerpEndMach { get; set; }
    public static double ConductionFactor { get; set; }
    public static double NewtonianMachTempLerpExponent { get; set; }
    public static int ThermalIntegrationHighMaxPasses { get; set; }
    public static double NewtonianMachTempLerpStartMach { get; set; }
    public static double ThermalConvergenceFactor { get; set; }
    public static double AnalyticLerpRateSkin { get; set; }
    public static double AnalyticLerpRateInternal { get; set; }
    public static double AnalyticConvectionSensitivityBase { get; set; }
    public static double AnalyticConvectionSensitivityFinal { get; set; }
    public static double OcclusionMinStep { get; set; }
    public static int TemperaturePropertyID { get; }
    public static bool BuoyancyUseCoBOffset { get; set; }
    public static bool BuoyancyApplyForceOnDie { get; set; }
    public static float BuoyancyForceOffsetLerp { get; set; }
    public static double BuoyancyWaterDragScalar { get; set; }
    public static double BuoyancyWaterDragScalarEnd { get; set; }
    public static double BuoyancyWaterDragScalarLerp { get; set; }
    public static double BuoyancyWaterDragScalarLerpDotMultBase { get; set; }
    public static double BuoyancyScalar { get; set; }
    public static bool ThermalIntegrationAlwaysRK2 { get; set; }
    public static int ThermalIntegrationHighMinPasses { get; set; }
    public static double ThermalIntegrationMinStep { get; set; }
    public static double MachTemperatureScalar { get; set; }
    public static double MachTemperatureVelocityExponent { get; set; }
    public static double TurbulentConvectionStart { get; set; }
    public static double TurbulentConvectionEnd { get; set; }
    public static double ThermalIntegrationMaxTimeOnePass { get; set; }
    public static double FullConvectionAreaMin { get; set; }
    public static double FullToCrossSectionLerpEnd { get; set; }
    public static double InternalHeatProductionFactor { get; set; }
    public static double TurbulentConvectionMult { get; set; }
    public static double ShieldedConductionFactor { get; set; }
    public static bool ThermalRadiationEnabled { get; set; }
    public static bool ThermalConductionEnabled { get; set; }
    public static bool ThermalConvectionEnabled { get; set; }
    public static double StandardSpecificHeatCapacity { get; set; }
    public static double SkinSkinConductionFactor { get; set; }
    public static double SkinInternalConductionFactor { get; set; }
    public static double NewtonianTemperatureFactor { get; set; }

    public static float DragCurveValue(SurfaceCurvesList cuves, float dotNormalized, float mach);
    public static Color GetBlackBodyRadiation(float temperature, Part part);
    public static LiftingSurfaceCurve GetLiftingSurfaceCurve(string name);
    public void CalculateValues();
    [ContextMenu("Load Database")]
    public bool LoadDatabase();
    [ContextMenu("Save Database")]
    public void SaveDatabase();

    public struct SurfaceCurvesList
    {
        public FloatCurve dragCurveTail;
        public FloatCurve dragCurveSurface;
        public FloatCurve dragCurveMultiplier;
        public FloatCurve dragCurveTip;
    }

    public class LiftingSurfaceCurve
    {
        public string name;
        public FloatCurve liftCurve;
        public FloatCurve liftMachCurve;
        public FloatCurve dragCurve;
        public FloatCurve dragMachCurve;

        public LiftingSurfaceCurve();

        public void Load(ConfigNode node);
        public void Save(ConfigNode node);
    }
}
Dunbaratu commented 5 years ago

Ah - I just saw that "ideal gas constant" is one of the things in the list, and "ideal" gas constant is listed as an alternative name for "universal" gas constant in wikipedia so it's probably the same thing?

Dunbaratu commented 5 years ago

Well, GetFullTemperature doesn't do what I thought. I tried it at vessel position at the launchpad and the answer it returned was: 10327691.6269393. No matter the units (the altitude temperature appears to be in K, because it gave values like 288, or 279, or 243, etc at various altitudes of Kerbin, but I have no idea what units this thing is).

nuggreat commented 5 years ago

Yes the "ideal gas constant" is likely the same thing as the "universal gas constant".

As for the temperature thing I have no idea what is going on there but failing all else the altitude based one should be good enough for rough calculations.

nuggreat commented 5 years ago

Thinking on it I wonder if the position for the GetFullTemperature is in a different reference frame from the raw ship3d position and you might need to do something silly like add/subtract the sun position and/or the body position

As an alternate source because I know trajectories mod does accurate atmospheric prediction I went poking about in there source and found this file that does have a function for calculating the temp at a given 3d position annoyingly named the same as the stock call. The problem with using a function like that one is obvious namely if squad change how temperature is calculated then said function will break and it might not be obvious that said function is not returning the correct data with out explicit testing.