Example #1
0
        private Vector3d getForces_FAR(CelestialBody body, Vector3d bodySpacePosition, Vector3d airVelocity, double angleOfAttack, double dt)
        {
            if (!isFARInitialized())
            {
                return(new Vector3d(0, 0, 0));
            }

            double altitudeAboveSea = bodySpacePosition.magnitude - body.Radius;

            double stockRho = StockAeroUtil.GetDensity(altitudeAboveSea, body);

            if (stockRho <= 0)
            {
                return(Vector3d.zero);
            }
            double rho = stockRho;

            rho = useNEAR ? stockRho : (double)FARAeroUtil_GetCurrentDensity.Invoke(null, new object[] { body, altitudeAboveSea, false });

#if !USE_CACHE
            return(computeForces_FAR(altitudeAboveSea, airVelocity, bodySpacePosition, angleOfAttack, dt));
#else
            //double approxMachNumber = useNEAR ? 0.0 : (double)FARAeroUtil_GetMachNumber.Invoke(null, new object[] { body_, body.maxAtmosphereAltitude * 0.5, new Vector3d((float)airVelocity.magnitude, 0, 0) });
            //Util.PostSingleScreenMessage("machNum", "machNumber = " + actualMachNumber + " ; approx machNumber = " + approxMachNumber);

            Vector2 force = getCachedForce(airVelocity.magnitude, altitudeAboveSea, angleOfAttack);

            Vector3d forward = airVelocity.normalized;
            Vector3d right   = Vector3d.Cross(forward, bodySpacePosition).normalized;
            Vector3d up      = Vector3d.Cross(right, forward).normalized;

            return(forward * force.x + up * force.y);
#endif
        }
Example #2
0
        public override Vector3d UnpackForces(Vector2 packedForces, double altitudeAboveSea, double velocity)
        {
            double rho   = StockAeroUtil.GetDensity(altitudeAboveSea, body_);
            double scale = velocity * velocity * rho;

            return(new Vector3d((double)packedForces.x * scale, (double)packedForces.y * scale, 0.0));
        }
Example #3
0
        public Vector3d getForces_StockAero(CelestialBody body, Vector3d bodySpacePosition, Vector3d airVelocity, double angleOfAttack, double dt)
        {
            Vector3d position = body.position + bodySpacePosition;

            double altitude = (position - body.position).magnitude - body.Radius;

            if (altitude > body.atmosphereDepth)
            {
                return(Vector3d.zero);
            }
#if !USE_CACHE
            return(computeForces_StockAero(altitude, airVelocity, new Vector3(0, 1, 0), angleOfAttack, dt));
#else
            //double approxMachNumber = useNEAR ? 0.0 : (double)FARAeroUtil_GetMachNumber.Invoke(null, new object[] { body_, body.maxAtmosphereAltitude * 0.5, new Vector3d((float)airVelocity.magnitude, 0, 0) });
            //Util.PostSingleScreenMessage("machNum", "machNumber = " + actualMachNumber + " ; approx machNumber = " + approxMachNumber);

            Vector2 force = getCachedForce(airVelocity.magnitude, altitude, angleOfAttack);

            // adjust force using the more accurate air density that we can compute knowing where the vessel is relatively to the sun and body
            double preciseRho     = StockAeroUtil.GetDensity(position, body);
            double approximateRho = StockAeroUtil.GetDensity(altitude, body);
            if (approximateRho > 0)
            {
                force = force * (float)(preciseRho / approximateRho);
            }

            Vector3d forward = airVelocity.normalized;
            Vector3d right   = Vector3d.Cross(forward, bodySpacePosition).normalized;
            Vector3d up      = Vector3d.Cross(right, forward).normalized;

            return(forward * force.x + up * force.y);
#endif
        }
Example #4
0
        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"));
            }
        }
