Example #1
0
        public static ManeuverParameters OptimizeEjection(ManeuverParameters original_maneuver, Orbit initial_orbit, Orbit target, double UT_arrival)
        {
            alglib.minlmstate  state;
            alglib.minlmreport rep;

            double[] x     = new double[4];
            double[] scale = new double[4];

            x[0] = original_maneuver.dV.x;
            x[1] = original_maneuver.dV.y;
            x[2] = original_maneuver.dV.z;
            x[3] = 0;

            scale[0] = scale[1] = scale[2] = original_maneuver.dV.magnitude;
            scale[3] = initial_orbit.period;

            OptimizerData data = new OptimizerData();

            data.initial_orbit = initial_orbit;
            data.original_UT   = original_maneuver.UT;
            data.UT_arrival    = UT_arrival;
            data.pos_arrival   = target.getTruePositionAtUT(UT_arrival);

            alglib.minlmcreatev(3, x, 0.01, out state);
            alglib.minlmsetcond(state, 0, 0, 0, 50);
            alglib.minlmsetscale(state, scale);
            alglib.minlmoptimize(state, DistanceToTarget, null, data);
            alglib.minlmresults(state, out x, out rep);

            return(new ManeuverParameters(new Vector3d(x[0], x[1], x[2]), original_maneuver.UT + x[3]));
        }
Example #2
0
        public static ManeuverParameters OptimizeEjection(ManeuverParameters original_maneuver, Orbit initial_orbit, Orbit target, double UT_arrival, double earliest_UT)
        {
            int N = 0;

            while (true)
            {
                alglib.minlmstate  state;
                alglib.minlmreport rep;

                double[] x     = new double[5];
                double[] scale = new double[5];

                x[0] = original_maneuver.dV.x;
                x[1] = original_maneuver.dV.y;
                x[2] = original_maneuver.dV.z;
                x[3] = original_maneuver.UT + N * initial_orbit.period;
                x[4] = UT_arrival;

                scale[0] = scale[1] = scale[2] = original_maneuver.dV.magnitude;
                scale[3] = initial_orbit.period;
                scale[4] = target.period / 4.0;

                OptimizerData data = new OptimizerData();
                data.initial_orbit = initial_orbit;
                data.target_orbit  = target;

                alglib.minlmcreatev(6, x, 0.001, out state);
                double epsx = 1e-16; // stop if |(x(k+1)-x(k)) ./ scale| <= EpsX
                double epsf = 1e-16; // stop if |F(k+1)-F(k)| <= EpsF*max{|F(k)|,|F(k+1)|,1}
                alglib.minlmsetcond(state, 0, epsf, epsx, 50);
                alglib.minlmsetscale(state, scale);
                alglib.minlmoptimize(state, DistanceToTarget, null, data);
                alglib.minlmresults(state, out x, out rep);

                Debug.Log("Transfer calculator: termination type=" + rep.terminationtype);
                Debug.Log("Transfer calculator: iteration count=" + rep.iterationscount);

                // try again in one orbit if the maneuver node is in the past
                if (x[3] < earliest_UT)
                {
                    Debug.Log("Transfer calculator: maneuver is " + (earliest_UT - x[3]) + " s too early, trying again in " + initial_orbit.period + " s");
                    N++;
                }
                else
                {
                    Debug.Log("from optimizer DV = " + Math.Sqrt(Math.Pow(x[0], 2.0) + Math.Pow(x[1], 2.0) + Math.Pow(x[2], 2.0)));
                    return(new ManeuverParameters(new Vector3d(x[0], x[1], x[2]), x[3]));
                }
            }
        }
