public void SimulateAeroProperties(out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude) { // Rodhern: It seems that this method, 'SimulateAeroProperties', is only used in FARAPI, which in turn can be used by say KSPTrajectories. // The parameter 'FARCenterQuery dummy' is from a code fix by Benjamin Chung (commit 18fbb9d29431679a4de9dfc22a443f400d2d4f8b). FARCenterQuery center = new FARCenterQuery(); FARCenterQuery dummy = new FARCenterQuery(); float pressure; float density; float temperature; float speedOfSound; CelestialBody body = vessel.mainBody; //Calculate main gas properties pressure = (float)body.GetPressure(altitude); temperature = (float)body.GetTemperature(altitude); density = (float)body.GetDensity(pressure, temperature); speedOfSound = (float)body.GetSpeedOfSound(pressure, density); if (pressure <= 0 || temperature <= 0 || density <= 0 || speedOfSound <= 0) { aeroForce = Vector3.zero; aeroTorque = Vector3.zero; return; } float velocityMag = velocityWorldVector.magnitude; float machNumber = velocityMag / speedOfSound; float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex); float reynoldsPerLength = reynoldsNumber / (float)Length; float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber); float skinFriction = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber); FlightEnv fenv = FlightEnv.NewPredicted(vessel.mainBody, altitude, machNumber); if (_currentAeroSections != null) { for (int i = 0; i < _currentAeroSections.Count; i++) { FARAeroSection curSection = _currentAeroSections[i]; if (curSection != null) { curSection.PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center); } } for (int i = 0; i < _legacyWingModels.Count; i++) { FARWingAerodynamicModel curWing = _legacyWingModels[i]; if ((object)curWing != null) { Vector3d force = curWing.PrecomputeCenterOfLift(velocityWorldVector, fenv, dummy); center.AddForce(curWing.transform.position, force); } } } aeroForce = center.force; aeroTorque = center.TorqueAt(vessel.CoM); }
public void ApplyForce(FARAeroSection.PartData pd, Vector3 localVel, Vector3 forceVector, Vector3 torqueVector) { double tmp = 0.0005 * Vector3.SqrMagnitude(localVel); double dynamicPressurekPa = tmp * atmDensity; double dragFactor = dynamicPressurekPa * Mathf.Max(PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(atmDensity * Vector3.Magnitude(localVel)), 1.0f); double liftFactor = dynamicPressurekPa; Vector3 localVelNorm = Vector3.Normalize(localVel); Vector3 localForceTemp = Vector3.Dot(localVelNorm, forceVector) * localVelNorm; Vector3 partLocalForce = localForceTemp * (float)dragFactor + (forceVector - localForceTemp) * (float)liftFactor; forceVector = pd.aeroModule.part.transform.TransformDirection(partLocalForce); torqueVector = pd.aeroModule.part.transform.TransformDirection(torqueVector * (float)dynamicPressurekPa); if (float.IsNaN(forceVector.x) || float.IsNaN(torqueVector.x)) { return; } Vector3 centroid = pd.aeroModule.part.transform.TransformPoint(pd.centroidPartSpace - pd.aeroModule.part.CoMOffset); center.AddForce(centroid, forceVector); center.AddTorque(torqueVector); }
private void CalculateTotalAeroForce() { aeroForces.ClearAll(); if (_vessel.dynamicPressurekPa <= 0.00001) { return; } if (_currentAeroModules != null) { for (int i = 0; i < _currentAeroModules.Count; i++) { FARAeroPartModule m = _currentAeroModules[i]; if ((object)m != null) { aeroForces.AddForce(m.transform.position, m.totalWorldSpaceAeroForce); aeroForces.AddTorque(m.worldSpaceTorque); } } } /* * for (int i = 0; i < _LEGACY_currentWingAeroModel.Count; i++) * { * FARWingAerodynamicModel w = _LEGACY_currentWingAeroModel[i]; * if ((object)w == null) * continue; * totalAeroForceVector += w.worldSpaceForce; * aeroForces.AddForce(w.AerodynamicCenter, w.worldSpaceForce); * * totalAeroForceVector += w.worldSpaceForce; * totalAeroTorqueVector += Vector3.Cross(w.AerodynamicCenter - _vessel.CoM, w.worldSpaceForce); * } * * for(int i = 0; i < _vessel.parts.Count; i++) * { * Part p = _vessel.parts[i]; * totalAeroForceVector += -p.dragVectorDir * p.dragScalar; // dragVectorDir is actually the velocity vector direction * } */ }
private void CalculateTotalAeroForce() { aeroForces.ClearAll(); if (_vessel.dynamicPressurekPa <= 0.00001) { return; } if (_currentAeroModules == null) { return; } foreach (FARAeroPartModule m in _currentAeroModules) { if (m is null) { continue; } aeroForces.AddForce(m.transform.position, m.totalWorldSpaceAeroForce); aeroForces.AddTorque(m.worldSpaceTorque); } }
public void SimulateAeroProperties( out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude ) { Vector3d position = vessel.CurrentPosition(altitude); if (velocityWorldVector.NearlyEqual(lastSimResults.VelocityVector) && (FARAtmosphere.IsCustom // Custom atmospheres are not guaranteed to be independent of latitude and longitude ? position.NearlyEqual(lastSimResults.Position) : altitude.NearlyEqual(lastSimResults.Position.z))) { aeroForce = lastSimResults.Force; aeroTorque = lastSimResults.Torque; return; } var center = new FARCenterQuery(); var dummy = new FARCenterQuery(); //Calculate main gas properties GasProperties properties = FARAtmosphere.GetGasProperties(vessel.mainBody, position, Planetarium.GetUniversalTime()); if (properties.Pressure <= 0 || properties.Temperature <= 0) { aeroForce = Vector3.zero; aeroTorque = Vector3.zero; return; } float velocityMag = velocityWorldVector.magnitude; float machNumber = (float)(velocityMag / properties.SpeedOfSound); float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(properties.Density, Length, velocityMag, machNumber, properties.Temperature, properties.AdiabaticIndex); float reynoldsPerLength = reynoldsNumber / (float)Length; float skinFriction = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber); float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber); if (_currentAeroSections != null) { foreach (FARAeroSection curSection in _currentAeroSections) { curSection?.PredictionCalculateAeroForces((float)properties.Density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center); } foreach (FARWingAerodynamicModel curWing in _legacyWingModels) { if (curWing != null) { center.AddForce(curWing.transform.position, curWing.PrecomputeCenterOfLift(velocityWorldVector, machNumber, properties.Density, dummy)); } } } aeroForce = center.force; aeroTorque = center.TorqueAt(vessel.CoM); lastSimResults = new CachedSimResults(velocityWorldVector, position, aeroForce, aeroTorque); }
public void SimulateAeroProperties( out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude ) { var center = new FARCenterQuery(); var dummy = new FARCenterQuery(); CelestialBody body = vessel.mainBody; //Calculate main gas properties float pressure = (float)body.GetPressure(altitude); float temperature = (float)body.GetTemperature(altitude); float density = (float)body.GetDensity(pressure, temperature); float speedOfSound = (float)body.GetSpeedOfSound(pressure, density); if (pressure <= 0 || temperature <= 0 || density <= 0 || speedOfSound <= 0) { aeroForce = Vector3.zero; aeroTorque = Vector3.zero; return; } float velocityMag = velocityWorldVector.magnitude; float machNumber = velocityMag / speedOfSound; float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex); float reynoldsPerLength = reynoldsNumber / (float)Length; float skinFriction = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber); float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber); if (_currentAeroSections != null) { foreach (FARAeroSection curSection in _currentAeroSections) { curSection?.PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center); } foreach (FARWingAerodynamicModel curWing in _legacyWingModels) { if (!(curWing is null)) { center.AddForce(curWing.transform.position, curWing.PrecomputeCenterOfLift(velocityWorldVector, machNumber, density, dummy)); } } } aeroForce = center.force; aeroTorque = center.TorqueAt(vessel.CoM); }
public void SimulateAeroProperties( out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude ) { var center = new FARCenterQuery(); var dummy = new FARCenterQuery(); //Calculate main gas properties GasProperties properties = FARAtmosphere.GetGasProperties(vessel, altitude, Planetarium.GetUniversalTime()); if (properties.Pressure <= 0 || properties.Temperature <= 0) { aeroForce = Vector3.zero; aeroTorque = Vector3.zero; return; } float velocityMag = velocityWorldVector.magnitude; float machNumber = (float)(velocityMag / properties.SpeedOfSound); float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(properties.Density, Length, velocityMag, machNumber, properties.Temperature, properties.AdiabaticIndex); float reynoldsPerLength = reynoldsNumber / (float)Length; float skinFriction = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber); float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber); if (_currentAeroSections != null) { foreach (FARAeroSection curSection in _currentAeroSections) { curSection?.PredictionCalculateAeroForces((float)properties.Density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center); } foreach (FARWingAerodynamicModel curWing in _legacyWingModels) { if (curWing != null) { center.AddForce(curWing.transform.position, curWing.PrecomputeCenterOfLift(velocityWorldVector, machNumber, properties.Density, dummy)); } } } aeroForce = center.force; aeroTorque = center.TorqueAt(vessel.CoM); }