Example #5
0
        public override Vector2 PackForces(Vector3d forces, double altitudeAboveSea, double velocity)
        {
            double rho = StockAeroUtil.GetDensity(altitudeAboveSea, body_); // would be even better to use FAR method of computing the air density (which also depends on velocity), but this is already better than nothing

            if (rho < 0.0000000001)
            {
                return(new Vector2(0, 0));
            }
            double invScale = 1.0 / (rho * Math.Max(1.0, velocity * velocity));

            forces *= invScale;
            return(new Vector2((float)forces.x, (float)forces.y));
        }
        public override Vector2 PackForces(Vector3d forces, double altitudeAboveSea, double velocity)
        {
            double rho = StockAeroUtil.GetDensity(altitudeAboveSea, body_);

            if (rho < 0.0000000001)
            {
                return(new Vector2(0, 0));
            }
            double invScale = 1.0 / (rho * Math.Max(1.0, velocity * velocity)); // divide by v² and rho before storing the force, to increase accuracy (the reverse operation is performed when reading from the cache)

            forces *= invScale;
            return(new Vector2((float)forces.x, (float)forces.y));
        }
Example #7
0
        private Vector2 getCachedForce(double velocity, double altitudeAboveSea, double angleOfAttack)
        {
            precomputeCache();

            //Util.PostSingleScreenMessage("getFARForce velocity", "velocity = " + velocity);
            float vFrac  = (float)(velocity / maxFARVelocity * (double)(cachedFARForces.GetLength(0) - 1));
            int   vFloor = Math.Min(cachedFARForces.GetLength(0) - 2, (int)vFrac);

            vFrac = Math.Min(1.0f, vFrac - (float)vFloor);

            float aFrac  = (float)((angleOfAttack / maxFARAngleOfAttack * 0.5 + 0.5) * (double)(cachedFARForces.GetLength(1) - 1));
            int   aFloor = Math.Max(0, Math.Min(cachedFARForces.GetLength(1) - 2, (int)aFrac));

            aFrac = Math.Max(0.0f, Math.Min(1.0f, aFrac - (float)aFloor));

            double maxAltitude = body_.atmosphereDepth;
            float  mFrac       = (float)(altitudeAboveSea / maxAltitude * (double)(cachedFARForces.GetLength(2) - 1));
            int    mFloor      = Math.Max(0, Math.Min(cachedFARForces.GetLength(2) - 2, (int)mFrac));

            mFrac = Math.Max(0.0f, Math.Min(1.0f, mFrac - (float)mFloor));

            if (Verbose)
            {
                Util.PostSingleScreenMessage("cache cell", "cache cell: [" + vFloor + ", " + aFloor + ", " + mFloor + "]");
                Util.PostSingleScreenMessage("altitude cell", "altitude cell: " + altitudeAboveSea + " / " + maxAltitude + " * " + (double)(cachedFARForces.GetLength(2) - 1));
            }

            Vector2 res = sample3d(vFloor, vFrac, aFloor, aFrac, mFloor, mFrac);

            double stockRho = StockAeroUtil.GetDensity(altitudeAboveSea, body_);
            double rho      = stockRho;

            if (!useStockModel)
            {
                rho = useNEAR ? stockRho : (double)FARAeroUtil_GetCurrentDensity.Invoke(null, new object[] { body_, altitudeAboveSea, false });
            }

            res = res * (float)(velocity * velocity * rho);

            return(res);
        }
