Beispiel #1
0
            public Maneuver(System.DateTime date,
                            SatelliteMotion resulting_motion)
            {
                Date            = date;
                ResultingMotion = resulting_motion;

                WasExecuted = false;
            }
Beispiel #2
0
    public HohmannTransfer(SatelliteMotion original_motion,
                           SatelliteMotion target_motion,
                           System.DateTime earliest_departure_date)
        : base(original_motion, target_motion)
    {
        Debug.Assert(original_motion.Primary == target_motion.Primary);

        DepartureDate = GetLaunchWindow(earliest_departure_date);
    }
Beispiel #3
0
    public void ChangeMotion(SatelliteMotion motion)
    {
        Motion = motion;

        if (Primary != null &&
            transform.parent != Motion.Primary.SatellitesContainer)
        {
            transform.SetParent(Primary.SatellitesContainer);
        }
    }
Beispiel #4
0
    //How much additional mass is required to push craft_mass
    public float GetPropellentMassRequired(Navigation.Transfer.Maneuver maneuver,
                                           SatelliteMotion craft_motion,
                                           float craft_mass)
    {
        float payload_fraction = Mathf.Pow(
            (float)System.Math.E,
            -GetVelocityChangeRequired(maneuver, craft_motion) / ExhaustVelocity);

        return(craft_mass / (1 / (1 - payload_fraction) - 1));
    }
Beispiel #5
0
    public System.DateTime GetLaunchWindow(System.DateTime earliest_launch,
                                           int launch_window_skip_count = 0)
    {
        //Can't use .TransferMotion here because this method is
        //used to determine DepartureDate, which is required for
        //calculating .TransferMotion

        SatelliteMotion simple_transfer_motion =
            new SatelliteMotion(TargetMotion.Primary,
                                OriginalMotion.DistanceFromPrimary,
                                TargetMotion.DistanceFromPrimary,
                                0, 0);

        if (simple_transfer_motion.Periapsis > simple_transfer_motion.Apoapsis)
        {
            Utility.Swap(ref simple_transfer_motion.Periapsis,
                         ref simple_transfer_motion.Apoapsis);
        }

        float radial_launch_window =
            Mathf.PI -
            (2 * Mathf.PI) *
            (simple_transfer_motion.Period / 2) /
            TargetMotion.Period;

        float seconds_until_launch_window =
            (radial_launch_window -
             TargetMotion.TrueAnomalyAtDate(earliest_launch) +
             OriginalMotion.TrueAnomalyAtDate(earliest_launch)) /
            GetRelativeRadialVelocity();

        while (seconds_until_launch_window < 0)
        {
            seconds_until_launch_window += GetLaunchWindowPeriod();
        }

        System.DateTime launch_date =
            earliest_launch.AddSeconds(seconds_until_launch_window);

        launch_date.AddSeconds(GetLaunchWindowPeriod() * launch_window_skip_count);

        return(launch_date);
    }
    public InterplanetaryTransfer(SatelliteMotion original_motion,
                                  SatelliteMotion target_motion,
                                  System.DateTime earliest_launch_date)
        : base(original_motion, target_motion)
    {
        Satellite transfer_primary = null;

        foreach (SatelliteMotion octave in original_motion.Hierarchy)
        {
            if (target_motion.Hierarchy.Contains(octave.Primary.Motion))
            {
                transfer_primary = octave.Primary;
                break;
            }
        }
        Debug.Assert(transfer_primary != null);

        hohmann_transfer = new HohmannTransfer(
            OriginalMotion.Hierarchy.PreviousElement(transfer_primary.Motion),
            TargetMotion.Hierarchy.PreviousElement(transfer_primary.Motion),
            earliest_launch_date);
    }
Beispiel #7
0
 public Transfer(SatelliteMotion original_motion, SatelliteMotion target_motion)
 {
     OriginalMotion = original_motion;
     TargetMotion   = target_motion;
 }
