Esempio n. 1
0
    void FixedUpdate()
    {
        // Better performance with bulk set of positions in LR
        if (ge.trajectoryPrediction && (points != null))
        {
            float currentTime = ge.GetPhysicalTime();
            // remove any points older than current time
            while ((points.Count > 0) && (points[0].worldTime < currentTime))
            {
                points.RemoveAt(0);
            }

            // add/remove a time marker?
            if (timeMarkerPrefab != null)
            {
                // remove any old time markers
                while ((timeMarks.Count > 0) && (timeMarks[0].time < currentTime))
                {
                    Destroy(timeMarks[0].marker);
                    if (timeMarks[0].textObject != null)
                    {
                        Destroy(timeMarks[0].textObject);
                    }
                    timeMarks.RemoveAt(0);
                }
            }

            UpdateLineRenderer();
        }
    }
    /// <summary>
    /// Set up a KeplerSeqeunce to do the three phases of the transfer as Kepler mode conics.
    ///
    /// Add all the ghost orbits with the required times
    /// </summary>
    /// <param name="transferTime"></param>
    private void TransferOnRails()
    {
        // the ship needs to have a KeplerSequence
        KeplerSequence kseq = spaceship.GetComponent <KeplerSequence>();

        if (kseq == null)
        {
            Debug.LogError("Could not find a KeplerSequence on " + spaceship.name);
            return;
        }
        // Ellipse 1: shipPos/shipvel already phased by the caller.
        double t_start = ge.GetPhysicalTime();
        double t_toSoi = timeHohmann * tflightFactor;

        KeplerSequence.ElementStarted noCallback = null;
        Vector3d r0    = new Vector3d();
        Vector3d v0    = new Vector3d();
        double   time0 = 0;

        ghostShipOrbit[TO_MOON].GetRVT(ref r0, ref v0, ref time0);
        kseq.AppendElementRVT(r0, v0, t_start, true, spaceship, planet, noCallback);

        // Hyperbola: start at t + transferTime
        // Need to add wrt to ghostMoon (relative=true), then for actual Kepler motion want it around moon
        ghostShipOrbit[SOI_HYPER].GetRVT(ref r0, ref v0, ref time0);
        OrbitUniversal hyperObit = kseq.AppendElementRVT(r0, v0, t_start + t_toSoi, true, spaceship, ghostMoon[MOON_SOI_ENTER], EnterMoonSoi);

        hyperObit.centerNbody = moonBody;

        // Ellipse 2:
        ghostShipOrbit[EXIT_SOI].GetRVT(ref r0, ref v0, ref time0);
        kseq.AppendElementRVT(r0, v0, t_soiExit, true, spaceship, planet, ExitMoonSoi);
    }