Example #8
0
        private Vector2 computeCacheEntry(int v, int a, int m)
        {
            double vel = maxFARVelocity * (double)v / (double)(cachedFARForces.GetLength(0) - 1);
            double v2  = Math.Max(1.0, vel * vel);

            Vector3d velocity = new Vector3d(vel, 0, 0);

            double maxAltitude     = body_.atmosphereDepth;
            double currentAltitude = maxAltitude * (double)m / (double)(cachedFARForces.GetLength(2) - 1);
            double stockRho        = StockAeroUtil.GetDensity(currentAltitude, body_);
            double rho             = stockRho;

            if (!useStockModel)
            {
                if (!isFARInitialized())
                {
                    throw new Exception("Internal error");
                }
                rho = useNEAR ? stockRho : (double)FARAeroUtil_GetCurrentDensity.Invoke(null, new object[] { body_, currentAltitude, false });
            }
            if (rho < 0.0000000001)
            {
                return(new Vector2(0, 0));
            }
            double invScale = 1.0 / (rho * v2); // divide by v² and rho before storing the force, to increase accuracy (the reverse operation is performed when reading from the cache)

            double AoA = maxFARAngleOfAttack * ((double)a / (double)(cachedFARForces.GetLength(1) - 1) * 2.0 - 1.0);

            Vector3d force;

            if (useStockModel)
            {
                force = computeForces_StockAero(currentAltitude, velocity, new Vector3(0, 1, 0), AoA, 0.25) * invScale;
            }
            else
            {
                force = computeForces_FAR(currentAltitude, velocity, new Vector3(0, 1, 0), AoA, 0.25) * invScale;
            }
            return(cachedFARForces[v, a, m] = new Vector2((float)force.x, (float)force.y));
        }