Example #3
0
        public static ManeuverParameters OptimizeEjection(ManeuverParameters original_maneuver, Orbit initial_orbit, Orbit target, double UT_arrival, double earliest_UT)
        {
            while (true)
            {
                alglib.minlmstate  state;
                alglib.minlmreport rep;

                double[] x     = new double[4];
                double[] scale = new double[4];

                x[0] = original_maneuver.dV.x;
                x[1] = original_maneuver.dV.y;
                x[2] = original_maneuver.dV.z;
                x[3] = 0;

                scale[0] = scale[1] = scale[2] = original_maneuver.dV.magnitude;
                scale[3] = initial_orbit.period;

                OptimizerData data = new OptimizerData();
                data.initial_orbit = initial_orbit;
                data.original_UT   = original_maneuver.UT;
                data.UT_arrival    = UT_arrival;
                data.pos_arrival   = target.getTruePositionAtUT(UT_arrival);

                alglib.minlmcreatev(4, x, 0.01, out state);
                double epsx = 1e-4;                 // stop if |(x(k+1)-x(k)) ./ scale| <= EpsX
                double epsf = 0.01;                 // stop if |F(k+1)-F(k)| <= EpsF*max{|F(k)|,|F(k+1)|,1}
                alglib.minlmsetcond(state, 0, epsf, epsx, 50);
                alglib.minlmsetscale(state, scale);
                alglib.minlmoptimize(state, DistanceToTarget, null, data);
                alglib.minlmresults(state, out x, out rep);

                Debug.Log("Transfer calculator: termination type=" + rep.terminationtype);
                Debug.Log("Transfer calculator: iteration count=" + rep.iterationscount);

                // try again in one orbit if the maneuver node is in the past
                if (original_maneuver.UT + x[3] < earliest_UT)
                {
                    Debug.Log("Transfer calculator: maneuver is " + (earliest_UT - original_maneuver.UT - x[3]) + " s too early, trying again in " + initial_orbit.period + " s");
                    original_maneuver.UT += initial_orbit.period;
                }
                else
                {
                    return(new ManeuverParameters(new Vector3d(x[0], x[1], x[2]), original_maneuver.UT + x[3]));
                }
            }
        }
Example #4
0
        private void JobFinished()
        {
            int remaining = Interlocked.Decrement(ref pendingJobs);

            if (remaining == 0)
            {
                for (int date_index = 0; date_index < dateSamples; date_index++)
                {
                    int n = DurationSamplesForDate(date_index);
                    for (int duration_index = 0; duration_index < n; duration_index++)
                    {
                        if (computed[bestDate, bestDuration] == null ||
                            (computed[date_index, duration_index] != null &&
                             IsBetter(bestDate, bestDuration, date_index, duration_index)))
                        {
                            bestDate     = date_index;
                            bestDuration = duration_index;
                        }
                    }
                }

                arrivalDate = DateFromIndex(bestDate) + DurationFromIndex(bestDuration);
                result      = computed[bestDate, bestDuration];

                pendingJobs = -1;

#if DEBUG
                string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                var    f   = System.IO.File.CreateText(dir + "/DeltaVWorking.csv");
                f.WriteLine(originOrbit.referenceBody.referenceBody.gravParameter);
                for (int date_index = 0; date_index < dateSamples; date_index++)
                {
                    int n = DurationSamplesForDate(date_index);
                    for (int duration_index = 0; duration_index < n; duration_index++)
                    {
                        f.WriteLine(log[date_index, duration_index]);
                    }
                }
#endif
            }
        }
