Ejemplo n.º 1
0
        public Point FlyAbovePoint(Vector3d pos)
        {
            if (Utils.ProjectionAngle(Orbit.getRelativePositionAtUT(StartUT), pos,
                                      Orbit.getOrbitalVelocityAtUT(StartUT)) < 0)
            {
                return(newP(StartUT));
            }
            if (!HavePoints ||
                Utils.ProjectionAngle(Orbit.getRelativePositionAtUT(AtmoStartUT),
                                      TrajectoryCalculator.BodyRotationAtdT(Orbit.referenceBody, AtmoStartUT - UT0) * pos,
                                      Orbit.getOrbitalVelocityAtUT(AtmoStartUT)) < 0)
            {
                return(newP(TrajectoryCalculator.FlyAboveUT(Orbit, pos, StartUT)));
            }
            var p0     = Points[0];
            var angle0 = Utils.ProjectionAngle(p0.pos,
                                               TrajectoryCalculator
                                               .BodyRotationAtdT(Orbit.referenceBody, p0.UT - UT0) * pos,
                                               p0.vel);

            for (int i = 1, count = Points.Count; i < count; i++)
            {
                var p1     = Points[i];
                var angle1 = Utils.ProjectionAngle(p1.pos,
                                                   TrajectoryCalculator
                                                   .BodyRotationAtdT(Orbit.referenceBody, p1.UT - UT0) * pos,
                                                   p1.vel);
                if (angle1 > 0)
                {
                    angle0 = angle1;
                    continue;
                }
                p0 = Points[i - 1];
                var p = p0;
                var t = angle0 / (angle0 - angle1);
                p.UT      += p0.Duration * t;
                p.Duration = p1.UT - p.UT;
                p.pos      = Vector3d.Lerp(p0.pos, p1.pos, t);
                p.Update();
                return(p);
            }
            return(LastPoint);
        }
 void update(bool with_brake)
 {
     update_from_orbit(Orbit, StartUT);
     //correct for brake maneuver
     if (with_brake)
     {
         BrakeEndUT    = AtTargetUT - GLB.LTRJ.CorrectionOffset;
         BrakeStartUT  = BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)AtTargetVel.magnitude, VSL, out BrakeDuration);
         brake_delta_v = -0.9 * Orbit.getOrbitalVelocityAtUT(BrakeEndUT);
         update_from_orbit(TrajectoryCalculator.NewOrbit(Orbit, BrakeDeltaV, BrakeEndUT), BrakeEndUT);
     }
     else
     {
         brake_delta_v = -(AtTargetVel + Vector3d.Cross(Body.zUpAngularVelocity, AtTargetPos));
         BrakeEndUT    = TrajectoryCalculator.FlyAboveUT(Orbit, Target.RelSurfPos(Body).xzy, StartUT);
         BrakeStartUT  = BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration);
     }
     //compute vessel coordinates at maneuver start
     if (VSL.LandedOrSplashed)
     {
         VslStartLat = Utils.ClampAngle(VSL.vessel.latitude);
         VslStartLon = Utils.ClampAngle(VSL.vessel.longitude);
     }
     else
     {
         var start_pos = (TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToStart) * StartPos).xzy + Body.position;
         VslStartLat = Utils.ClampAngle(Body.GetLatitude(start_pos));
         VslStartLon = Utils.ClampAngle(Body.GetLongitude(start_pos));
     }
     //compute distance to target
     DistanceToTarget = Target.AngleTo(SurfacePoint) * Body.Radius;
     BrakeEndDeltaAlt = Orbit.getRelativePositionAtUT(BrakeEndUT).magnitude - Body.Radius - TargetAltitude;
     //compute distance in lat-lon coordinates
     DeltaLat = Utils.AngleDelta(SurfacePoint.Pos.Lat, Target.Pos.Lat) *
                Math.Sign(Utils.AngleDelta(Utils.ClampAngle(VslStartLat), SurfacePoint.Pos.Lat));
     DeltaLon = Utils.AngleDelta(SurfacePoint.Pos.Lon, Target.Pos.Lon) *
                Math.Sign(Utils.AngleDelta(Utils.ClampAngle(VslStartLon), SurfacePoint.Pos.Lon));
     //compute distance in radial coordinates
     DeltaFi = 90 - Vector3d.Angle(Orbit.GetOrbitNormal(),
                                   TrajectoryCalculator.BodyRotationAtdT(Body, TimeToSurface) *
                                   Body.GetRelSurfacePosition(Target.Pos.Lat, Target.Pos.Lon, TargetAltitude).xzy);
     DeltaR = Utils.RadDelta(SurfacePoint.AngleTo(VslStartLat, VslStartLon), Target.AngleTo(VslStartLat, VslStartLon)) * Mathf.Rad2Deg;
 }
        void update(bool with_brake)
        {
            update_from_orbit(Orbit, StartUT);
            LandingAngle = 90 - Vector3d.Angle(AtTargetPos, -AtTargetVel);
            //correct for brake maneuver
            if (with_brake)
            {
                //estimate time needed to rotate the ship downwards
                var rotation_time = VSL.Torque.NoEngines?
                                    VSL.Torque.NoEngines.MinRotationTime(90) :
                                    VSL.Torque.MaxPossible.RotationTime(90, 0.1f);
                //estimate amount fuel needed for the maneuver
                var vertical_vel = Vector3d.Project(AtTargetVel, AtTargetPos);
                SetBrakeEndUT(Math.Max(AtTargetUT - GLB.LTRJ.CorrectionOffset + rotation_time, StartUT));
                SetBrakeDeltaV(vertical_vel);
                if (BrakeFuel > 0)
                {
                    //calculate braking maneuver
                    var dV = (float)BrakeDeltaV.magnitude;
                    BrakeDuration  = VSL.Engines.AntigravTTB(dV);
                    BrakeDuration += rotation_time;
                    //find the appropriate point to perform the maneuver
                    var    brake_end_UT   = Math.Max(AtTargetUT - Mathf.Max(GLB.LTRJ.CorrectionOffset, BrakeDuration * 1.1f), StartUT);
                    var    vertical_speed = vertical_vel.magnitude;
                    double fly_over_error;
                    do
                    {
                        SetBrakeEndUT(brake_end_UT);
                        fly_over_error = BrakeEndDeltaAlt - GLB.LTRJ.FlyOverAlt;
                        brake_end_UT  -= Math.Abs(fly_over_error / vertical_speed);
                    } while(brake_end_UT > StartUT && fly_over_error < -1);
                    SetBrakeDeltaV(-0.9 * Orbit.getOrbitalVelocityAtUT(BrakeEndUT));
                    //calculate maneuver start time and update landing site
                    BrakeStartUT = Math.Max(BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration), StartUT);
                    update_from_orbit(TrajectoryCalculator.NewOrbit(Orbit, BrakeDeltaV, BrakeEndUT), BrakeEndUT);
                }
                else
                {
                    BrakeStartUT  = BrakeEndUT;
                    BrakeDuration = 0;
                }
            }
            else
            {
                SetBrakeEndUT(TrajectoryCalculator.FlyAboveUT(Orbit, Target.RelOrbPos(Body), StartUT));
                SetBrakeDeltaV(-(AtTargetVel + Vector3d.Cross(Body.zUpAngularVelocity, AtTargetPos)));
                if (BrakeFuel > 0)
                {
                    var offset = MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration);
                    BrakeStartUT = Math.Max(BrakeEndUT - offset, StartUT);
                }
                else
                {
                    BrakeStartUT  = BrakeEndUT;
                    BrakeDuration = 0;
                }
            }
            BrakeOffset = (float)Utils.ClampL(BrakeEndUT - BrakeStartUT, 0);
            //compute vessel coordinates at maneuver start
            if (VSL.LandedOrSplashed)
            {
                VslStartLat = Utils.ClampAngle(VSL.vessel.latitude);
                VslStartLon = Utils.ClampAngle(VSL.vessel.longitude);
            }
            else
            {
                var start_pos = (TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToStart) * StartPos).xzy + Body.position;
                VslStartLat = Utils.ClampAngle(Body.GetLatitude(start_pos));
                VslStartLon = Utils.ClampAngle(Body.GetLongitude(start_pos));
            }
            //compute distance to target
            DistanceToTarget   = Target.AngleTo(SurfacePoint) * Body.Radius;
            SurfacePoint.Name += string.Format("\n{0} from target", Utils.formatBigValue((float)DistanceToTarget, "m"));
            //compute distance in lat-lon coordinates
            DeltaLat = Utils.AngleDelta(SurfacePoint.Pos.Lat, Target.Pos.Lat) *
                       Math.Sign(Utils.AngleDelta(approach.Lat, SurfacePoint.Pos.Lat));
            DeltaLon = Utils.AngleDelta(SurfacePoint.Pos.Lon, Target.Pos.Lon) *
                       Math.Sign(Utils.AngleDelta(approach.Lon, SurfacePoint.Pos.Lon));
            //compute distance in radial coordinates
            DeltaFi = 90 - Vector3d.Angle(Orbit.GetOrbitNormal(),
                                          TrajectoryCalculator.BodyRotationAtdT(Body, TimeToTarget) *
                                          Body.GetRelSurfacePosition(Target.Pos.Lat, Target.Pos.Lon, TargetAltitude).xzy);
            DeltaR = Utils.RadDelta(SurfacePoint.AngleTo(VslStartLat, VslStartLon), Target.AngleTo(VslStartLat, VslStartLon)) * Mathf.Rad2Deg;
//            Utils.Log("{}", this);//debug
        }