Example #9
0
        internal static void DebugTelemetry()
        {
            if (!Util.IsFlight)
            {
                return;
            }

            double now = Planetarium.GetUniversalTime();
            double dt  = now - PreviousFrameTime;

            if (dt > 0.5 || dt < 0.0)
            {
                Vector3d bodySpacePosition = new Vector3d();
                Vector3d bodySpaceVelocity = new Vector3d();

                if (aerodynamicModel_ != null && Trajectories.IsVesselAttached)
                {
                    CelestialBody body = Trajectories.AttachedVessel.orbit.referenceBody;

                    bodySpacePosition = Trajectories.AttachedVessel.GetWorldPos3D() - body.position;
                    bodySpaceVelocity = Trajectories.AttachedVessel.obt_velocity;

                    double altitudeAboveSea = bodySpacePosition.magnitude - body.Radius;

                    Vector3d airVelocity = bodySpaceVelocity - body.getRFrmVel(body.position + bodySpacePosition);

                    double   R            = PreviousFramePos.magnitude;
                    Vector3d gravityForce = PreviousFramePos * (-body.gravParameter / (R * R * R) * Trajectories.AttachedVessel.totalMass);

                    Quaternion inverseRotationFix = body.inverseRotation ?
                                                    Quaternion.AngleAxis((float)(body.angularVelocity.magnitude / Math.PI * 180.0 * dt), Vector3.up)
                        : Quaternion.identity;
                    Vector3d TotalForce = (bodySpaceVelocity - inverseRotationFix * PreviousFrameVelocity) * (Trajectories.AttachedVessel.totalMass / dt);
                    TotalForce += bodySpaceVelocity * (dt * 0.000015); // numeric precision fix
                    Vector3d ActualForce = TotalForce - gravityForce;

                    Transform vesselTransform = Trajectories.AttachedVessel.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;
                    }

                    VesselAerodynamicModel.DebugParts = true;
                    Vector3d referenceForce = aerodynamicModel_.ComputeForces(20000, new Vector3d(0, 0, 1500), new Vector3d(0, 1, 0), 0);
                    VesselAerodynamicModel.DebugParts = false;

                    Vector3d predictedForce = aerodynamicModel_.ComputeForces(altitudeAboveSea, airVelocity, vesselUp, AoA);
                    //VesselAerodynamicModel.Verbose = true;
                    Vector3d predictedForceWithCache = aerodynamicModel_.GetForces(body, bodySpacePosition, airVelocity, AoA);
                    //VesselAerodynamicModel.Verbose = false;

                    Vector3d localTotalForce = new Vector3d(
                        Vector3d.Dot(TotalForce, vesselRight),
                        Vector3d.Dot(TotalForce, vesselUp),
                        Vector3d.Dot(TotalForce, vesselBackward));
                    Vector3d localActualForce = new Vector3d(
                        Vector3d.Dot(ActualForce, vesselRight),
                        Vector3d.Dot(ActualForce, vesselUp),
                        Vector3d.Dot(ActualForce, 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));

                    Telemetry.Send("ut", now);
                    Telemetry.Send("altitude", Trajectories.AttachedVessel.altitude);

                    Telemetry.Send("airspeed", Math.Floor(airVelocity.magnitude));
                    Telemetry.Send("aoa", (AoA * 180.0 / Math.PI));

                    Telemetry.Send("force_actual", localActualForce.magnitude);
                    Telemetry.Send("force_actual.x", localActualForce.x);
                    Telemetry.Send("force_actual.y", localActualForce.y);
                    Telemetry.Send("force_actual.z", localActualForce.z);


                    //Telemetry.Send("force_total", localTotalForce.magnitude);
                    //Telemetry.Send("force_total.x", localTotalForce.x);
                    //Telemetry.Send("force_total.y", localTotalForce.y);
                    //Telemetry.Send("force_total.z", localTotalForce.z);

                    Telemetry.Send("force_predicted", localPredictedForce.magnitude);
                    Telemetry.Send("force_predicted.x", localPredictedForce.x);
                    Telemetry.Send("force_predicted.y", localPredictedForce.y);
                    Telemetry.Send("force_predicted.z", localPredictedForce.z);

                    Telemetry.Send("force_predicted_cache", localPredictedForceWithCache.magnitude);
                    //Telemetry.Send("force_predicted_cache.x", localPredictedForceWithCache.x);
                    //Telemetry.Send("force_predicted_cache.y", localPredictedForceWithCache.y);
                    //Telemetry.Send("force_predicted_cache.z", localPredictedForceWithCache.z);

                    //Telemetry.Send("force_reference", referenceForce.magnitude);
                    //Telemetry.Send("force_reference.x", referenceForce.x);
                    //Telemetry.Send("force_reference.y", referenceForce.y);
                    //Telemetry.Send("force_reference.z", referenceForce.z);

                    //Telemetry.Send("velocity.x", bodySpaceVelocity.x);
                    //Telemetry.Send("velocity.y", bodySpaceVelocity.y);
                    //Telemetry.Send("velocity.z", bodySpaceVelocity.z);

                    //Vector3d velocity_pos = (bodySpacePosition - PreviousFramePos) / dt;
                    //Telemetry.Send("velocity_pos.x", velocity_pos.x);
                    //Telemetry.Send("velocity_pos.y", velocity_pos.y);
                    //Telemetry.Send("velocity_pos.z", velocity_pos.z);

                    Telemetry.Send("drag", Trajectories.AttachedVessel.rootPart.rb.drag);

                    Telemetry.Send("density", Trajectories.AttachedVessel.atmDensity);
                    Telemetry.Send("density_calc", StockAeroUtil.GetDensity(altitudeAboveSea, body));
                    Telemetry.Send("density_calc_precise", StockAeroUtil.GetDensity(Trajectories.AttachedVessel.GetWorldPos3D(), body));

                    Telemetry.Send("temperature", Trajectories.AttachedVessel.atmosphericTemperature);
                    Telemetry.Send("temperature_calc", StockAeroUtil.GetTemperature(Trajectories.AttachedVessel.GetWorldPos3D(), body));
                }

                PreviousFrameVelocity = bodySpaceVelocity;
                PreviousFramePos      = bodySpacePosition;
                PreviousFrameTime     = now;
            }
        }
 protected override Vector3d ComputeForces_Model(Vector3d airVelocity, double altitude)
 {
     return((Vector3d)StockAeroUtil.SimAeroForce(vessel_, (Vector3)airVelocity, altitude));
 }