Example #5
0
        public List <ManeuverParameters> OptimizeEjection(double UT_transfer, Orbit initial_orbit, Orbit target, CelestialBody target_body, double UT_arrival, double earliest_UT, double target_PeR, bool includeCaptureBurn)
        {
            int N = 0;

            List <ManeuverParameters> NodeList = new List <ManeuverParameters>();

            while (true)
            {
                const double DIFFSTEP = 1e-6;
                const double EPSX     = 1e-9;
                const int    MAXITS   = 100;

                alglib.minlmstate  state;
                alglib.minlmreport rep;

                double[] x     = new double[3];
                double[] scale = new double[3];

                Vector3d exitDV, captureDV;
                CalcLambertDVs(UT_transfer, UT_arrival - UT_transfer, out exitDV, out captureDV);

                Orbit source = initial_orbit.referenceBody.orbit; // helicentric orbit of the source planet

                // helicentric transfer orbit
                Orbit transfer_orbit = new Orbit();
                transfer_orbit.UpdateFromStateVectors(source.getRelativePositionAtUT(UT_transfer), source.getOrbitalVelocityAtUT(UT_transfer) + exitDV, source.referenceBody, UT_transfer);

                double UT_SOI_exit;
                OrbitalManeuverCalculator.SOI_intercept(transfer_orbit, initial_orbit.referenceBody, UT_transfer, UT_arrival, out UT_SOI_exit);

                // convert from heliocentric to body centered velocity
                Vector3d Vsoi = transfer_orbit.getOrbitalVelocityAtUT(UT_SOI_exit) - initial_orbit.referenceBody.orbit.getOrbitalVelocityAtUT(UT_SOI_exit);

                // find the magnitude of Vinf from energy
                double Vsoi_mag = Vsoi.magnitude;
                double E_h      = Vsoi_mag * Vsoi_mag / 2 - initial_orbit.referenceBody.gravParameter / initial_orbit.referenceBody.sphereOfInfluence;
                double Vinf_mag = Math.Sqrt(2 * E_h);

                // scale Vsoi by the Vinf magnitude (this is now the Vinf target that will yield Vsoi at the SOI interface, but in the Vsoi direction)
                Vector3d Vinf = Vsoi / Vsoi.magnitude * Vinf_mag;

                // using Vsoi seems to work slightly better here than the Vinf from the heliocentric computation at UT_Transfer
                //ManeuverParameters maneuver = ComputeEjectionManeuver(Vsoi, initial_orbit, UT_transfer, true);
                ManeuverParameters maneuver = ComputeEjectionManeuver(Vinf, initial_orbit, UT_transfer, true);

                //
                // common setup for the optimization problems
                //

                x[0]        = maneuver.dV.x;
                x[1]        = maneuver.dV.y;
                x[2]        = maneuver.dV.z;
                UT_transfer = maneuver.UT;

                scale[0] = scale[1] = scale[2] = 1000.0f;

                //
                // initial patched conic shooting to precisely hit the target
                //

                const int ZEROMISSCONS = 3;
                double[]  fi           = new double[ZEROMISSCONS];

                zeroMissObjectiveFunction(x, fi, null, initial_orbit, target_body, UT_transfer, UT_arrival);
                Debug.Log("zero miss phase before optimization = " + new Vector3d(fi[0], fi[1], fi[2]).magnitude + " m (" + new Vector3d(x[0], x[1], x[2]).magnitude + " m/s)");

                alglib.minlmcreatev(3, ZEROMISSCONS, x, DIFFSTEP, out state);
                alglib.minlmsetcond(state, EPSX, MAXITS);
                alglib.minlmsetscale(state, scale);
                alglib.minlmoptimize(state, (x, fi, obj) => zeroMissObjectiveFunction(x, fi, obj, initial_orbit, target_body, UT_transfer, UT_arrival), null, null);
                alglib.minlmresults(state, out x, out rep);

                zeroMissObjectiveFunction(x, fi, null, initial_orbit, target_body, UT_transfer, UT_arrival);
                Debug.Log("zero miss phase after optimization = " + new Vector3d(fi[0], fi[1], fi[2]).magnitude + " m (" + new Vector3d(x[0], x[1], x[2]).magnitude + " m/s)");

                Debug.Log("Transfer calculator: termination type=" + rep.terminationtype);
                Debug.Log("Transfer calculator: iteration count=" + rep.iterationscount);

                //
                // Fine tuning of the periapsis
                //

                bool failed = false;

                if (target_PeR > 0)
                {
                    const int PERIAPSISCONS = 1;
                    double[]  fi2           = new double[PERIAPSISCONS];

                    periapsisObjectiveFunction(x, fi2, null, initial_orbit, target_body, UT_transfer, UT_arrival, target_PeR, ref failed);
                    Debug.Log("periapsis phase before optimization = " + fi2[0] + " m (" + new Vector3d(x[0], x[1], x[2]).magnitude + " m/s)");

                    alglib.minlmcreatev(3, PERIAPSISCONS, x, DIFFSTEP, out state);
                    alglib.minlmsetcond(state, EPSX, MAXITS);
                    alglib.minlmsetscale(state, scale);
                    alglib.minlmoptimize(state, (x, fi, obj) => periapsisObjectiveFunction(x, fi, obj, initial_orbit, target_body, UT_transfer, UT_arrival, target_PeR, ref failed), null, null);
                    alglib.minlmresults(state, out x, out rep);

                    periapsisObjectiveFunction(x, fi2, null, initial_orbit, target_body, UT_transfer, UT_arrival, target_PeR, ref failed);
                    Debug.Log("periapsis phase after optimization = " + fi2[0] + " m (" + new Vector3d(x[0], x[1], x[2]).magnitude + " m/s)");

                    Debug.Log("Transfer calculator: termination type=" + rep.terminationtype);
                    Debug.Log("Transfer calculator: iteration count=" + rep.iterationscount);
                }

                maneuver.dV.x = x[0];
                maneuver.dV.y = x[1];
                maneuver.dV.z = x[2];

                //
                // exit conditions and error handling
                //

                // try again if we failed to intersect the target orbit
                if (failed)
                {
                    Debug.Log("Failed to intersect target orbit");
                }
                // try again in one orbit if the maneuver node is in the past
                else if (maneuver.UT < earliest_UT || failed)
                {
                    Debug.Log("Transfer calculator: maneuver is " + (earliest_UT - maneuver.UT) + " s too early, trying again in " + initial_orbit.period + " s");
                    UT_transfer += initial_orbit.period;
                }
                else
                {
                    Debug.Log("from optimizer DV = " + maneuver.dV + " t = " + maneuver.UT + " original arrival = " + UT_arrival);
                    NodeList.Add(maneuver);
                    break;
                }
                if (N++ > 10)
                {
                    throw new OperationException("Ejection Optimization failed; try manual selection");
                }
            }
            if (NodeList.Count > 0 && target_PeR > 0 && includeCaptureBurn)
            {
                // calculate the incoming orbit
                Orbit incoming_orbit;
                OrbitalManeuverCalculator.PatchedConicInterceptBody(initial_orbit, target_body, NodeList[0].dV, NodeList[0].UT, UT_arrival, out incoming_orbit);
                double burnUT = incoming_orbit.NextPeriapsisTime(incoming_orbit.StartUT);
                NodeList.Add(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToCircularize(incoming_orbit, burnUT), burnUT));
            }
            return(NodeList);
        }
		public static ManeuverParameters OptimizeEjection(ManeuverParameters original_maneuver, Orbit initial_orbit, Orbit target, double UT_arrival, double earliest_UT)
		{
			while(true)
			{
				alglib.minlmstate state;
				alglib.minlmreport rep;

				double[] x = new double[4];
				double[] scale = new double[4];

				x[0] = original_maneuver.dV.x;
				x[1] = original_maneuver.dV.y;
				x[2] = original_maneuver.dV.z;
				x[3] = 0;

				scale[0] = scale[1] = scale[2] = original_maneuver.dV.magnitude;
				scale[3] = initial_orbit.period;

				OptimizerData data = new OptimizerData();
				data.initial_orbit = initial_orbit;
				data.original_UT = original_maneuver.UT;
				data.UT_arrival = UT_arrival;
				data.pos_arrival = target.getTruePositionAtUT(UT_arrival);

				alglib.minlmcreatev(4, x, 0.01, out state);
				double epsx = 1e-4; // stop if |(x(k+1)-x(k)) ./ scale| <= EpsX
				double epsf = 0.01; // stop if |F(k+1)-F(k)| <= EpsF*max{|F(k)|,|F(k+1)|,1}
				alglib.minlmsetcond(state, 0, epsf, epsx, 50);
				alglib.minlmsetscale(state, scale);
				alglib.minlmoptimize(state, DistanceToTarget, null, data);
				alglib.minlmresults(state, out x, out rep);

				Debug.Log("Transfer calculator: termination type=" + rep.terminationtype);
				Debug.Log("Transfer calculator: iteration count=" + rep.iterationscount);

				// try again in one orbit if the maneuver node is in the past
				if (original_maneuver.UT + x[3] < earliest_UT)
				{
					Debug.Log("Transfer calculator: maneuver is " + (earliest_UT - original_maneuver.UT - x[3]) + " s too early, trying again in " + initial_orbit.period + " s");
					original_maneuver.UT += initial_orbit.period;
				}
				else
					return new ManeuverParameters(new Vector3d(x[0], x[1], x[2]), original_maneuver.UT + x[3]);
			}
		}
		private void JobFinished()
		{
			int remaining = Interlocked.Decrement(ref pendingJobs);
			if (remaining == 0)
			{
				for (int date_index = 0; date_index < dateSamples; date_index++)
				{
					int n = DurationSamplesForDate(date_index);
					for (int duration_index = 0; duration_index < n; duration_index++)
					{
						if (computed[bestDate, bestDuration] == null ||
							(computed[date_index, duration_index] != null
								&& IsBetter(bestDate, bestDuration, date_index, duration_index)))
						{
							bestDate = date_index;
							bestDuration = duration_index;
						}
					}
				}

				arrivalDate = DateFromIndex(bestDate) + DurationFromIndex(bestDuration);
				result = computed[bestDate, bestDuration];

				pendingJobs = -1;

#if DEBUG
				string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
				var f = System.IO.File.CreateText(dir + "/DeltaVWorking.csv");
				f.WriteLine(originOrbit.referenceBody.referenceBody.gravParameter);
				for (int date_index = 0; date_index < dateSamples; date_index++)
				{
					int n = DurationSamplesForDate(date_index);
					for (int duration_index = 0; duration_index < n; duration_index++)
					{
						f.WriteLine(log[date_index, duration_index]);
					}
				}
#endif
			}
		}
