/// <summary> /// Add an element to the sequence using r0/v0/t0 initial conditions. /// /// Position and velocity are with respect to the center body (NOT world/physics space!). /// /// Orbit segements must be added in increasing time order. /// </summary> /// <param name="r0"></param> /// <param name="v0"></param> /// <param name="time"></param> /// <param name="relativePos"></param> /// <param name="body"></param> /// <param name="centerBody"></param> /// <param name="callback">(Optional) Method to call when sequence starts</param> /// <returns></returns> public OrbitUniversal AppendElementRVT(Vector3d r0, Vector3d v0, double time, bool relativePos, NBody body, NBody centerBody, ElementStarted callback) { if (BadTime(time)) { return(null); } KeplerElement ke = new KeplerElement { timeStart = time, callback = callback, returnToGE = false }; OrbitUniversal orbit = orbitsGO.AddComponent <OrbitUniversal>(); orbit.centerNbody = centerBody; orbit.SetNBody(body); orbit.InitFromRVT(r0, v0, time, centerBody, relativePos); orbit.evolveMode = OrbitUniversal.EvolveMode.KEPLERS_EQN; ke.orbit = orbit; keplerElements.Add(ke); return(orbit); }
/// <summary> /// Add an element to the sequence that begins at time and evolves based on the orbit data provided. /// /// Orbit elements must be added in increasing time order. /// </summary> /// <param name="time"></param> /// <param name="orbitData"></param> /// <param name="body"></param> /// <param name="centerBody"></param> /// <param name="callback">(Optional) Method to call when sequence starts</param> /// <returns></returns> public OrbitUniversal AppendElementOrbitData(double time, OrbitData orbitData, NBody body, NBody centerBody, ElementStarted callback) { if (BadTime(time)) { return(null); } KeplerElement ke = new KeplerElement { timeStart = time, returnToGE = false, callback = callback }; OrbitUniversal orbit = orbitsGO.AddComponent <OrbitUniversal>(); orbit.centerNbody = centerBody; orbit.SetNBody(body); orbit.InitFromOrbitData(orbitData, time); orbit.evolveMode = OrbitUniversal.EvolveMode.KEPLERS_EQN; ke.orbit = orbit; keplerElements.Add(ke); return(orbit); }
public void AppendReturnToGE(double time, NBody body) { KeplerElement ke = new KeplerElement(); ke.timeStart = time; ke.returnToGE = true; keplerElements.Add(ke); }
/// <summary> /// Add an element using an existing OrbitUniversal instance /// /// Orbit elements must be added in increasing time order. /// </summary> /// <param name="orbitU"></param> /// <param name="callback">(Optional) Method to call when sequence starts</param> public void AppendElementExistingOrbitU(OrbitUniversal orbitU, ElementStarted callback) { if (BadTime(orbitU.GetStartTime())) { return; } KeplerElement ke = new KeplerElement { timeStart = orbitU.GetStartTime(), returnToGE = false }; ke.orbit = orbitU; ke.callback = callback; keplerElements.Add(ke); }
/// <summary> /// Add orbit segements for each of the maneuvers. The maneuvers must have been created by transfer code /// that populated the fields: relativeTo, relativePos, relativeVel and time fields. /// /// </summary> /// <param name="list"></param> public void AddManeuvers(List <Maneuver> maneuverList) { foreach (Maneuver m in maneuverList) { if (m.relativeTo != null) { Debug.LogFormat("Maneuver: relPos={0} phyPos={1} t={2}", m.relativePos, m.physPosition, m.worldTime); AppendElementRVT(m.relativePos, m.relativeVel, m.worldTime, true, m.nbody, m.relativeTo, null); // add the maneuver to the KE so callback can be used KeplerElement ke = keplerElements[keplerElements.Count - 1]; ke.maneuver = m; } else { Debug.LogError("Could not add maneuver. Missing relativeTo information. Skipped."); } } }
public void Evolve(double physicsTime, ref double[] r) { if ((activeElement < keplerElements.Count - 1) && (physicsTime > keplerElements[activeElement + 1].timeStart)) { // Advance to next element activeElement++; GravityEngine ge = GravityEngine.Instance(); KeplerElement activeKE = keplerElements[activeElement]; if (activeKE.returnToGE) { #pragma warning disable 162 // disable unreachable code warning if (GravityEngine.DEBUG) { Debug.Log("return to GE:" + gameObject.name); } #pragma warning restore 162 KeplerElement priorKE = keplerElements[activeElement - 1]; priorKE.orbit.Evolve(physicsTime, ref r); Vector3d pos = priorKE.orbit.GetPositionDouble(); Vector3d vel = priorKE.orbit.GetVelocityDouble(); ge.BodyOffRails(nbody, pos, vel); return; } else { // if the center object of the orbit changes, need to recompute the KeplerDepth and update if (keplerElements[activeElement - 1].orbit.centerNbody != activeKE.orbit.centerNbody) { NewCenter(activeKE.orbit); } // move on to the next orbit in the sequence activeKE.orbit.PreEvolve(ge.physToWorldFactor, ge.massScale); if (activeKE.callback != null) { activeKE.callback(activeKE.orbit); } if ((activeKE.maneuver != null) && (activeKE.maneuver.onExecuted != null)) { activeKE.maneuver.onExecuted(activeKE.maneuver); } } #pragma warning disable 162 // disable unreachable code warning if (GravityEngine.DEBUG) { Debug.LogFormat("Changed to segment {0} tnow={1} tseg={2} ", activeElement, physicsTime, keplerElements[activeElement].timeStart); } #pragma warning restore 162 } else if (physicsTime < keplerElements[activeElement].timeStart) { // Use an earlier element (happens if time set to earlier) int lastElement = activeElement; while (physicsTime < keplerElements[activeElement].timeStart && (activeElement >= 0)) { activeElement--; // if the center object of the orbit changes, need to recompute the KeplerDepth and update if (keplerElements[lastElement].orbit.centerNbody != keplerElements[activeElement].orbit.centerNbody) { NewCenter(keplerElements[activeElement].orbit); } } } if (!keplerElements[activeElement].returnToGE) { // time for evolve is absolute - up to OrbitUniversal to make it relative to their time0 keplerElements[activeElement].orbit.Evolve(physicsTime, ref r); } }