Example #11
0
        public void FixedUpdate()
        {
            if (HighLogic.LoadedScene != GameScenes.FLIGHT)
            {
                return;
            }

            double now = Planetarium.GetUniversalTime();
            double dt  = now - PreviousFrameTime;

            if (dt > 0.5 || dt < 0.0)
            {
                Vector3d bodySpacePosition = new Vector3d();
                Vector3d bodySpaceVelocity = new Vector3d();

                if (aerodynamicModel_ != null && vessel_ != null)
                {
                    CelestialBody body = vessel_.orbit.referenceBody;

                    bodySpacePosition = vessel_.GetWorldPos3D() - body.position;
                    bodySpaceVelocity = vessel_.obt_velocity;

                    double altitudeAboveSea = bodySpacePosition.magnitude - body.Radius;

                    Vector3d airVelocity = bodySpaceVelocity - body.getRFrmVel(body.position + bodySpacePosition);

                                        #if DEBUG_COMPARE_FORCES
                    double   R            = PreviousFramePos.magnitude;
                    Vector3d gravityForce = PreviousFramePos * (-body.gravParameter / (R * R * R) * vessel_.totalMass);

                    Quaternion inverseRotationFix = body.inverseRotation ? Quaternion.AngleAxis((float)(body.angularVelocity.magnitude / Math.PI * 180.0 * dt), Vector3.up) : Quaternion.identity;
                    Vector3d   TotalForce         = (bodySpaceVelocity - inverseRotationFix * PreviousFrameVelocity) * (vessel_.totalMass / dt);
                    TotalForce += bodySpaceVelocity * (dt * 0.000015);                     // numeric precision fix
                    Vector3d ActualForce = TotalForce - gravityForce;

                    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;
                    }

                    VesselAerodynamicModel.DebugParts = true;
                    Vector3d referenceForce = aerodynamicModel_.ComputeForces(20000, new Vector3d(0, 0, 1500), new Vector3d(0, 1, 0), 0);
                    VesselAerodynamicModel.DebugParts = false;

                    Vector3d predictedForce = aerodynamicModel_.ComputeForces(altitudeAboveSea, airVelocity, vesselUp, AoA);
                    //VesselAerodynamicModel.Verbose = true;
                    Vector3d predictedForceWithCache = aerodynamicModel_.GetForces(body, bodySpacePosition, airVelocity, AoA);
                    //VesselAerodynamicModel.Verbose = false;

                    Vector3d localTotalForce              = new Vector3d(Vector3d.Dot(TotalForce, vesselRight), Vector3d.Dot(TotalForce, vesselUp), Vector3d.Dot(TotalForce, vesselBackward));
                    Vector3d localActualForce             = new Vector3d(Vector3d.Dot(ActualForce, vesselRight), Vector3d.Dot(ActualForce, vesselUp), Vector3d.Dot(ActualForce, 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("actual/predict comparison", "air vel=" + Math.Floor(airVelocity.magnitude) + " ; AoA=" + (AoA * 180.0 / Math.PI));
                    //Util.PostSingleScreenMessage("total force", "actual total force=" + localTotalForce.ToString("0.000"));
                    Util.PostSingleScreenMessage("actual force", "actual force=" + localActualForce.ToString("0.000"));
                    Util.PostSingleScreenMessage("predicted force", "predicted force=" + localPredictedForce.ToString("0.000"));
                    Util.PostSingleScreenMessage("predict with cache", "predicted force with cache=" + localPredictedForceWithCache.ToString("0.000"));

                    Util.PostSingleScreenMessage("reference force", "reference force=" + referenceForce.ToString("0.000"));

                    Util.PostSingleScreenMessage("current vel", "current vel=" + bodySpaceVelocity.ToString("0.00") + " (mag=" + bodySpaceVelocity.magnitude.ToString("0.00") + ")");
                    //Util.PostSingleScreenMessage("vel from pos", "vel from pos=" + ((bodySpacePosition - PreviousFramePos) / dt).ToString("0.000") + " (mag=" + ((bodySpacePosition - PreviousFramePos) / dt).magnitude.ToString("0.00") + ")");
                    Util.PostSingleScreenMessage("force diff", "force ratio=" + (localActualForce.z / localPredictedForce.z).ToString("0.000"));
                    Util.PostSingleScreenMessage("drag", "physics drag=" + vessel_.rootPart.rb.drag);
                                        #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") + " ; " +*/ "rho=" + approximateRho.ToString("0.0000") + " ; actual=" + actualRho.ToString("0.0000") + " ; ratio=" + (actualRho / approximateRho).ToString("0.00"));
                }

                PreviousFrameVelocity = bodySpaceVelocity;
                PreviousFramePos      = bodySpacePosition;
                PreviousFrameTime     = now;
            }
        }
Example #12
0
        public Vector3d computeForces_StockAero(double altitude, Vector3d airVelocity, Vector3d vup, double angleOfAttack, double dt)
        {
            Transform vesselTransform = vessel_.ReferenceTransform;
            //TODO:  This is the same code as FAR call, so clearly it can be common in computeForces
            // this is weird, but the vessel orientation does not match the reference transform (up is forward), this code fixes it but I don't know if it'll work in all cases
            Vector3d vesselBackward = (Vector3d)(-vesselTransform.up.normalized);
            Vector3d vesselForward  = -vesselBackward;
            Vector3d vesselUp       = (Vector3d)(-vesselTransform.forward.normalized);
            Vector3d vesselRight    = Vector3d.Cross(vesselUp, vesselBackward).normalized;

            Vector3d airVelocityForFixedAoA = (vesselForward * Math.Cos(-angleOfAttack) + vesselUp * Math.Sin(-angleOfAttack)) * airVelocity.magnitude;

            if (altitude >= body_.atmosphereDepth)
            {
                return(Vector3d.zero);
            }

            Vector3 aero_force = StockAeroUtil.SimAeroForce(vessel_, (Vector3)airVelocityForFixedAoA, altitude);
            //Util.PostSingleScreenMessage("aeroforce", String.Format("aero_force = {0}",aero_force));

            Vector3d totalForce = (Vector3d)aero_force;

            if (Double.IsNaN(totalForce.x) || Double.IsNaN(totalForce.y) || Double.IsNaN(totalForce.z))
            {
                Debug.Log("Trajectories: WARNING: StockAero totalForce is NAN (altitude=" + altitude + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
                return(new Vector3d(0, 0, 0)); // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
            }

            // convert the force computed by FAR (depends on the current vessel orientation, which is irrelevant for the prediction) to the predicted vessel orientation (which depends on the predicted velocity)
            Vector3d localForce = new Vector3d(Vector3d.Dot(vesselRight, totalForce), Vector3d.Dot(vesselUp, totalForce), Vector3d.Dot(vesselBackward, totalForce));

            //if (Double.IsNaN(localForce.x) || Double.IsNaN(localForce.y) || Double.IsNaN(localForce.z))
            //    throw new Exception("localForce is NAN");

            Vector3d velForward  = airVelocity.normalized;
            Vector3d velBackward = -velForward;
            Vector3d velRight    = Vector3d.Cross(vup, velBackward);

            if (velRight.sqrMagnitude < 0.001)
            {
                velRight = Vector3d.Cross(vesselUp, velBackward);
                if (velRight.sqrMagnitude < 0.001)
                {
                    velRight = Vector3d.Cross(vesselBackward, velBackward).normalized;
                }
                else
                {
                    velRight = velRight.normalized;
                }
            }
            else
            {
                velRight = velRight.normalized;
            }
            Vector3d velUp = Vector3d.Cross(velBackward, velRight).normalized;

            Vector3d predictedVesselForward  = velForward * Math.Cos(angleOfAttack) + velUp * Math.Sin(angleOfAttack);
            Vector3d predictedVesselBackward = -predictedVesselForward;
            Vector3d predictedVesselRight    = velRight;
            Vector3d predictedVesselUp       = Vector3d.Cross(predictedVesselBackward, predictedVesselRight).normalized;

            Vector3d res = predictedVesselRight * localForce.x + predictedVesselUp * localForce.y + predictedVesselBackward * localForce.z;

            if (Double.IsNaN(res.x) || Double.IsNaN(res.y) || Double.IsNaN(res.z))
            {
                Debug.Log("Trajectories: res is NaN (altitude=" + altitude + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
                return(new Vector3d(0, 0, 0)); // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
            }
            return(res);
        }
 protected override Vector3d ComputeForces_Model(Vector3d airVelocity, double altitude)
 {
     return(StockAeroUtil.SimAeroForce(trajectory_.AttachedVessel, airVelocity, altitude));
 }