Esempio n. 3
0
    // Scaling:
    // Setting the size of the ellipse is done via the ellipse base "a". This is
    // entered by the user in the units selected in the GE units chooser. Additionaly the
    // GE inspector may indicate a Unity Units per [km|AU] and this needs to be taken into account
    // in the Gizmo that draws the orbit.
    //

    /// <summary>
    /// Inits the N body position and velocity based on the ellipse parameters and the
    /// position and velocity of the parent.
    /// </summary>
    /// <param name="physicalScale">Physical scale.</param>
    public void InitNBody(float physicalScale, float massScale)
    {
        base.Init();
        float a_phy = a_scaled / physicalScale;

        if (nbody == null)
        {
            nbody = GetComponent <NBody>();
        }

        // Phase is TRUE anomoly f
        float f = phase * Mathf.Deg2Rad;
        // Murray and Dermot
        // (2.26)
        // This should really be (M+m), but assume m << M
        // (massScale is added in at the GE level)
        float n = Mathf.Sqrt((float)(centerNbody.mass * massScale) / (a_phy * a_phy * a_phy));
        // (2.36)
        float denom = Mathf.Sqrt(1f - ecc * ecc);
        float xdot  = -1f * n * a_phy * Mathf.Sin(f) / denom;
        float ydot  = n * a_phy * (ecc + Mathf.Cos(f)) / denom;

        // Init functions are called in the engine by SetupOneBody and calls of parent vs children/grandchildren etc.
        // can be in arbitrary order. A child will need info from parent for position and velocity. Ensure parent
        // has inited. Init may get called more than once.
        centerNbody.InitPosition(GravityEngine.Instance());

        Vector3 v_xy = new Vector3(xdot, ydot, 0);

        // if we're evolving, get the latest velocity
        if (centerNbody.engineRef != null)
        {
            centerNbody.UpdateVelocity();
        }
        Vector3 vphy = ellipse_orientation * v_xy + centerNbody.vel_phys;

        nbody.vel_phys = vphy;
        SetInitialPosition(nbody);
        if (evolveMode == evolveType.KEPLERS_EQN)
        {
            if (Application.isPlaying)
            {
                // Need to force an evolve to update position and velocity so that
                // dependent objects get the correct values.
                GravityEngine ge = GravityEngine.Instance();
                double[]      r  = new double[] { 0, 0, 0 };
                PreEvolve(ge.GetLengthScale(), ge.massScale);
                Evolve(ge.GetPhysicalTime(), ref r);
            }
            else
            {
                // if in the editor/DrawGizmos all we care about is position and above clause
                // causes exceptions, since it asks GE for position/velocity
                position = nbody.initialPhysPosition;
            }
        }
    }
