public override void FixedUpdate() { currentDrag = 0; // With unity objects, "foo" or "foo != null" calls a method to check if // it's destroyed. (object)foo != null just checks if it is actually null. if (start != StartState.Editor && (object)part != null) { if (animatingPart) { UpdatePropertiesWithAnimation(); } if (!isShielded) { Rigidbody rb = part.Rigidbody; Vessel vessel = part.vessel; // Check that rb is not destroyed, but vessel is just not null if (rb && (object)vessel != null && vessel.atmDensity > 0) { Vector3d velocity = rb.velocity + Krakensbane.GetFrameVelocity(); double soundspeed, v_scalar = velocity.magnitude; double rho = FARAeroUtil.GetCurrentDensity(vessel, out soundspeed); if (rho > 0 && v_scalar > 0.1) { Vector3d force = RunDragCalculation(velocity, v_scalar / soundspeed, rho); rb.AddForceAtPosition(force, GetCoD()); } } } } }
public void FixedUpdate() { if (aerodynamicModel_ != null && vessel_ != null) { CelestialBody body = vessel_.orbit.referenceBody; Vector3d bodySpacePosition = vessel_.GetWorldPos3D() - body.position; Vector3d bodySpaceVelocity = vessel_.obt_velocity; double altitudeAboveSea = bodySpacePosition.magnitude - body.Radius; Vector3d airVelocity = bodySpaceVelocity - body.getRFrmVel(body.position + bodySpacePosition); #if DEBUG_COMPARE_FORCES Vector3d FARForce = FARBasicDragModel.debugForceAccumulator + FARWingAerodynamicModel.debugForceAccumulator; FARBasicDragModel.debugForceAccumulator = new Vector3d(0, 0, 0); FARWingAerodynamicModel.debugForceAccumulator = new Vector3d(0, 0, 0); double rho = FARAeroUtil.GetCurrentDensity(body, altitudeAboveSea); //double rho = vessel_.atmDensity; //double pressure = FlightGlobals.getStaticPressure(altitudeAboveSea, body); //double rho = FlightGlobals.getAtmDensity(pressure); double machNumber = FARAeroUtil.GetMachNumber(body, altitudeAboveSea, airVelocity); //double machNumber = airVelocity.magnitude / 300.0; Transform vesselTransform = vessel_.ReferenceTransform; Vector3d vesselBackward = (Vector3d)(-vesselTransform.up.normalized); Vector3d vesselForward = -vesselBackward; Vector3d vesselUp = (Vector3d)(-vesselTransform.forward.normalized); Vector3d vesselRight = Vector3d.Cross(vesselUp, vesselBackward).normalized; double AoA = Math.Acos(Vector3d.Dot(airVelocity.normalized, vesselForward.normalized)); if (Vector3d.Dot(airVelocity, vesselUp) > 0) { AoA = -AoA; } Vector3d predictedForce = aerodynamicModel_.computeForces_FAR(rho, machNumber, airVelocity, vesselUp, AoA, 0.05); aerodynamicModel_.Verbose = true; Vector3d predictedForceWithCache = aerodynamicModel_.computeForces(body, bodySpacePosition, airVelocity, AoA, 0.05); aerodynamicModel_.Verbose = false; Vector3d localFARForce = new Vector3d(Vector3d.Dot(FARForce, vesselRight), Vector3d.Dot(FARForce, vesselUp), Vector3d.Dot(FARForce, vesselBackward)); Vector3d localPredictedForce = new Vector3d(Vector3d.Dot(predictedForce, vesselRight), Vector3d.Dot(predictedForce, vesselUp), Vector3d.Dot(predictedForce, vesselBackward)); Vector3d localPredictedForceWithCache = new Vector3d(Vector3d.Dot(predictedForceWithCache, vesselRight), Vector3d.Dot(predictedForceWithCache, vesselUp), Vector3d.Dot(predictedForceWithCache, vesselBackward)); Util.PostSingleScreenMessage("FAR/predict comparison", "air vel=" + Math.Floor(airVelocity.magnitude) + ", AoA=" + (AoA * 180.0 / Math.PI) + ", FAR force=" + localFARForce + ", predicted force=" + localPredictedForce); Util.PostSingleScreenMessage("predict with cache", "predicted force with cache=" + localPredictedForceWithCache); #endif double approximateRho = StockAeroUtil.GetDensity(altitudeAboveSea, body); double preciseRho = StockAeroUtil.GetDensity(vessel_.GetWorldPos3D(), body); double actualRho = vessel_.atmDensity; Util.PostSingleScreenMessage("rho info", "preciseRho=" + preciseRho.ToString("0.0000") + " ; approximateRho=" + approximateRho.ToString("0.0000") + " ; actualRho=" + actualRho.ToString("0.0000")); } }
public void FixedUpdate() { currentDrag = 0; // With unity objects, "foo" or "foo != null" calls a method to check if // it's destroyed. (object)foo != null just checks if it is actually null. if (HighLogic.LoadedSceneIsFlight && (object)part != null && FlightGlobals.ready) { if (animatingPart) { UpdatePropertiesWithAnimation(); } if (!isShielded) { Rigidbody rb = part.Rigidbody; Vessel vessel = part.vessel; // Check that rb is not destroyed, but vessel is just not null if (rb && (object)vessel != null && vessel.atmDensity > 0 && !vessel.packed) { Vector3d velocity = rb.velocity + Krakensbane.GetFrameVelocity() - FARWind.GetWind(FlightGlobals.currentMainBody, part, rb.position); double machNumber, v_scalar = velocity.magnitude; rho = FARAeroUtil.GetCurrentDensity(vessel.mainBody, part.transform.position); machNumber = GetMachNumber(vessel.mainBody, vessel.altitude, velocity); if (rho > 0 && v_scalar > 0.1) { double failureForceScaling = FARAeroUtil.GetFailureForceScaling(vessel); Vector3d force = RunDragCalculation(velocity, machNumber, rho, failureForceScaling); rb.AddForceAtPosition(force, GetCoD()); } } } } }
public double CalculateEAS() { double densityRatio = (FARAeroUtil.GetCurrentDensity(_vessel) / 1.225); return(_vessel.srfSpeed * Math.Sqrt(densityRatio)); }
public void ChangeSurfVelocity() { active = false; //DaMichel: Avoid conflict between multiple vessels in physics range. We only want to show the speed of the active vessel. if (FlightGlobals.ActiveVessel != _vessel) { return; } //DaMichel: Keep our fingers off of this also if there is no atmosphere (staticPressure <= 0) if (FlightGlobals.speedDisplayMode != FlightGlobals.SpeedDisplayModes.Surface || _vessel.atmDensity <= 0) { return; } if (SpeedDisplay.Instance == null) { return; } double unitConversion = 1; string unitString;// = "m/s"; string caption; if (unitMode == SurfaceVelUnit.KNOTS) { unitConversion = 1.943844492440604768413343347219; unitString = surfUnit_str[1]; } else if (unitMode == SurfaceVelUnit.KM_H) { unitConversion = 3.6; unitString = surfUnit_str[3]; } else if (unitMode == SurfaceVelUnit.MPH) { unitConversion = 2.236936; unitString = surfUnit_str[2]; } else { unitString = surfUnit_str[0]; } if (velMode == SurfaceVelMode.TAS) { caption = surfModel_str[0]; velString = (_vessel.srfSpeed * unitConversion).ToString("F1") + unitString; } else { if (velMode == SurfaceVelMode.IAS) { caption = surfModel_str[1]; //double densityRatio = (FARAeroUtil.GetCurrentDensity(_vessel) / 1.225); double pressureRatio = FARAeroUtil.RayleighPitotTubeStagPressure(_vessel.mach); //stag pressure at pitot tube face / ambient pressure double velocity = pressureRatio - 1; velocity *= _vessel.staticPressurekPa * 1000 * 2; velocity /= 1.225; velocity = Math.Sqrt(velocity); velString = (velocity * unitConversion).ToString("F1") + unitString; } else if (velMode == SurfaceVelMode.EAS) { caption = surfModel_str[2]; double densityRatio = (FARAeroUtil.GetCurrentDensity(_vessel) / 1.225); velString = (_vessel.srfSpeed * Math.Sqrt(densityRatio) * unitConversion).ToString("F1") + unitString; } else// if (velMode == SurfaceVelMode.MACH) { caption = surfModel_str[3]; velString = _vessel.mach.ToString("F3"); } } active = true; SpeedDisplay UI = SpeedDisplay.Instance; if (UI.textSpeed == null || UI.textTitle == null) { return; } UI.textTitle.text = caption; UI.textSpeed.text = velString; }
public void ChangeSurfVelocity() { active = false; //DaMichel: Avoid conflict between multiple vessels in physics range. We only want to show the speed of the active vessel. if (FlightGlobals.ActiveVessel != _vessel) { return; } //DaMichel: Keep our fingers off of this also if there is no atmosphere (staticPressure <= 0) if (FlightUIController.speedDisplayMode != FlightUIController.SpeedDisplayModes.Surface || _vessel.atmDensity <= 0) { return; } double unitConversion = 1; string unitString = "m/s"; string caption; if (unitMode == SurfaceVelUnit.KNOTS) { unitConversion = 1.943844492440604768413343347219; unitString = "knots"; } else if (unitMode == SurfaceVelUnit.KM_H) { unitConversion = 3.6; unitString = "km/h"; } else if (unitMode == SurfaceVelUnit.MPH) { unitConversion = 2.236936; unitString = "mph"; } if (velMode == SurfaceVelMode.TAS) { caption = "Surface"; velString = (_vessel.srfSpeed * unitConversion).ToString("F1") + unitString; } else { if (velMode == SurfaceVelMode.IAS) { caption = "IAS"; double densityRatio = (FARAeroUtil.GetCurrentDensity(_vessel.mainBody, _vessel.altitude, false) / 1.225); double pressureRatio = FARAeroUtil.StagnationPressureCalc(_vessel.mach); velString = (_vessel.srfSpeed * Math.Sqrt(densityRatio) * pressureRatio * unitConversion).ToString("F1") + unitString; } else if (velMode == SurfaceVelMode.EAS) { caption = "EAS"; double densityRatio = (FARAeroUtil.GetCurrentDensity(_vessel.mainBody, _vessel.altitude, false) / 1.225); velString = (_vessel.srfSpeed * Math.Sqrt(densityRatio) * unitConversion).ToString("F1") + unitString; } else// if (velMode == SurfaceVelMode.MACH) { caption = "Mach"; velString = _vessel.mach.ToString("F3"); } } active = true; FlightUIController UI = FlightUIController.fetch; if (UI.spdCaption == null || UI.speed == null) { return; } UI.spdCaption.text = caption; UI.speed.text = velString; }
private void FixedUpdate() { //Flight values if (!CompatibilityChecker.IsAllCompatible() || !HighLogic.LoadedSceneIsFlight || FlightGlobals.ActiveVessel == null || this.part.Rigidbody == null) { return; } this.pos = this.part.partTransform.position; this.ASL = FlightGlobals.getAltitudeAtPos(this.pos); this.trueAlt = this.ASL; if (this.vessel.mainBody.pqsController != null) { double terrainAlt = this.vessel.pqsAltitude; if (!this.vessel.mainBody.ocean || terrainAlt > 0) { this.trueAlt -= terrainAlt; } } this.atmPressure = FlightGlobals.getStaticPressure(this.ASL, this.vessel.mainBody) * PhysicsGlobals.KpaToAtmospheres; this.atmDensity = FARAeroUtil.GetCurrentDensity(this.vessel.mainBody, this.ASL, false); Vector3 velocity = this.part.Rigidbody.velocity + Krakensbane.GetFrameVelocityV3f(); this.sqrSpeed = velocity.sqrMagnitude; this.dragVector = -velocity.normalized; if (!this.staged && GameSettings.LAUNCH_STAGES.GetKeyDown() && this.vessel.isActiveVessel && (this.part.inverseStage == Staging.CurrentStage - 1 || Staging.CurrentStage == 0)) { ActivateRC(); } if (this.staged) { //Checks if the parachute must disarm if (this.armed) { this.part.stackIcon.SetIconColor(XKCDColors.LightCyan); if (this.canDeploy) { this.armed = false; } } //Parachute deployments else { //Parachutes if (this.canDeploy) { if (this.isDeployed) { if (!CalculateChuteTemp()) { return; } FollowDragDirection(); } switch (this.deploymentState) { case DeploymentStates.STOWED: { this.part.stackIcon.SetIconColor(XKCDColors.LightCyan); if (this.pressureCheck && this.randomDeployment) { PreDeploy(); } break; } case DeploymentStates.PREDEPLOYED: { this.part.Rigidbody.AddForceAtPosition(DragForce(0, this.preDeployedDiameter, 1f / this.semiDeploymentSpeed), this.forcePosition, ForceMode.Force); if (this.trueAlt <= this.deployAltitude && this.dragTimer.elapsed.TotalSeconds >= 1f / this.semiDeploymentSpeed) { Deploy(); } break; } case DeploymentStates.DEPLOYED: { this.part.rigidbody.AddForceAtPosition(DragForce(this.preDeployedDiameter, this.deployedDiameter, 1f / this.deploymentSpeed), this.forcePosition, ForceMode.Force); break; } default: break; } } //Deactivation else { if (this.isDeployed) { Cut(); } else { this.failedTimer.Start(); StagingReset(); } } } } }
private void partModuleUpdate(PartModule pm) { if (isFarLoaded && pm is FARControllableSurface) { FARControllableSurface fcs = (FARControllableSurface)pm; if (vessel.atmDensity > 0) { Vector3d forcePosition = fcs.AerodynamicCenter - vesselState.CoM; Vector3 velocity = fcs.GetVelocity(); double soundspeed, v_scalar = velocity.magnitude; double rho = FARAeroUtil.GetCurrentDensity(vessel, out soundspeed); if (rho <= 0.0 || v_scalar <= 0.1 || fcs.isShielded) { return; } // First we save the curent state of the part double YmaxForce = fcs.YmaxForce; double XZmaxForce = fcs.XZmaxForce; double AoAcurrentFlap = (double)(FieldAoAcurrentFlap.GetValue(fcs)); double MaxAoAdesiredControl = 0; if (fcs.pitchaxis != 0.0) { MaxAoAdesiredControl += (double)(FieldPitchLocation.GetValue(fcs)) * fcs.pitchaxis * 0.01; } if (fcs.yawaxis != 0.0) { MaxAoAdesiredControl += (double)(FieldYawLocation.GetValue(fcs)) * fcs.yawaxis * 0.01;; } if (fcs.rollaxis != 0.0) { MaxAoAdesiredControl += (double)(FieldRollLocation.GetValue(fcs)) * fcs.rollaxis * 0.01;; } MaxAoAdesiredControl *= fcs.maxdeflect; if (fcs.pitchaxisDueToAoA != 0.0) { double _AoA = (fcs as FARWingAerodynamicModel).CalculateAoA(velocity.normalized); _AoA = FARMathUtil.rad2deg * Math.Asin(_AoA); if (double.IsNaN(_AoA)) { _AoA = 0; } MaxAoAdesiredControl += _AoA * fcs.pitchaxisDueToAoA * 0.01; } MaxAoAdesiredControl = FARMathUtil.Clamp(MaxAoAdesiredControl, -Math.Abs(fcs.maxdeflect), Math.Abs(fcs.maxdeflect)); double MachNumber = v_scalar / soundspeed; fcs.YmaxForce = double.MaxValue; fcs.XZmaxForce = double.MaxValue; // Then we turn it one way double AoA = fcs.CalculateAoA(velocity, AoAcurrentFlap + MaxAoAdesiredControl); vesselState.ctrlTorqueAvailable.Add(vessel.GetTransform().InverseTransformDirection(Vector3.Cross(forcePosition, fcs.CalculateForces(velocity, MachNumber, AoA)))); // We restore it to the initial state AoA = fcs.CalculateAoA(velocity); fcs.CalculateForces(velocity, MachNumber, AoA); // And we turn it the other way AoA = fcs.CalculateAoA(velocity, AoAcurrentFlap - MaxAoAdesiredControl); vesselState.ctrlTorqueAvailable.Add(vessel.GetTransform().InverseTransformDirection(Vector3.Cross(forcePosition, fcs.CalculateForces(velocity, MachNumber, AoA)))); // And in the end we restore its initial state AoA = fcs.CalculateAoA(velocity); fcs.CalculateForces(velocity, MachNumber, AoA); fcs.YmaxForce = YmaxForce; fcs.XZmaxForce = XZmaxForce; } } }