public void HyperOmegaLNoInclNoPhase() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitPeri = 15f; GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.ecc = 1.4f; orbitHyper.perihelion = orbitPeri; orbitHyper.r_initial = orbitPeri; // Try some values of om float[] omegaValues = { 30f, 45f, 60f, 90f, 135f, 180f, 0f }; foreach (float omega in omegaValues) { orbitHyper.omega_lc = omega; orbitHyper.Init(); orbitHyper.InitNBody(1f, 1f); orbitHyper.Log(System.Reflection.MethodBase.GetCurrentMethod().Name); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("omega = " + omega + " od.omega_l=" + od.omega_lc); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqual(omega, od.omega_lc, 0.05)); TestRV(od, planet, star); } }
/// <summary> /// Raise a circular orbit by the specified percent /// - only on-rail is implemented /// </summary> /// <param name="percentRaise"></param> private void NewCircularOrbit(float percentRaise) { if (onRails) { KeplerSequence keplerSeq = spaceship.GetComponent <KeplerSequence>(); OrbitUniversal orbitU = keplerSeq.GetCurrentOrbit(); // check orbit is circular if (orbitU.eccentricity < 1E-2) { // circular, ok to proceed OrbitData fromOrbit = new OrbitData(orbitU); OrbitData toOrbit = new OrbitData(fromOrbit); toOrbit.a = percentRaise * fromOrbit.a; const bool rendezvous = false; OrbitTransfer hohmannXfer = new HohmannXfer(fromOrbit, toOrbit, rendezvous); keplerSeq.RemoveFutureSegments(); keplerSeq.AddManeuvers(hohmannXfer.GetManeuvers()); } } else { // assume we're in orbit around the moon OrbitData orbitData = new OrbitData(); orbitData.SetOrbitForVelocity(spaceship, moonBody); OrbitData toOrbit = new OrbitData(orbitData); toOrbit.a = percentRaise * orbitData.a; const bool rendezvous = false; OrbitTransfer hohmannXfer = new HohmannXfer(orbitData, toOrbit, rendezvous); ge.AddManeuvers(hohmannXfer.GetManeuvers()); } }
public void HyperOmegaUInclNoPhase() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.ecc = 1.4f; orbitHyper.perihelion = 20f; orbitHyper.r_initial = 20f; orbitHyper.inclination = 35f; // Try some values of om float[] omegaValues = { 30f, 45f, 60f, 90f, 135f, 180f, 210f, 275f, 355f }; foreach (float omega in omegaValues) { orbitHyper.omega_uc = omega; TestSetupUtils.SetupGravityEngine(star, planet); orbitHyper.Log(System.Reflection.MethodBase.GetCurrentMethod().Name); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("omega = " + omega + " od.omega_uc=" + od.omega_uc); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqualMod360(omega, od.omega_uc, 0.05)); } }
// Update is called once per frame void Update() { if (xferRequested) { return; } if (Input.GetKeyUp(KeyCode.T)) { OrbitData od1 = new OrbitData(); od1.SetOrbitForVelocity(orbit1, centerBody); OrbitData od2 = new OrbitData(); od2.SetOrbitForVelocity(orbit2, centerBody); OrbitTransfer transfer = new CircularInclinationAndAN(od1, od2); // Update for as many markers as provided List <Maneuver> maneuvers = transfer.GetManeuvers(); for (int i = 0; i < commonPointMarker.Length; i++) { commonPointMarker[i].transform.position = maneuvers[i].physPosition.ToVector3(); } GravityEngine.instance.AddManeuvers(transfer.GetManeuvers()); xferRequested = true; } }
public void PhaseRetrogradeEllipse() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.ecc = 0.4f; orbitEllipse.inclination = 180f; // Try some values of om float[] phaseValues = { 30f, 45f, 60f, 90f, 135f, 180f, 0f }; foreach (float phase in phaseValues) { orbitEllipse.phase = phase; orbitEllipse.Init(); orbitEllipse.ApplyScale(1f); orbitEllipse.InitNBody(1f, 1f); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("phase = " + phase + " od.phase=" + od.phase); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqual(phase, od.phase, 0.02)); TestRV(od, planet, star, orbitRadius); } }
// Update is called once per frame void Update() { if (Input.GetKeyUp(KeyCode.C)) { OrbitData currentOrbit = new OrbitData(); currentOrbit.SetOrbitForVelocity(shipNbody, centerNbody); // circularize the orbit OrbitTransfer t = new CircularizeXfer(currentOrbit); // If this is a ship with a Kepler sequence take the maneuvers and add them as KeplerSequence elements // This allows the transfer to be time-reversible if the whole scene is on rails. if (keplerSeq != null) { keplerSeq.AddManeuvers(t.GetManeuvers()); } else { // Nbody evolution (or plain onRails w/o KeplerSequence) use maneuvers GravityEngine.Instance().AddManeuver(t.GetManeuvers()[0]); } } else if (Input.GetKeyDown(KeyCode.R)) { // return orbit to GravityEngine control (go Off-Rails) if (keplerSeq != null) { keplerSeq.AppendReturnToGE(GravityEngine.Instance().GetPhysicalTime(), shipNbody); } } else if (Input.GetKeyDown(KeyCode.W)) { // return orbit to GravityEngine control (go Off-Rails) GravityEngine.Instance().ApplyImpulse(shipNbody, Vector3.up); } }
public void HyperInclOmega() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.r_initial = 20f; orbitHyper.ecc = 2.5f; // Try some values of phase float[] inclinationValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f }; float[] omegaUValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float incl in inclinationValues) { foreach (float omegau in omegaUValues) { orbitHyper.inclination = incl; orbitHyper.omega_uc = omegau; orbitHyper.Init(); orbitHyper.InitNBody(1f, 1f); orbitHyper.Log("Initial circle:"); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("incl = " + incl + " od.incl=" + od.inclination); Debug.Log("omegaU = " + omegau + " od.omegau=" + od.omega_uc); TestRV(od, planet, star); } } }
public void HyperInclination() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.ecc = 1.4f; orbitHyper.r_initial = 20f; // Try some values of om float[] inclValues = { 30f, 45f, 60f, 90f, 135f, 180f, 0f }; foreach (float incl in inclValues) { orbitHyper.inclination = incl; TestSetupUtils.SetupGravityEngine(star, planet); orbitHyper.Log(System.Reflection.MethodBase.GetCurrentMethod().Name); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("incl = " + incl + " od.incl=" + od.inclination); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqual(incl, od.inclination, 0.02)); } }
public void HyperPhaseNoIncl() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitPeri = 15f; GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.ecc = 1.4f; orbitHyper.perihelion = orbitPeri; orbitHyper.r_initial = orbitPeri; // Try some values of om float[] rinit_values = { orbitPeri, orbitPeri + 2f, orbitPeri + 5f, orbitPeri + 10f, orbitPeri + 20f }; foreach (float rinit in rinit_values) { orbitHyper.r_initial = rinit; TestSetupUtils.SetupGravityEngine(star, planet); orbitHyper.Log(System.Reflection.MethodBase.GetCurrentMethod().Name); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("rinit = " + rinit + " od.r_initial=" + od.r_initial); // Need a bit of leeway at 0 with error TestRV(od, planet, star); } }
public void OmegaUCircleInclination() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); NBody starNbody = star.GetComponent <NBody>(); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbitUniversal(starNbody, 1f, orbitRadius); OrbitUniversal orbitU = planet.GetComponent <OrbitUniversal>(); orbitU.eccentricity = 0.0f; orbitU.inclination = 5; orbitU.SetMajorAxisInspector(orbitRadius); // Try some values of om float[] omegaValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float omega in omegaValues) { orbitU.omega_uc = omega; TestSetupUtils.SetupGravityEngine(star, planet); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("Omega = " + omega + " od.omega_lc=" + od.omega_lc + " od:" + od.LogString()); Assert.IsTrue(GEUnit.FloatEqual(omega, od.omega_uc, 0.1)); } }
public void OmegasEllipseInclination() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.InitNBody(1f, 1f); orbitEllipse.inclination = 35f; orbitEllipse.ecc = 0.25f; orbitEllipse.Init(); orbitEllipse.ApplyScale(1f); orbitEllipse.InitNBody(1f, 1f); // Try some values of om float[] omegaValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f }; foreach (float omega in omegaValues) { orbitEllipse.omega_uc = omega; orbitEllipse.Init(); orbitEllipse.InitNBody(1f, 1f); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); TestRV(od, planet, star, orbitRadius); } }
public void OmegaULEllipseInclined() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.InitNBody(1f, 1f); orbitEllipse.inclination = 30f; orbitEllipse.ecc = 0.2f; orbitEllipse.Init(); orbitEllipse.ApplyScale(1f); orbitEllipse.InitNBody(1f, 1f); // Try some values of om float[] omegaUValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 310f }; float[] omegaLValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 310f }; foreach (float omegaU in omegaUValues) { foreach (float omegaL in omegaLValues) { orbitEllipse.omega_uc = omegaU; orbitEllipse.omega_lc = omegaL; TestSetupUtils.SetupGravityEngine(star, planet); orbitEllipse.Log("OmegaUL inclined:"); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("omegaU = " + omegaU + "omegaL = " + omegaL + " OD:=" + od.LogString()); TestRV(od, planet, star, orbitRadius); } } }
// Update is called once per frame void Update() { if (Input.GetKeyUp(KeyCode.H)) { OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbitForVelocity(shipNbody, centerNbody); OrbitData targetOrbit = new OrbitData(); targetOrbit.SetOrbitForVelocity(targetNbody, centerNbody); // determine the transfer orbitTransfer = new HohmannXfer(shipOrbit, targetOrbit, rendezvous); // If this is a ship with a Kepler sequence take the maneuvers and add them as KeplerSequence elements // This allows the transfer to be time-reversible if the whole scene is on rails. if (keplerSeq != null) { keplerSeq.AddManeuvers(orbitTransfer.GetManeuvers()); } else { // Nbody evolution (or plain onRails w/o KeplerSequence) use maneuvers foreach (Maneuver m in orbitTransfer.GetManeuvers()) { GravityEngine.Instance().AddManeuver(m); } } // Maneuver markers if (markerPrefab != null) { foreach (Maneuver m in orbitTransfer.GetManeuvers()) { // set maneuver position marker GameObject marker = Instantiate(markerPrefab, centerNbody.gameObject.transform, true); marker.transform.position = m.physPosition.ToVector3(); markers.Add(marker); m.onExecuted = RemoveMarker; } } } if (Input.GetKeyUp(KeyCode.C)) { // clear maneuvers GravityEngine.Instance().ClearManeuvers(); // delete on rails maneuvers if (keplerSeq != null) { keplerSeq.RemoveManeuvers(orbitTransfer.GetManeuvers()); } foreach (GameObject marker in markers) { Destroy(marker); } markers.Clear(); } // optionally report time to next maneuver // for now just do first maneuver if ((timeToManeuverText != null) && (orbitTransfer != null)) { double time = orbitTransfer.GetManeuvers()[0].worldTime - GravityEngine.Instance().GetPhysicalTime(); timeToManeuverText.text = string.Format("Time to Next Maneuver = {0:0.00}", time); } }
public void CirclePhaseOmegaInclined() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.inclination = 20f; // Try some values of phase // omegaU for a circle does not make sense, no axis to relate it to. float[] phaseValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float phase in phaseValues) { orbitEllipse.phase = phase; orbitEllipse.omega_uc = 0; TestSetupUtils.SetupGravityEngine(star, planet); Debug.LogFormat("Test for phase={0} omegau={1}", phase, 0); orbitEllipse.Log("Initial circle:"); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("OrbitData: " + od.LogString()); Assert.IsTrue(FloatEqualMod360(phase, od.phase, 0.05)); Assert.IsTrue(FloatEqualMod360(0, od.omega_uc, 0.05)); TestRV(od, planet, star, orbitRadius); } }
public void PhaseNoInclinationEllipse() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 20f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.ecc = 0.2f; // Try some values of om float[] phaseValues = { 30f, 45f, 60f, 90f, 135f, 180f, 225f, 270f, 325f, 0f }; foreach (float phase in phaseValues) { orbitEllipse.phase = phase; TestSetupUtils.SetupGravityEngine(star, planet); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); orbitEllipse.Log("PhaseNoInclinationEllipse:"); Debug.Log(od.LogString()); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqualMod360(phase, od.phase, 0.02)); Assert.IsTrue(FloatEqualMod360(0f, od.omega_lc, 0.02)); Assert.IsTrue(FloatEqualMod360(0f, od.omega_uc, 0.02)); TestRV(od, planet, star, orbitRadius); } }
// Check eccentricity and inclination public void EllipseInclination() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); float eccentricity = 0.3f; orbitEllipse.ecc = eccentricity; TestSetupUtils.SetupGravityEngine(star, planet); // take the velocity and check OrbitData orbitData = new OrbitData(); orbitData.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Assert.IsTrue(FloatEqual(orbitRadius, orbitData.a)); Assert.IsTrue(FloatEqual(eccentricity, orbitData.ecc)); // Try some values of inclination float[] inclinationValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f }; foreach (float inc in inclinationValues) { Debug.Log("====EclipseInclination==== inc=" + inc); orbitEllipse.inclination = inc; TestSetupUtils.SetupGravityEngine(star, planet); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("TEST: incl = " + orbitEllipse.inclination + " ecc=" + orbitEllipse.ecc + " od:" + od.LogString()); Assert.IsTrue(FloatEqual(inc, od.inclination)); TestRV(od, planet, star, orbitRadius); } }
public void CirclePhaseOmegaInclined() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.inclination = 20f; // Try some values of phase float[] phaseValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; float[] omegaUValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float phase in phaseValues) { foreach (float omegau in omegaUValues) { orbitEllipse.phase = phase; orbitEllipse.omega_uc = omegau; orbitEllipse.Init(); orbitEllipse.ApplyScale(1f); orbitEllipse.InitNBody(1f, 1f); orbitEllipse.Log("Initial circle:"); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("TEST: phase = " + phase + " od.phase=" + od.phase + " omegaU = " + omegau + " od.omegau=" + od.omega_uc); TestRV(od, planet, star, orbitRadius); } } }
/// <summary> /// Circularize around Moon /// - currently only onRails is implemented /// </summary> private void CircularizeAroundMoon() { // check ship is on segment where it near Moon if (onRails) { KeplerSequence keplerSeq = spaceship.GetComponent <KeplerSequence>(); OrbitUniversal orbitU = keplerSeq.GetCurrentOrbit(); if (orbitU.centerNbody == moonBody) { // in orbit around the moon - do circularization OrbitData orbitData = new OrbitData(orbitU); OrbitTransfer circularizeXfer = new CircularizeXfer(orbitData); keplerSeq.RemoveFutureSegments(); keplerSeq.AddManeuvers(circularizeXfer.GetManeuvers()); } } else { // assume we're in orbit around the moon OrbitData orbitData = new OrbitData(); orbitData.SetOrbitForVelocity(spaceship, moonBody); OrbitTransfer circularizeXfer = new CircularizeXfer(orbitData); ge.AddManeuvers(circularizeXfer.GetManeuvers()); } }
public void OmegaUNoInclination() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse orbitEllipse = planet.GetComponent <OrbitEllipse>(); orbitEllipse.InitNBody(1f, 1f); orbitEllipse.ecc = 0.1f; // Try some values of om float[] omegaValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float omega in omegaValues) { orbitEllipse.omega_uc = omega; orbitEllipse.Init(); orbitEllipse.ApplyScale(1f); orbitEllipse.InitNBody(1f, 1f); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("omega = " + omega + " od.omega_lc=" + od.omega_lc); Assert.IsTrue(FloatEqual(omega, od.omega_lc, 0.4)); } }
private void ComputeTransfer() { shipData = new OrbitData(); shipData.centralMass = starNBody; shipData.SetOrbitForVelocity(spaceshipNBody, starNBody); targetData = new OrbitData(targetEllipses[selectedEllipse].orbitData); targetData.phase = targetEllipses[selectedEllipse].manueverPhase; // compute the min energy path (this will be in the short path direction) lambertU = new LambertUniversal(shipData, targetData, shortPath); // apply any time of flight change transferTime = tflightFactor * lambertU.GetTMin(); bool reverse = !shortPath; // recompute with updated time const bool df = false; const int nrev = 0; int error = lambertU.ComputeXfer(reverse, df, nrev, transferTime); if (error != 0) { Debug.LogWarning("Lambert failed to find solution."); maneuverSegment.gameObject.SetActive(false); return; } Vector3 vel = lambertU.GetTransferVelocity(); maneuverOrbitPredictor.SetVelocity(vel); maneuverSegment.SetVelocity(vel); maneuverOrbitPredictor.gameObject.SetActive(true); maneuverSegment.gameObject.SetActive(true); }
private void ComputeTransfer() { Vector3d r_from = GravityEngine.Instance().GetPositionDoubleV3(spaceship); Vector3d r_to = new Vector3d(targetPoint.transform.position); OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbitForVelocity(spaceship, centralMass); // compute the min energy path (this will be in the short path direction) lambertU = new LambertUniversal(shipOrbit, r_from, r_to, shortPath); // apply any time of flight change double t_flight = tflightFactor * lambertU.GetTMin(); bool reverse = !shortPath; const bool df = false; const int nrev = 0; int error = lambertU.ComputeXfer(reverse, df, nrev, t_flight); if (error != 0) { Debug.LogWarning("Lambert failed to find solution."); maneuverSegment.gameObject.SetActive(false); return; } Vector3 dv = lambertU.GetTransferVelocity() - GravityEngine.Instance().GetVelocity(spaceship); dvText.text = string.Format("dV = {0:00.00} Time={1:00.00}", dv.magnitude, t_flight); maneuverOrbitPredictor.SetVelocity(lambertU.GetTransferVelocity()); maneuverSegment.gameObject.SetActive(true); maneuverSegment.SetDestination(r_to.ToVector3()); maneuverSegment.SetVelocity(lambertU.GetTransferVelocity()); }
public OrbitTransfer Circularize() { OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbitForVelocity(ship, centralMass); return(new CircularizeXfer(shipOrbit)); }
// Create an NBody and check it's mass public void CircleA() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); // confirm planet is in correct location Assert.AreEqual(Vector3.Distance(planet.transform.position, new Vector3(10f, 0f, 0)), 0); // take the velocity and check OrbitData orbitData = new OrbitData(); orbitData.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Assert.AreEqual(orbitData.a, orbitRadius); Assert.AreEqual(orbitData.omega_uc, 0f); }
// Update is called once per frame void Update() { if (Input.GetKey(KeyCode.A)) { fromPhase += PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.S)) { fromPhase -= PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.Q)) { toPhase += PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.W)) { toPhase -= PHASE_PER_KEY; } fromPhase = NUtils.DegreesMod360(fromPhase); toPhase = NUtils.DegreesMod360(toPhase); SetMarkers(); shipOrbitData.SetOrbitForVelocity(spaceshipNBody, shipOrbit.centerNbody); // Determine TOF Vector3d from = new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(fromPhase)); Vector3d to = new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(toPhase)); Vector3d shipPos = GravityEngine.instance.GetPositionDoubleV3(spaceshipNBody); double tPeri = shipOrbit.TimeOfFlight(shipPos, new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(0f))); double tApo = shipOrbit.TimeOfFlight(shipPos, new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(180f))); double tof = shipOrbit.TimeOfFlight(from, to); // Scale to game time //tApo = GravityScaler.ScaleToGameSeconds((float) tApo); //tPeri = GravityScaler.ScaleToGameSeconds((float)tPeri); //tof = GravityScaler.ScaleToGameSeconds((float)tof); //tofText.text = string.Format("Time of Flight = {0:#.#}\nTime to Apoapsis = {1:#.#}\nTime to Periapsis = {2:#.#}\ntau = {3}", // tof, tApo, tPeri, shipOrbitData.tau); GravityScaler.Units units = GravityEngine.instance.units; tofText.text = string.Format("Time of Flight = {0}\nTime to Apoapsis = {1}\nTime to Periapsis = {2}\ntau = {3}", GravityScaler.GetWorldTimeFormatted(tof, units), GravityScaler.GetWorldTimeFormatted(tApo, units), GravityScaler.GetWorldTimeFormatted(tPeri, units), GravityScaler.GetWorldTimeFormatted(shipOrbitData.tau, units)); }
// Check eccentricity and inclination public void EccentricityInclTest() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); NBody starNbody = star.GetComponent <NBody>(); const float orbitRadius = 10f; GameObject planet = TestSetupUtils.CreatePlanetInOrbitUniversal(starNbody, 1f, orbitRadius); OrbitUniversal orbitU = planet.GetComponent <OrbitUniversal>(); float eccentricity = 0.3f; // MUST reset the scale after ecc is changed, since -> p orbitU.eccentricity = eccentricity; orbitU.SetMajorAxisInspector(orbitRadius); TestSetupUtils.SetupGravityEngine(star, planet); // Try some values of inclination and ecc float[] eccValues = { 0f, .1f, .2f, 0.5f, 0.9f }; float[] inclinationValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f }; foreach (float inc in inclinationValues) { foreach (float ecc in eccValues) { Debug.Log("====EccentricityInclTest==== ecc=" + ecc + " incl = " + inc); orbitU.inclination = inc; orbitU.eccentricity = ecc; orbitU.SetMajorAxisInspector(orbitRadius); // can only use for ellipses TestSetupUtils.SetupGravityEngine(star, planet); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), starNbody); Debug.Log("TEST: incl = " + orbitU.inclination + " ecc=" + orbitU.eccentricity + " od:" + od.LogString()); Debug.LogFormat("Check ecc: {0} vs {1}", ecc, od.ecc); Assert.IsTrue(GEUnit.FloatEqual(ecc, od.ecc, 1E-3)); float axis = (float)orbitU.GetMajorAxisInspector(); Debug.LogFormat("Check axis: {0} vs {1}", axis, od.a); Assert.IsTrue(GEUnit.FloatEqual(axis, od.a, 1E-3)); Debug.LogFormat("Check incl: {0} vs {1}", inc, od.inclination); Assert.IsTrue(GEUnit.FloatEqual(inc, od.inclination, 1E-3)); // TestRV(od, planet, starNbody, orbitRadius); } } }
public void HyperBasic() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); // Try some values of om float[] eccValues = { 1.1f, 1.3f, 2f, 2.2f, 3f, 10f }; foreach (float ecc in eccValues) { orbitHyper.ecc = ecc; orbitHyper.Init(); orbitHyper.InitNBody(1f, 1f); orbitHyper.Log(System.Reflection.MethodBase.GetCurrentMethod().Name); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("ecc = " + ecc + " od.ecc=" + od.ecc); // Need a bit of leeway at 0 with error Assert.IsTrue(FloatEqual(ecc, od.ecc, 0.02)); } }
public void HyperInclOmega() { const float mass = 1000f; GameObject star = TestSetupUtils.CreateNBody(mass, new Vector3(0, 0, 0)); GameObject planet = TestSetupUtils.CreatePlanetInHyper(star, 1f); OrbitHyper orbitHyper = planet.GetComponent <OrbitHyper>(); orbitHyper.r_initial = 20f; orbitHyper.ecc = 2.5f; // Try some values of phase (incl=0 covered by another test) float[] inclinationValues = { 30f, 45f, 60f, 90f, 135f, 180f }; float[] omegaUValues = { 0f, 30f, 45f, 60f, 90f, 135f, 180f, 210f, 320f }; foreach (float incl in inclinationValues) { foreach (float omegau in omegaUValues) { orbitHyper.inclination = incl; orbitHyper.omega_uc = omegau; TestSetupUtils.SetupGravityEngine(star, planet); Debug.LogFormat("Test for i={0} omegaU={1}", incl, omegau); orbitHyper.Log("Initial circle:"); OrbitData od = new OrbitData(); od.SetOrbitForVelocity(planet.GetComponent <NBody>(), star.GetComponent <NBody>()); Debug.Log("OrbitData: " + od.LogString()); TestRV(od, planet, star); Debug.Log("incl = " + incl + " od.incl=" + od.inclination); Debug.Log("omegaU = " + omegau + " od.omegau=" + od.omega_uc + " od.omega_lc=" + od.omega_lc); if (incl != 180f) { // 180 comes back as omegaL = omegaU = 180, but TestRV is ok Assert.IsTrue(FloatEqual(incl, od.inclination, 0.02)); Assert.IsTrue(FloatEqualMod360(omegau, od.omega_uc, 0.02)); } } } }
// Update is called once per frame void Update() { if (initOk) { // velocities not normally updated in NBody (to reduce CPU). Need to ask // object to update its velocity from Gravity Engine if engine is running if (GravityEngine.instance.GetEvolve()) { nbody.UpdateVelocity(); } orbitData.SetOrbitForVelocity(nbody, aroundNBody); // Is the resulting orbit and ellipse or hyperbola? if (orbitData.ecc < 1f) { ellipseBase.InitFromOrbitData(orbitData); lineR.SetPositions(ellipseBase.OrbitPositions(numPoints)); } else { orbitHyper.InitFromOrbitData(orbitData); lineR.SetPositions(orbitHyper.OrbitPositions(numPoints)); } } }
//============================================================================================ // Console commands: If there is a GEConsole in the scene, these commands will be available //============================================================================================ // In-class console method // Quick and Dirty implementation for testing LambertUniversal code. private string LambertUniversal(float time) { OrbitData shipData = new OrbitData(); shipData.SetOrbitForVelocity(spaceshipNBody, starNBody); OrbitData targetData = targetEllipses[selectedEllipse].orbitData; targetData.phase = targetEllipses[selectedEllipse].manueverPhase; // get time and try universal LambertUniversal lu = new LambertUniversal(shipData, targetData, true); const bool reverse = false; const bool df = false; const int nrev = 0; int error = lu.ComputeXfer(reverse, df, nrev, time); if (error != 0) { return(string.Format("Error: LambertUniversal rc=" + error)); } spaceshipNBody.vel_phys = lu.GetTransferVelocity(); return(string.Format("time={0} univ={1}", time, lu.GetTransferVelocity())); }
/// <summary> /// Computes the transfer with the moon on the +X axis without accounting for the moon motion during /// transit. (That is accounted for in the ExecuteTransfer routine). /// /// This allows a co-rotating visualization of the orbit. /// </summary> /// <returns></returns> private Vector3 ComputeTransfer() { OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbitForVelocity(spaceship, planet); // compute the min energy path (this will be in the short path direction) lambertU = new LambertUniversal(shipOrbit, startPoint, targetPoint, shortPath); // apply any time of flight change double t_flight = tflightFactor * lambertU.GetTMin(); bool reverse = !shortPath; const bool df = false; const int nrev = 0; int error = lambertU.ComputeXfer(reverse, df, nrev, t_flight); if (error != 0) { Debug.LogWarning("Lambert failed to find solution."); aroundMoonSegment.gameObject.SetActive(false); return(Vector3.zero); } // Check Lambert is going in the correct direction Vector3 shipOrbitAxis = Vector3.Cross(ge.GetVelocity(spaceship), ge.GetPhysicsPosition(spaceship)).normalized; Vector3 tliOrbitAxis = Vector3.Cross(lambertU.GetTransferVelocity(), startPoint.ToVector3()); if (Vector3.Dot(shipOrbitAxis, tliOrbitAxis) < 0) { error = lambertU.ComputeXfer(!reverse, df, nrev, t_flight); if (error != 0) { Debug.LogWarning("Lambert failed to find solution for reverse path. error=" + error); return(Vector3.zero); } } Vector3 tliVelocity = lambertU.GetTransferVelocity(); toMoonOrbit.SetVelocity(tliVelocity); toMoonSegment.SetVelocity(tliVelocity); aroundMoonSegment.gameObject.SetActive(true); // Set velocity for orbit around moon Vector3 soiEnterVel = lambertU.GetFinalVelocity(); aroundMoonSegment.SetVelocity(soiEnterVel); // update shipEnterSOI object ge.UpdatePositionAndVelocity(shipEnterSOI, targetPoint.ToVector3(), soiEnterVel); // Find the orbit around the moon. By using the mirror position we're assuming it's // a hyperbola (since there is no course correction at SOI this is true). // (Moon is in correct position for these calcs so can use world positions, relativePos=false) Vector3d soiEnterV = new Vector3d(lambertU.GetFinalVelocity()); OrbitUtils.OrbitElements oe = OrbitUtils.RVtoCOE(targetPoint, soiEnterV, moonBody, false); Vector3d soiExitR = new Vector3d(); Vector3d soiExitV = new Vector3d(); OrbitUtils.COEtoRVMirror(oe, moonBody, ref soiExitR, ref soiExitV, false); // Set position and vel for exit ship, so exit orbit predictor can run. Moon offset/vel already added. ge.SetPositionDoubleV3(shipExitSOI, soiExitR); ge.SetVelocityDoubleV3(shipExitSOI, soiExitV); aroundMoonSegment.UpdateOrbit(); return(tliVelocity); }