Esempio n. 4
0
    // Use this for initialization
    void Start()
    {
        GravityEngine ge = GravityEngine.Instance();

        time.text = string.Format(time_format, ge.GetPhysicalTime(), ge.GetTimeZoom());
        Vector3 pos = ship.initialPos;

        position.text = string.Format(pos_format, pos.x, pos.y, pos.z);
        velocity.text = string.Format(vel_format, 0f, 0f, 0f);
        RocketEngine rocketEngine = ship.GetComponent <RocketEngine>();

        if (rocketEngine == null)
        {
            Debug.LogError("Need a rocket component");
        }
        fuelText.text = string.Format(fuel_format, rocketEngine.GetFuel(ge.GetPhysicalTime()));
        attitude.text = string.Format(attitude_format, 0f, 0f, 0f);

        // assume earth at (0,0,0)
        initial_altitude = Vector3.Magnitude(ship.transform.position);
        altitude.text    = string.Format(altitude_format, 0f);
    }
    public CircularizeXfer(OrbitData fromOrbit) : base(fromOrbit)
    {
        name = "Circularize";
        GravityEngine ge = GravityEngine.Instance();

        // find velocity vector perpendicular to r for circular orbit
        Vector3d r_ship   = ge.GetPositionDoubleV3(fromOrbit.nbody);
        Vector3d v_ship   = ge.GetVelocityDoubleV3(fromOrbit.nbody);
        Vector3d r_center = ge.GetPositionDoubleV3(fromOrbit.centralMass);
        Vector3d v_center = ge.GetVelocityDoubleV3(fromOrbit.centralMass);

        Vector3d r = r_ship - r_center;

        // want velocity relative to central mass (it could be moving)
        Vector3d v = v_ship - v_center;

        // to get axis of orbit, can take r x v
        Vector3d axis = Vector3d.Cross(r, v).normalized;
        // vis visa for circular orbit
        double mu    = GravityEngine.Instance().GetMass(centerBody);
        double v_mag = Mathd.Sqrt(mu / r.magnitude);
        // positive v is counter-clockwise
        Vector3d v_dir      = Vector3d.Cross(axis, r).normalized;
        Vector3d v_circular = v_mag * v_dir;

        Maneuver m1;

        m1           = new Maneuver();
        m1.nbody     = fromOrbit.nbody;
        m1.mtype     = Maneuver.Mtype.vector;
        m1.velChange = (v_circular - v).ToVector3();
        m1.dV        = Vector3.Magnitude(m1.velChange);

        // maneuver positions and info for KeplerSeq conversion and velocity directions
        Vector3d h_unit = fromOrbit.GetAxis();

        m1.physPosition = r_ship;
        m1.relativePos  = r_ship - r_center;
        m1.relativeVel  = v_circular.magnitude * Vector3d.Cross(h_unit, m1.relativePos).normalized;
        m1.relativeTo   = fromOrbit.centralMass;

        //Debug.LogFormat("v_ship={0} v_center={1} v_c.x={2}", vel_ship, vel_center, v_center[0]);
        //Debug.Log(string.Format("v_ship={0} v_circular={1} axis={2} v_dir={3} velChange={4}",
        //    vel_ship, v_circular, axis, v_dir, m1.velChange));
        m1.worldTime = ge.GetPhysicalTime();
        maneuvers.Add(m1);
    }
    // Update is called once per frame
    void FixedUpdate()
    {
        // monitor for engine start (not ideal, but avoids linking to LaunchUI script)
        if ((timeStarted < 0) && engine.engineOn)
        {
            timeStarted = ge.GetPhysicalTime();
            float   pitch0        = pitchCurve.Evaluate(0);
            Vector3 localVertical = Vector3.Normalize(ge.GetPhysicsPosition(ship) - ge.GetPhysicsPosition(earth));
            lastAttitude = Vector3.Cross(localVertical, Vector3.forward); // forward = (0,0,1)
            lastAttitude = Quaternion.AngleAxis(pitch0, Vector3.forward) * lastAttitude;
        }

        if (timeStarted > 0)
        {
            float t = (float)(ge.GetTimeWorldSeconds() - timeStarted) / timeRangePhysical;
            t = Mathf.Clamp(t, 0f, 1f);

            // pitch in range 0..90 as curve goes 0..1
            float pitch = pitchCurve.Evaluate(t) * 90.0f;
            // find the local vertical
            Vector3 localVertical = Vector3.Normalize(ge.GetPhysicsPosition(ship) - ge.GetPhysicsPosition(earth));
            // First get local horizontal (this ordering of cross product assumes we want to go East)
            Vector3 attitude = Vector3.Cross(localVertical, Vector3.forward); // forward = (0,0,1)
            attitude = Quaternion.AngleAxis(pitch, Vector3.forward) * attitude;
            engine.SetThrustAxis(-attitude);
            shipModel.RotateToVector(attitude);

            // when attitude changes by 1 degree, re-compute trajectories
            if (Vector3.Angle(attitude, lastAttitude) > 1f)
            {
                ge.TrajectoryRestart();
                lastAttitude = attitude;
            }

            // thrust
            float thrust = thrustCurve.Evaluate(t);
            engine.SetThrottlePercent(100f * thrust);
        }
    }
    // Update is called once per fixed frame by GE
    public void FixedUpdate()
    {
        // need to get physics positions for everything
        GravityEngine ge       = GravityEngine.Instance();
        Vector3       shipPos  = ge.GetPhysicsPosition(spaceship);
        Vector3       body1Pos = ge.GetPhysicsPosition(body1);
        Vector3       body2Pos = ge.GetPhysicsPosition(body2);

        float D = Vector3.Distance(body1Pos, body2Pos);

        NBody influencer = lastInfluencer;
        float d          = Vector3.Distance(shipPos, body2Pos);

        // add a bit of hysteresis
        if (d < ENTER_DERATE * D * massRatio25)
        {
            influencer = body2;
        }
        else if (d > D * massRatio25)
        {
            influencer = body1;
        }
        if (influencer != lastInfluencer)
        {
            if (patchChanged != null)
            {
                patchChanged.OnNewInfluencer(influencer, lastInfluencer);
            }
#pragma warning disable 162        // disable unreachable code warning
            if (GravityEngine.DEBUG)
            {
                Debug.LogFormat("Influencer changed from {0} to {1} at d={2} t={3}",
                                lastInfluencer, influencer, d, ge.GetPhysicalTime());
            }
#pragma warning restore 162
            lastInfluencer = influencer;
        }
    }
    /// <summary>
    /// Set up a KeplerSeqeunce to do the three phases of the transfer as Kepler mode conics.
    ///
    /// Leave the existing ship orbit as the first
    /// </summary>
    /// <param name="transferTime"></param>
    private void TransferOnRails(double transferTime, Vector3 shipPos, Vector3 shipVel, float moonOmega)
    {
        // the ship needs to have a KeplerSequence
        KeplerSequence kseq = spaceship.GetComponent <KeplerSequence>();

        if (kseq == null)
        {
            Debug.LogError("Could not find a KeplerSequence on " + spaceship.name);
            return;
        }
        float      moonPhaseDeg = moonOmega * (float)transferTime * Mathf.Rad2Deg;
        Quaternion moonPhaseRot = Quaternion.AngleAxis(moonPhaseDeg, Vector3.forward);

        // Ellipse 1: shipPos/shipvel already phased by the caller.
        double t = ge.GetPhysicalTime();

        KeplerSequence.ElementStarted noCallback = null;
        kseq.AppendElementRVT(new Vector3d(shipPos), new Vector3d(shipVel), t, false, spaceship, planet, noCallback);

        // Hyperbola: start at t + transferTime
        // have targetPoint and final velocity from LambertTransfer. Need to make these wrt moon at this time
        // targetPoint is w.r.t current moon position, but need to rotate around SOI by amount moon will shift
        // as ship transits to moon
        Vector3 targetPos    = targetPoint.ToVector3();
        Vector3 moonPosAtSoi = moonPhaseRot * ge.GetPhysicsPosition(moonBody);
        Vector3 moonVelAtSoi = moonPhaseRot * ge.GetVelocity(moonBody);
        // get the relative positions (i.e. as if moon at the origin with v=0)
        Vector3 adjustedTarget = moonPhaseRot * targetPos - moonPosAtSoi;
        Vector3 adjustedVel    = moonPhaseRot * lambertU.GetFinalVelocity() - moonVelAtSoi;

        // Create moon hyperbola at the moon position after flight to moon. This means the init cannot make reference
        // to the CURRENT moon position.
        Vector3d       soiEnterR  = new Vector3d(adjustedTarget);
        Vector3d       soiEnterV  = new Vector3d(adjustedVel);
        OrbitUniversal hyperOrbit = kseq.AppendElementRVT(soiEnterR,
                                                          soiEnterV,
                                                          t + transferTime,
                                                          true,
                                                          spaceship,
                                                          moonBody,
                                                          EnterMoonSoi);

        // Find the hyperbola exit SOI position/vel
        OrbitUtils.OrbitElements oe = OrbitUtils.RVtoCOE(soiEnterR, soiEnterV, moonBody, true);
        Vector3d soiExitR           = new Vector3d();
        Vector3d soiExitV           = new Vector3d();

        Debug.Log("oe=" + oe);
        // Gives position and velocity in relative position
        OrbitUtils.COEtoRVMirror(oe, moonBody, ref soiExitR, ref soiExitV, true);

        // Determine hyperbola transit time to the soiExit position
        double hyperTOF = hyperOrbit.TimeOfFlight(soiEnterR, soiExitR);

        //Debug.LogFormat("Hyper TOF={0} r0={1} r1={2} p={3}", hyperTOF, adjustedTarget, soiExitR,
        //    hyperOrbit.p);

        // Ellipse 2:
        // Adjust phase to allow for moon travel during hyperbola transit
        // Need to set position and vel relative to the planet using position relative to moon at 0
        moonPhaseDeg = moonOmega * (float)hyperTOF * Mathf.Rad2Deg;
        Quaternion moonHyperRot     = Quaternion.AngleAxis(moonPhaseDeg, Vector3.forward);
        Vector3    moonAtExit       = moonHyperRot * moonPosAtSoi;
        Vector3    moonVelAtExit    = moonHyperRot * moonVelAtSoi;
        Vector3    soiExitwrtPlanet = soiExitR.ToVector3() + moonAtExit;
        // soiexitV is relative to moon at (0,0,0) BUT frame of hyperbola does not rotate
        Vector3 soiExitVelwrtPlanet = moonHyperRot * soiExitV.ToVector3() + moonVelAtExit;

        Debug.LogFormat("Ellipse2: soiExitV={0} moonV={1} net={2}", soiExitV, moonVelAtExit, soiExitVelwrtPlanet);

        kseq.AppendElementRVT(new Vector3d(soiExitwrtPlanet),
                              new Vector3d(soiExitVelwrtPlanet),
                              t + transferTime + hyperTOF,
                              true,
                              spaceship,
                              planet,
                              ExitMoonSoi);
        running = true;
    }