Example #8
0
		public Porkchop(ManeuverParameters[,] nodes)
		{
			Gradient colours = new Gradient();
			var colourKeys = new GradientColorKey[6];
			colourKeys[0].color = new Color(0.25f, 0.25f, 1.0f);
			colourKeys[0].time = 0.0f;
			colourKeys[1].color = new Color(0.5f, 0.5f, 1.0f);
			colourKeys[1].time = 0.01f;
			colourKeys[2].color = new Color(0.5f, 1.0f, 1.0f);
			colourKeys[2].time = 0.25f;
			colourKeys[3].color = new Color(0.5f, 1.0f, 0.5f);
			colourKeys[3].time = 0.5f;
			colourKeys[4].color = new Color(1.0f, 1.0f, 0.5f);
			colourKeys[4].time = 0.75f;
			colourKeys[5].color = new Color(1.0f, 0.5f, 0.5f);
			colourKeys[5].time = 1.0f;

			var alphaKeys = new GradientAlphaKey[2];
			alphaKeys[0].alpha = 1.0f;
			alphaKeys[0].time = 0.0f;
			alphaKeys[1].alpha = 1.0f;
			alphaKeys[1].time = 1.0f;

			colours.SetKeys(colourKeys, alphaKeys);

			double DVminsqr = double.MaxValue;
			double DVmaxsqr = double.MinValue;
			for (int i = 0; i < nodes.GetLength(0); i++)
			{
				for (int j = 0; j < nodes.GetLength(1); j++)
				{
					if (nodes[i, j] != null)
					{
						double DVsqr = nodes[i, j].dV.sqrMagnitude;
						if (DVsqr < DVminsqr)
						{
							DVminsqr = DVsqr;
						}

						DVmaxsqr = Math.Max(DVmaxsqr, nodes[i, j].dV.sqrMagnitude);
					}
				}
			}

			texture = new Texture2D(nodes.GetLength(0), nodes.GetLength(1), TextureFormat.RGB24, false);
			double logDVminsqr = Math.Log(DVminsqr);
			double logDVmaxsqr = Math.Min(Math.Log(DVmaxsqr), logDVminsqr + 4);


			for (int i = 0; i < nodes.GetLength(0); i++)
			{
				for (int j = 0; j < nodes.GetLength(1); j++)
				{
					if (nodes[i, j] == null)
					{
						texture.SetPixel(i, j, colours.Evaluate(1));
					}
					else
					{
						double lambda = (Math.Log(nodes[i, j].dV.sqrMagnitude) - logDVminsqr) / (logDVmaxsqr - logDVminsqr);
						texture.SetPixel(i, j, colours.Evaluate((float)lambda));
					}
				}
			}

			texture.Apply();

#if DEBUG
			string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
			System.IO.File.WriteAllBytes(dir + "/Porkchop.png", texture.EncodeToPNG());
#endif
		}