Beispiel #8
0
    public float GetVelocityChangeRequired(Navigation.Transfer.Maneuver maneuver,
                                           SatelliteMotion craft_motion)
    {
        //If craft's primary does not change, just take the difference in
        //velocities between current and target motion at the date of the
        //maneuver

        if (maneuver.ResultingMotion.Primary == Craft.Primary)
        {
            return((maneuver.ResultingMotion.LocalVelocityAtDate(maneuver.Date) -
                    craft_motion.LocalVelocityAtDate(maneuver.Date))
                   .magnitude);
        }

        //In the more complex case of changing your orbit to another body,
        //this problem is solved by calculating total dV needed to escape n levels
        //(i.e. escaping lunar orbit to solar orbit is going down 2 levels) of
        //orbit and achieve the correct final relative velocity between craft
        //immediately before and after maneuver. Because of reversiblity of
        //orbits, the same dV is required for insertion (f.e. inserting into lunar
        //orbit from solar orbit) Therefore, I simply figure out which side would
        //be prior to escape ("innermost") and which would be after escape
        //("outermost"), and then solve the problem as an escape.

        SatelliteMotion innermost_motion = craft_motion,
                        outermost_motion = maneuver.ResultingMotion;

        if (maneuver.ResultingMotion.Primary.IsChildOf(craft_motion.Primary))
        {
            Utility.Swap(ref innermost_motion, ref outermost_motion);
        }

        Debug.Assert(
            maneuver.ResultingMotion.Primary.IsChildOf(craft_motion.Primary) ||
            craft_motion.Primary.IsChildOf(maneuver.ResultingMotion.Primary),
            "Cannot enter orbit around primary's cousin in a single step.");

        int imaginary_primary_index =
            innermost_motion.Hierarchy.IndexOf(outermost_motion.Primary.Motion) - 1;

        SatelliteMotion top_level_satellite =
            innermost_motion.Hierarchy[imaginary_primary_index];

        float top_level_velocity_change =
            (outermost_motion.LocalVelocityAtDate(maneuver.Date) -
             top_level_satellite.LocalVelocityAtDate(maneuver.Date)).magnitude;

        float current_level_velocity_change = top_level_velocity_change;

        float velocity_change = top_level_velocity_change;

        bool use_energy_based_solution = true;

        if (use_energy_based_solution)
        {
            //This solution simply sums the total potential energy gained
            //when escaping a planet/satellite and use it to calculate the
            //necessary periapsis velocity to escape with the correct amount
            //of kinetic energy.

            //The else case solves the same problem, but considers velocity directy
            //using formula v_infinity^2 = v_initial^2 - v_escape^2
            //I implemented both in order to confirm the results of the other.

            float potential_energy_sum = 0;

            foreach (SatelliteMotion motion in innermost_motion.Hierarchy)
            {
                if (motion == top_level_satellite)
                {
                    break;
                }

                potential_energy_sum +=
                    -MathConstants.GravitationalConstant *
                    motion.Primary.Mass /
                    motion.AltitudeAtDate(maneuver.Date);
            }

            velocity_change = Mathf.Abs(
                Mathf.Sqrt(2 * (Mathf.Pow(top_level_velocity_change, 2) / 2 -
                                potential_energy_sum)) -
                innermost_motion.LocalVelocityAtDate(maneuver.Date).magnitude);
        }
        else
        {
            //Solve the problem for each stage in the journey
            //F.e. First you must escape the Moon, then you must still have
            //enough speed to escape the Earth, and finally, you must still
            //have enough speed to enter the new orbit around the sun.

            //The problem is solved backwards. We start with the
            //"infinity velocity" you should have upon escaping earth. This
            //is difference between earth's velocity and the craft's velocity
            //after the maneuver. Using the infinity velocity and the escape
            //velocity of earth, we can calculate the dV required to reach
            //that speed, given altitude. Then, assuming we aren't done
            //(if the craft is directly orbiting the earth, rather than the
            //moon, we're done), we use that dV as the new infinity velocity,
            //in this case the velocity we should have upon escaping the moon.
            //In both examples, the altitude used for escape velocity is
            //derived from going one level down in the hierarchy; with earth
            //as the primary, we use the moon's altitude. With the moon, we
            //use the craft's altitude.

            while (imaginary_primary_index > 0)
            {
                SatelliteMotion imaginary_craft_motion =
                    innermost_motion.Hierarchy[imaginary_primary_index - 1];
                Satellite imaginary_primary = imaginary_craft_motion.Primary;

                float escape_velocity = Mathf.Sqrt(
                    2 * MathConstants.GravitationalConstant *
                    imaginary_primary.Mass /
                    imaginary_craft_motion.AltitudeAtDate(maneuver.Date));

                float infinity_velocity = current_level_velocity_change;

                float periapsis_velocity = Mathf.Sqrt(Mathf.Pow(infinity_velocity, 2) +
                                                      Mathf.Pow(escape_velocity, 2));
                current_level_velocity_change = periapsis_velocity;

                velocity_change = Mathf.Abs(
                    periapsis_velocity -
                    imaginary_craft_motion.LocalVelocityAtDate(maneuver.Date).magnitude);

                imaginary_primary_index--;
            }
        }

        return(velocity_change);
    }