Esempio n. 9
0
 // Update is called once per frame
 void Update()
 {
     timeLast     = ge.GetPhysicalTime();
     slider.value = timeLast;
 }
Esempio n. 10
0
    /// <summary>
    /// Execute the maneuver. Called automatically by Gravity Engine for maneuvers that
    /// have been added to the GE via AddManeuver().
    ///
    /// Unusual to call this method directly.
    /// </summary>
    /// <param name="ge"></param>
    public void Execute(GravityEngine ge)
    {
        Vector3 vel = ge.GetVelocity(nbody);

        switch (mtype)
        {
        case Mtype.vector:
            vel += velChange;
            break;

        case Mtype.scalar:
            // scalar: adjust existing velocity by dV
            Vector3 change = Vector3.Normalize(vel) * dV;
            vel += change;
            break;

        case Mtype.circularize:
            // find velocity vector perpendicular to r for circular orbit
            // Since we could be mid-integration need to get exact position from GE
            double[] r_ship = new double[3];
            double[] v_ship = new double[3];
            ge.GetPositionVelocityScaled(nbody, ref r_ship, ref v_ship);
            double[] r_center = new double[3];
            double[] v_center = new double[3];
            ge.GetPositionVelocityScaled(centerBody, ref r_center, ref v_center);

            Vector3 pos_ship   = new Vector3((float)r_ship[0], (float)r_ship[1], (float)r_ship[2]);
            Vector3 vel_ship   = new Vector3((float)v_ship[0], (float)v_ship[1], (float)v_ship[2]);
            Vector3 pos_center = new Vector3((float)r_center[0], (float)r_center[1], (float)r_center[2]);
            Vector3 r          = pos_ship - pos_center;

            // to get axis of orbit, can take v x r
            Vector3 axis = Vector3.Normalize(Vector3.Cross(vel_ship, pos_ship));
            // vis visa for circular orbit
            float mu    = nbody.mass * ge.massScale;
            float v_mag = Mathf.Sqrt(mu / Vector3.Magnitude(r));
            // positive v is counter-clockwise
            Vector3 v_dir      = Vector3.Normalize(Vector3.Cross(axis, r));
            Vector3 v_circular = v_mag * v_dir;
            ge.SetVelocity(nbody, v_circular);

            break;
        }
#pragma warning disable 162        // disable unreachable code warning
        if (GravityEngine.DEBUG)
        {
            Debug.Log("Applied manuever: " + LogString() + " engineRef.index=" + nbody.engineRef.index +
                      " engineRef.bodyType=" + nbody.engineRef.bodyType + " timeError=" + (worldTime - ge.GetPhysicalTime()));
            Debug.Log("r= " + Vector3.Magnitude(nbody.transform.position));
        }
#pragma warning restore 162        // enable unreachable code warning

        ge.SetVelocity(nbody, vel);
    }