Пример #1
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);
    }
Пример #2
0
    /// <summary>
    /// Take the Nbody objects in the nbodies list set them inactive and make them children of a new
    /// NBody object moving as the CM of the nbodies. This allows RigidBody mechanics during close
    /// encounters.
    /// </summary>
    private void Activate()
    {
        if (nbodies.Length < 2)
        {
            Debug.LogError("Need two or more nbodies");
            return;
        }

        GravityEngine ge = GravityEngine.Instance();

        // Step 1: calculate CM position and velocity
        Vector3d cmPos = new Vector3d(0, 0, 0);
        Vector3d cmVel = new Vector3d(0, 0, 0);

        float mass = 0f;

        rigidBodies = new Rigidbody[nbodies.Length];

        // RigidBody is assumed to be attached to one of the children (to keep model scale independent)
        int i = 0;

        foreach (NBody nbody in nbodies)
        {
            rigidBodies[i] = nbody.GetComponentInChildren <Rigidbody>();
            //rigidBodies[i] = nbody.GetComponent<Rigidbody>();
            if (rigidBodies[i] == null)
            {
                Debug.LogError("Abort - No rigidbody detected on " + nbody.gameObject.name);
                return;
            }
            mass  += rigidBodies[i].mass;
            cmPos += rigidBodies[i].mass * ge.GetPositionDoubleV3(nbody);
            cmVel += rigidBodies[i].mass * ge.GetVelocityDoubleV3(nbody);
            i++;
        }
        cmPos /= mass;
        cmVel /= mass;
        Debug.LogFormat("CM p={0} v={1} mass={2}", cmPos.ToVector3(), cmVel.ToVector3(), mass);

        // Step2: Inactivate the NBodies and make children of a new NBody object
        priorParents = new Transform[nbodies.Length];
        cmObject     = new GameObject("DockingGroupCM");
        cmNbody      = cmObject.AddComponent <NBody>();

        // Set cm pos/vel
        // NBody InitPosition will use transform or initialPos base on units. Set both.
        cmNbody.initialPos         = cmPos.ToVector3() * ge.physToWorldFactor;
        cmNbody.transform.position = cmNbody.initialPos;
        ge.AddBody(cmObject);
        ge.SetVelocity(cmNbody, cmVel.ToVector3());
        Debug.LogFormat("set pos={0} actual={1}", cmPos.ToVector3(), ge.GetPhysicsPosition(cmNbody));
        i = 0;
        foreach (NBody nbody in nbodies)
        {
            Vector3d pos = ge.GetPositionDoubleV3(nbody);
            Vector3d vel = ge.GetVelocityDoubleV3(nbody);
            priorParents[i] = nbody.gameObject.transform.parent;
            ge.InactivateBody(nbody.gameObject);
            nbody.gameObject.transform.parent = cmObject.transform;
            // position wrt to CM. Need to convert to Unity scene units from GE Internal
            pos = (pos - cmPos) * ge.physToWorldFactor;
            vel = GravityScaler.ScaleVelPhysToScene(vel - cmVel);
            nbody.transform.localPosition = pos.ToVector3();
            rigidBodies[i].velocity       = vel.ToVector3();
            // rigidBodies[i].isKinematic = false;
            i++;
            Debug.LogFormat("body {0} p={1} v={2}", nbody.gameObject.name, pos.ToVector3(), vel.ToVector3());
        }
        // activate any RCS elements
        foreach (ReactionControlSystem r in rcs)
        {
            if (r != null)
            {
                r.SetRigidBodyEnabled(true);
            }
        }
    }