// Create an NBody and check it's mass public void EccentricityPrediction() { 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>(); OrbitPredictor op = TestSetupUtils.AddOrbitPredictor(planet, star); Assert.NotNull(op); double[] ecc_values = { 0, 0.1, 0.7, 0.9, 0.99, 1.01, 1.5, 2 }; foreach (double ecc in ecc_values) { Debug.LogFormat("#### EccentricityPrediction ecc={0}", ecc); orbitU.eccentricity = ecc; TestSetupUtils.SetupGravityEngine(star, planet); op.TestRunnerSetup(); OrbitUniversal predictedOrbit = op.GetOrbitUniversal(); Assert.NotNull(predictedOrbit); CompareOrbits(orbitU, predictedOrbit, small); } }
// Create an NBody and check it's mass public void CirclePrediction() { 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>(); OrbitPredictor op = TestSetupUtils.AddOrbitPredictor(planet, star); Assert.NotNull(op); double[] p_values = { 10, 100, 1000 }; foreach (double p in p_values) { Debug.LogFormat("#### CirclePrediction p={0}", p); orbitU.p = p; TestSetupUtils.SetupGravityEngine(star, planet); op.TestRunnerSetup(); OrbitUniversal predictedOrbit = op.GetOrbitUniversal(); Assert.NotNull(predictedOrbit); CompareOrbits(orbitU, predictedOrbit, small); } }
// Create an NBody and check it's mass public void OmegaUEllipsePrediction() { 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>(); // Need a bit of incl, otherwise omegaU comes back as omegaL. orbitU.inclination = 10; orbitU.eccentricity = 0.05; OrbitPredictor op = TestSetupUtils.AddOrbitPredictor(planet, star); Assert.NotNull(op); double[] ou_values = { 0, 1, 5, 10, 30, 60, 90, 180, 270, 355, 360 }; foreach (double ou in ou_values) { Debug.LogFormat("#### OmegaUPrediction ou={0}", ou); orbitU.omega_uc = ou; TestSetupUtils.SetupGravityEngine(star, planet); op.TestRunnerSetup(); OrbitUniversal predictedOrbit = op.GetOrbitUniversal(); Assert.NotNull(predictedOrbit); CompareOrbits(orbitU, predictedOrbit, small); } }
// Create an NBody and check it's mass public void InclinationPrediction() { 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>(); OrbitPredictor op = TestSetupUtils.AddOrbitPredictor(planet, star); Assert.NotNull(op); double[] incl_values = { 0, 1, 5, 10, 30, 45, 60, 90, 145, 179, 180 }; foreach (double incl in incl_values) { Debug.LogFormat("#### InclinationPrediction incl={0}", incl); orbitU.inclination = incl; TestSetupUtils.SetupGravityEngine(star, planet); op.TestRunnerSetup(); OrbitUniversal predictedOrbit = op.GetOrbitUniversal(); Assert.NotNull(predictedOrbit); CompareOrbits(orbitU, predictedOrbit, small); } }
void Update() { OrbitUniversal orbitU = orbitPredictor.GetOrbitUniversal(); float apogee = (float)orbitU.GetApogee(); apogee_text.text = string.Format(apogee_str, apogee); if (orbitU.eccentricity < 1f) { float perigee = (float)orbitU.GetPerigee(); perigee_text.text = string.Format(perigee_str, perigee); } else { perigee_text.text = string.Format(" Perigee: N/A"); } e_text.text = string.Format(ecc_str, orbitU.eccentricity); i_text.text = string.Format(incl_str, orbitU.inclination); UOmega_text.text = string.Format(Omega_str, orbitU.omega_uc); LOmega_text.text = string.Format(omega_str, orbitU.omega_lc); }
/// <summary> /// Computes the transfer and updates all the ghost bodies. /// </summary> /// <returns></returns> private void ComputeTransfer() { double timeNow = ge.GetPhysicalTimeDouble(); // First using the transfer time, move the ghost Moon to position at SOI arrival. // Call evolve via LockAtTime on the ghostMoon to move it. Set position based on this. double t_flight = tflightFactor * timeHohmann; double timeatSoi = timeNow + t_flight; ghostMoonOrbit[MOON_SOI_ENTER].LockAtTime(timeatSoi); // Determine the moon phase angle double moonPhase = ghostMoonSoiEnterOrbitPredictor.GetOrbitUniversal().phase; // Place the TLI ship at the user-requested angle wrt planet-moon line // Put ghost ship in same orbit geometry as the moon, assuming it is circular. Then // can use same phase value. // (Ship needs to reach this departure point, it may not even be on the ship orbit // in general). ghostShipOrbit[TLI].phase = shipTLIAngleDeg + (moonPhase + 180f); ghostShipOrbit[TLI].inclination = ghostMoonOrbit[MOON_SOI_ENTER].inclination; ghostShipOrbit[TLI].omega_lc = ghostMoonOrbit[MOON_SOI_ENTER].omega_lc; ghostShipOrbit[TLI].omega_uc = ghostMoonOrbit[MOON_SOI_ENTER].omega_uc; ghostShipOrbit[TLI].p_inspector = shipOrbit.p; ghostShipOrbit[TLI].Init(); ghostShipOrbit[TLI].LockAtTime(0); // Place the SOI enter ship at the user-requested angle in an SOI orbit. Lock at time 0 so the phase // is held per the user input. ghostShipOrbit[ENTER_SOI].phase = soiAngleDeg + moonPhase; ghostShipOrbit[ENTER_SOI].inclination = soiInclination + shipOrbit.inclination; ghostShipOrbit[ENTER_SOI].omega_lc = ghostMoonOrbit[MOON_SOI_ENTER].omega_lc; ghostShipOrbit[ENTER_SOI].omega_uc = ghostMoonOrbit[MOON_SOI_ENTER].omega_uc; ghostShipOrbit[ENTER_SOI].Init(); ghostShipOrbit[ENTER_SOI].LockAtTime(0); // Find the line to the ENTER_SOI position. Ship departs from that line continued through planet // at the shipRadius distance (assumes circular ship orbit) // TODO: Handle planet not at (0,0,0) Vector3d soiEntryPos = ge.GetPositionDoubleV3(ghostShip[ENTER_SOI]); Vector3d planetPos = ge.GetPositionDoubleV3(planet); Vector3d departurePoint = ge.GetPositionDoubleV3(ghostShip[TLI]); // Use Lambert to find the departure velocity to get from departure to soiEntry // Since we need 180 degrees from departure to arrival, use LambertBattin lambertB = new LambertBattin(ghostShip[TO_MOON], planet, departurePoint, soiEntryPos, shipOrbit.GetAxis()); // apply any time of flight change bool reverse = !shortPath; const bool df = false; const int nrev = 0; int error = lambertB.ComputeXfer(reverse, df, nrev, t_flight); if (error != 0) { Debug.LogWarning("Lambert failed to find solution. error=" + error); return; } // Check Lambert is going in the correct direction //Vector3 shipOrbitAxis = Vector3.Cross(ge.GetPhysicsPosition(spaceship), ge.GetVelocity(spaceship) ).normalized; //Vector3 tliOrbitAxis = Vector3.Cross(departurePoint.ToVector3(), lambertB.GetTransferVelocity().ToVector3()).normalized; Vector3 shipOrbitAxis = Vector3.Cross(ge.GetVelocity(spaceship), ge.GetPhysicsPosition(spaceship)).normalized; Vector3 tliOrbitAxis = Vector3.Cross(lambertB.GetTransferVelocity().ToVector3(), departurePoint.ToVector3()).normalized; if (Vector3.Dot(shipOrbitAxis, tliOrbitAxis) < 0) { error = lambertB.ComputeXfer(!reverse, df, nrev, t_flight); if (error != 0) { Debug.LogWarning("Lambert failed to find solution for reverse path. error=" + error); return; } } Debug.LogFormat("tli_vel={0}", lambertB.GetTransferVelocity()); ghostShipOrbit[TO_MOON].InitFromRVT(departurePoint, lambertB.GetTransferVelocity(), timeNow, planet, false); // Set velocity for orbit around moon. Will be updated every frame ghostShipOrbit[SOI_HYPER].InitFromRVT(soiEntryPos, lambertB.GetFinalVelocity(), timeNow, ghostMoon[MOON_SOI_ENTER], false); // Find the exit point of the hyperbola in the SOI OrbitUtils.OrbitElements oe = OrbitUtils.RVtoCOE(soiEntryPos, lambertB.GetFinalVelocity(), ghostMoon[MOON_SOI_ENTER], false); Vector3d soiExitR = new Vector3d(); Vector3d soiExitV = new Vector3d(); OrbitUtils.COEtoRVMirror(oe, ghostMoon[MOON_SOI_ENTER], ref soiExitR, ref soiExitV, false); // Find time to go around the moon. TOF requires relative positions!! Vector3d ghostSoiEnterPos = ge.GetPositionDoubleV3(ghostMoon[MOON_SOI_ENTER]); Vector3d soiEnterRelative = soiEntryPos - ghostSoiEnterPos; Vector3d soiExitRelative = soiExitR - ghostSoiEnterPos; Vector3d soiExitVelRelative = soiExitV - ge.GetVelocityDoubleV3(ghostMoon[MOON_SOI_ENTER]); double hyperTOF = ghostShipOrbit[SOI_HYPER].TimeOfFlight(soiEnterRelative, soiExitRelative); // Position the ghost moon for SOI exit (timeAtSoi includes timeNow) t_soiExit = timeatSoi + hyperTOF; ghostMoonOrbit[MOON_SOI_EXIT].LockAtTime(t_soiExit); // Set position and vel for exit ship, so exit orbit predictor can run. Vector3d ghostMoonSoiExitPos = ge.GetPositionDoubleV3(ghostMoon[MOON_SOI_EXIT]); Vector3d ghostMoonSoiExitVel = ge.GetVelocityDoubleV3(ghostMoon[MOON_SOI_EXIT]); ghostShipOrbit[EXIT_SOI].InitFromRVT(soiExitRelative + ghostMoonSoiExitPos, soiExitVelRelative + ghostMoonSoiExitVel, timeNow, planet, false); }