示例#1
0
        private Vector3d CalculateImpactPositionWithAction()
        {
            var time_start = DateTime.Now;

            double   mass     = State.Vessel.Mass;
            double   dry_mass = State.Vessel.DryMass;
            Vector3d vel      = State.Vessel.Velocity;
            Vector3d pos      = State.Vessel.Position;
            double   altitude = pos.Length() - CommonData.Body.Radius;

            if (altitude <= TarAltitude)
            {
                return(pos);
            }

            double atm_depth      = CommonData.Body.AtmosphereDepth;
            bool   enter_atm      = false;
            double next_burn_time = -1d;

            double t              = 0d;
            double sim_lift_t     = 0d;
            double sim_lift_sum   = 0d;
            double sim_lift_min   = double.MaxValue;
            double sim_lift_max   = double.MinValue;
            double sim_thrust_sum = 0d;

            double drag_sum = 0d;
            double vel2_sum = 0d;

            while (t < 1000d)
            {
                double   atm = cache_.AtmAt(altitude);
                double   available_thrust = cache_.AvailableThrustAt(altitude);
                Vector3d g       = -pos * (CommonData.Body.GravitationalParameter / Math.Pow(CommonData.Body.Radius + altitude, 3));
                double   vel_mag = vel.Length();

                var sim_data = new SimulationData
                {
                    pos          = pos,
                    vel          = vel,
                    altitude     = altitude,
                    pressure     = atm,
                    g            = g.Length(),
                    mass         = mass,
                    tar_altitude = TarAltitude,
                    fuel_rate_at_full_throttle = State.Vessel.MaxFuelRate,
                    available_thrust           = available_thrust,
                    t = t
                };
                SimulationResult sim_res = mass > dry_mass?Planner(sim_data) : new SimulationResult();

                var thrust_acc = sim_res.Thrust / mass;

                double left_height = altitude - TarAltitude;
                double dt          = Math.Min(1d, Math.Max(0.1d, left_height / Math.Max(1d, vel_mag) / 2d)) * t_ratio_;
                if (sim_res.Throttle > 1e-3d && next_burn_time < 0d)
                {
                    next_burn_time = t;
                    NextBurnTime   = t;
                }

                // Lift estimation
                if (t < LiftEstimationTime)
                {
                    double sim_lift_mag = cache_.Lift(altitude, vel_mag);
                    sim_lift_t      = t + dt;
                    sim_lift_sum   += sim_lift_mag * dt;
                    sim_lift_min    = Math.Min(sim_lift_min, sim_lift_mag);
                    sim_lift_max    = Math.Max(sim_lift_max, sim_lift_mag);
                    sim_thrust_sum += sim_res.ThrustMag * dt;
                }

                double sim_drag_mag = cache_.Drift(altitude, vel_mag);
                drag_sum += sim_drag_mag * dt;
                vel2_sum += vel_mag * vel_mag * cache_.DensityAt(altitude) * dt;

                Vector3d sim_drag_acc = -sim_drag_mag / mass * vel.Norm();
                Vector3d acc          = thrust_acc + g + sim_drag_acc;

                //if (ut_before_calc_ - last_print_ut_ >= 1d)
                //    sw_.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}",
                //        ut_before_calc_,
                //        vel,
                //        pos,
                //        sim_res.Throttle,
                //        mass,
                //        sim_data.available_thrust,
                //        g.Length(),
                //        sim_drag_mag,
                //        t);

                t   += dt;
                vel += acc * dt;
                Vector3d pos_last      = pos;
                double   altitude_last = altitude;
                pos  += vel * dt;
                mass -= State.Vessel.MaxFuelRate * sim_res.Throttle * dt;

                altitude = pos.Length() - CommonData.Body.Radius;
                if (CommonData.Body.HasAtmosphere)
                {
                    if (!enter_atm && altitude <= atm_depth && altitude_last >= atm_depth)
                    {
                        enter_atm = true;
                        EnterAtmosphereDirection = -vel.Norm();
                    }
                }
                else
                {
                    if (!enter_atm && next_burn_time < 0.5d)
                    {
                        enter_atm = true;
                        EnterAtmosphereDirection = -vel.Norm();
                    }
                }
                if (altitude <= TarAltitude)
                {
                    double ratio = MathLib.InverseLerp(altitude_last, altitude, TarAltitude);
                    pos = MathLib.Lerp(pos_last, pos, ratio);
                    break;
                }
            }
            last_print_ut_ = (ulong)ut_before_calc_;

            ImpactTime              = t;
            LiftEstimationForceAve  = sim_lift_t > 1e-3d ? sim_lift_sum / sim_lift_t : 0d;
            LiftEstimationForceMin  = sim_lift_min;
            LiftEstimationThrustAve = sim_thrust_sum / sim_lift_t;

            drag_ratio_ = drag_sum == 0d ? 0d : drag_sum / vel2_sum;

            var time_used = (DateTime.Now - time_start).TotalMilliseconds;

            t_ave_       = Math.Max(time_used, 1d);
            t_ratio_    *= (t_ave_ / 100d - 1d) * 0.2d + 1d;
            t_ratio_     = Math.Clamp(t_ratio_, 0.01d, 100d);
            ResultStable = t_ratio_ < 1d;

            return(pos);
        }