Example #1
0
 /// <summary>
 /// Reset the modes
 /// </summary>
 public void Reset()
 {
     // get active command
     mMode              = ComputerMode.Off;
     mAttitude          = FlightAttitude.Null;
     mControlOutputMask = 0;
 }
Example #2
0
        public void mapFlightMode(FlightMode flightMode, FlightAttitude flightAttitude, ReferenceFrame frame)
        {
            computerMode     = ComputerMode.Off;
            computerAttitude = flightAttitude;

            switch (flightMode)
            {
            case FlightMode.Off: { computerMode = ComputerMode.Off; break; }

            case FlightMode.KillRot: { computerMode = ComputerMode.Kill; break; }

            case FlightMode.AttitudeHold:
            {
                computerMode = ComputerMode.Custom;
                switch (frame)
                {
                case ReferenceFrame.Maneuver: { computerMode = ComputerMode.Node; break; }

                case ReferenceFrame.Orbit: { computerMode = ComputerMode.Orbital; break; }

                case ReferenceFrame.Surface: { computerMode = ComputerMode.Surface; break; }

                case ReferenceFrame.TargetParallel: { computerMode = ComputerMode.TargetPos; break; }

                case ReferenceFrame.TargetVelocity: { computerMode = ComputerMode.TargetVel; break; }
                }
                break;
            }
            }
        }
Example #3
0
 public static AttitudeCommand WithAttitude(FlightAttitude att, ReferenceFrame frame)
 {
     return(new AttitudeCommand()
     {
         Mode = FlightMode.AttitudeHold,
         Attitude = att,
         Frame = frame,
         Orientation = Quaternion.identity,
         Altitude = Single.NaN,
         TimeStamp = RTUtil.GameTime,
     });
 }
        private void Confirm()
        {
            ICommand newCommand;

            switch (mMode)
            {
            default:
            case ComputerMode.Off:
                mAttitude  = FlightAttitude.Null;
                newCommand = AttitudeCommand.Off();
                break;

            case ComputerMode.Kill:
                mAttitude  = FlightAttitude.Null;
                newCommand = AttitudeCommand.KillRot();
                break;

            case ComputerMode.Node:
                mAttitude  = FlightAttitude.Null;
                newCommand = AttitudeCommand.ManeuverNode();
                break;

            case ComputerMode.TargetPos:
                mAttitude  = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
                newCommand =
                    AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.TargetParallel);
                break;

            case ComputerMode.Orbital:
                mAttitude  = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
                newCommand =
                    AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.Orbit);
                break;

            case ComputerMode.Surface:
                mAttitude  = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
                newCommand =
                    AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.Surface);
                break;

            case ComputerMode.TargetVel:
                mAttitude  = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
                newCommand =
                    AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.TargetVelocity);
                break;

            case ComputerMode.Custom:
                mAttitude  = FlightAttitude.Null;
                newCommand = AttitudeCommand.WithSurface(Pitch, Heading, Roll);
                break;
            }
            mFlightComputer.Enqueue(newCommand);
        }
        private IEnumerator OnAttitudeClick(FlightAttitude state)
        {
            yield return(null);

            if (mFlightComputer.InputAllowed)
            {
                mAttitude = (state < 0) ? FlightAttitude.Null : state;
                if (mMode == ComputerMode.Off || mMode == ComputerMode.Kill || mMode == ComputerMode.Node)
                {
                    mMode = ComputerMode.Orbital;
                }
                Confirm();
            }
        }
        /// <summary>
        /// Get the current active FlightMode and map it to the Computermode
        /// </summary>
        public void getActiveFlightMode()
        {
            // check the current flight mode
            if (mFlightComputer.CurrentFlightMode == null)
            {
                Reset();
                return;
            }

            // get active command
            SimpleTypes.ComputerModeMapper mappedCommand = mFlightComputer.CurrentFlightMode.mapFlightMode();
            mMode     = mappedCommand.computerMode;
            mAttitude = FlightAttitude.Null;

            if (mMode == ComputerMode.Orbital || mMode == ComputerMode.Surface || mMode == ComputerMode.TargetPos || mMode == ComputerMode.TargetVel)
            {
                mAttitude = mappedCommand.computerAttitude;
            }
        }
Example #7
0
        /// <summary>
        /// Get the current active FlightMode and map it to the Computermode
        /// </summary>
        public void getActiveFlightMode()
        {
            // check the current flight mode
            if (mFlightComputer.CurrentFlightMode == null)
            {
                Reset();
                return;
            }

            // get active command
            SimpleTypes.ComputerModeMapper mappedCommand = mFlightComputer.CurrentFlightMode.mapFlightMode();
            mMode     = mappedCommand.computerMode;
            mAttitude = FlightAttitude.Null;

            if (mMode == ComputerMode.Orbital || mMode == ComputerMode.Surface || mMode == ComputerMode.TargetPos || mMode == ComputerMode.TargetVel)
            {
                mAttitude = mappedCommand.computerAttitude;
            }

            var activeIgnoreCmd = FlightControlCommand.findActiveControlCmd(mFlightComputer);

            if (activeIgnoreCmd != null)
            {
                mControlOutputMask = 0;
                if (activeIgnoreCmd.ignorePitchOutput)
                {
                    mControlOutputMask |= FlightControlOutput.IgnorePitch;
                }
                if (activeIgnoreCmd.ignoreHeadingOutput)
                {
                    mControlOutputMask |= FlightControlOutput.IgnoreHeading;
                }
                if (activeIgnoreCmd.ignoreRollOutput)
                {
                    mControlOutputMask |= FlightControlOutput.IgnoreRoll;
                }
            }
        }
Example #8
0
        public void mapFlightMode(FlightMode flightMode, FlightAttitude flightAttitude, ReferenceFrame frame)
        {
            computerMode = ComputerMode.Off;
            computerAttitude = flightAttitude;

            switch (flightMode)
            {
                case FlightMode.Off: { computerMode = ComputerMode.Off; break; }
                case FlightMode.KillRot: { computerMode = ComputerMode.Kill; break; }
                case FlightMode.AttitudeHold:
                {
                    computerMode = ComputerMode.Custom;
                    switch (frame)
                    {
                        case ReferenceFrame.Maneuver: { computerMode = ComputerMode.Node; break; }
                        case ReferenceFrame.Orbit: { computerMode = ComputerMode.Orbital; break; }
                        case ReferenceFrame.Surface: { computerMode = ComputerMode.Surface; break; }
                        case ReferenceFrame.TargetParallel: { computerMode = ComputerMode.TargetPos; break; }
                        case ReferenceFrame.TargetVelocity: { computerMode = ComputerMode.TargetVel; break; }
                    }
                    break;
                }
            }
        }
Example #9
0
        public static void HoldAttitude(FlightCtrlState fs, FlightComputer f, ReferenceFrame frame, FlightAttitude attitude, Quaternion extra)
        {
            var v       = f.Vessel;
            var forward = Vector3.zero;
            var up      = Vector3.zero;

            switch (frame)
            {
            case ReferenceFrame.Orbit:
                forward = v.GetObtVelocity();
                up      = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.Surface:
                forward = v.GetSrfVelocity();
                up      = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.North:
                up      = (v.mainBody.position - v.CoM);
                forward = Vector3.ProjectOnPlane(up,
                                                 v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius - v.CoM);
                break;

            case ReferenceFrame.Maneuver:
                if (f.Vessel.patchedConicSolver.maneuverNodes.Count != 0)
                {
                    forward = f.Vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(v.orbit);
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    forward = v.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                break;

            case ReferenceFrame.TargetVelocity:
                // f.DelayedTarget may be any ITargetable, including a planet
                // Velocity matching only makes sense for vessels and part modules
                // Can test for Vessel but not PartModule, so instead test that it's not the third case (CelestialBody)
                if (f.DelayedTarget != null && !(f.DelayedTarget is CelestialBody))
                {
                    forward = v.GetObtVelocity() - f.DelayedTarget.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;

            case ReferenceFrame.TargetParallel:
                if (f.DelayedTarget != null && !(f.DelayedTarget is CelestialBody))
                {
                    forward = f.DelayedTarget.GetTransform().position - v.CoM;
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;
            }
            Vector3.OrthoNormalize(ref forward, ref up);
            Quaternion rotationReference = Quaternion.LookRotation(forward, up);

            switch (attitude)
            {
            case FlightAttitude.Prograde:
                break;

            case FlightAttitude.Retrograde:
                rotationReference = rotationReference * Quaternion.AngleAxis(180, Vector3.up);
                break;

            case FlightAttitude.NormalPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.up);
                break;

            case FlightAttitude.NormalMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.down);
                break;

            case FlightAttitude.RadialPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.right);
                break;

            case FlightAttitude.RadialMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.left);
                break;

            case FlightAttitude.Surface:
                rotationReference = rotationReference * extra;
                break;
            }
            HoldOrientation(fs, f, rotationReference);
        }
Example #10
0
        public static void HoldAttitude(FlightCtrlState fs, FlightComputer f, ReferenceFrame frame, FlightAttitude attitude, Quaternion extra)
        {
            var v = f.Vessel;
            var forward = Vector3.zero;
            var up = Vector3.zero;
            bool ignoreRoll = false;

            switch (frame)
            {
                case ReferenceFrame.Orbit:
                    ignoreRoll = true;
                    forward = v.GetObtVelocity();
                    up = (v.mainBody.position - v.CoM);
                    break;

                case ReferenceFrame.Surface:
                    ignoreRoll = true;
                    forward = v.GetSrfVelocity();
                    up = (v.mainBody.position - v.CoM);
                    break;

                case ReferenceFrame.North:
                    up = (v.mainBody.position - v.CoM);
                    forward = Vector3.ProjectOnPlane(v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius - v.CoM, up);
                    break;

                case ReferenceFrame.Maneuver:
                    ignoreRoll = true;
                    if (f.Vessel.patchedConicSolver.maneuverNodes.Count != 0)
                    {
                        forward = f.Vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(v.orbit);
                        up = (v.mainBody.position - v.CoM);
                    }
                    else
                    {
                        forward = v.GetObtVelocity();
                        up = (v.mainBody.position - v.CoM);
                    }
                    break;

                case ReferenceFrame.TargetVelocity:
                    // f.DelayedTarget may be any ITargetable, including a planet
                    // Velocity matching only makes sense for vessels and part modules
                    // Can test for Vessel but not PartModule, so instead test that it's not the third case (CelestialBody)
                    if (f.DelayedTarget != null && !(f.DelayedTarget is CelestialBody))
                    {
                        forward = v.GetObtVelocity() - f.DelayedTarget.GetObtVelocity();
                        up = (v.mainBody.position - v.CoM);
                    }
                    else
                    {
                        up = (v.mainBody.position - v.CoM);
                        forward = v.GetObtVelocity();
                    }
                    break;

                case ReferenceFrame.TargetParallel:
                    if (f.DelayedTarget != null && !(f.DelayedTarget is CelestialBody))
                    {
                        forward = f.DelayedTarget.GetTransform().position - v.CoM;
                        up = (v.mainBody.position - v.CoM);
                    }
                    else
                    {
                        up = (v.mainBody.position - v.CoM);
                        forward = v.GetObtVelocity();
                    }
                    break;
            }
            Vector3.OrthoNormalize(ref forward, ref up);
            Quaternion rotationReference = Quaternion.LookRotation(forward, up);
            
            switch (attitude)
            {
                case FlightAttitude.Prograde:
                    break;

                case FlightAttitude.Retrograde:
                    rotationReference = rotationReference * Quaternion.AngleAxis(180, Vector3.up);
                    break;

                case FlightAttitude.NormalPlus:
                    rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.up);
                    break;

                case FlightAttitude.NormalMinus:
                    rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.down);
                    break;

                case FlightAttitude.RadialPlus:
                    rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.right);
                    break;

                case FlightAttitude.RadialMinus:
                    rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.left);
                    break;

                case FlightAttitude.Surface:
                    rotationReference = rotationReference * extra;
                    break;
            }
            HoldOrientation(fs, f, rotationReference, ignoreRoll);
        }
Example #11
0
 /// <summary>
 /// Reset the modes
 /// </summary>
 public void Reset()
 {
     // get active command
     mMode     = ComputerMode.Off;
     mAttitude = FlightAttitude.Null;
 }
Example #12
0
 private IEnumerator OnAttitudeClick(FlightAttitude state)
 {
     yield return null;
     if (mFlightComputer.InputAllowed)
     {
         mAttitude = (state < 0) ? FlightAttitude.Null : state;
         if (mMode == ComputerMode.Off || mMode == ComputerMode.Kill || mMode == ComputerMode.Node)
         {
             mMode = ComputerMode.Orbital;
         }
         Confirm();
     }
 }
 public static AttitudeCommand WithAttitude(FlightAttitude att, ReferenceFrame frame)
 {
     return new AttitudeCommand()
     {
         Mode = FlightMode.AttitudeHold,
         Attitude = att,
         Frame = frame,
         Orientation = Quaternion.identity,
         Altitude = Single.NaN,
         TimeStamp = RTUtil.GameTime,
     };
 }
Example #14
0
 private void Confirm()
 {
     ICommand newCommand;
     switch (mMode)
     {
         default: 
         case ComputerMode.Off:
             mAttitude = FlightAttitude.Null;
             newCommand = AttitudeCommand.Off();
             break;
         case ComputerMode.Kill:
             mAttitude = FlightAttitude.Null;
             newCommand = AttitudeCommand.KillRot();
             break;
         case ComputerMode.Node:
             mAttitude = FlightAttitude.Null;
             newCommand = AttitudeCommand.ManeuverNode();
             break;
         case ComputerMode.TargetPos:
             mAttitude = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
             newCommand =
                 AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.TargetParallel);
             break;
         case ComputerMode.Orbital:
             mAttitude = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
             newCommand =
                 AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.Orbit);
             break;
         case ComputerMode.Surface:
             mAttitude = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
             newCommand =
                 AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.Surface);
             break;
         case ComputerMode.TargetVel:
             mAttitude = (mAttitude == FlightAttitude.Null) ? FlightAttitude.Prograde : mAttitude;
             newCommand =
                 AttitudeCommand.WithAttitude(Attitude, ReferenceFrame.TargetVelocity);
             break;
         case ComputerMode.Custom:
             mAttitude = FlightAttitude.Null;
             newCommand = AttitudeCommand.WithSurface(Pitch, Heading, Roll);
             break;
     }
     mFlightComputer.Enqueue(newCommand);
 }
Example #15
0
 public static void HoldAttitude(FlightCtrlState fs, FlightComputer f, ReferenceFrame frame, FlightAttitude attitude, Quaternion extra)
 {
     var v = f.Vessel;
     var forward = Vector3.zero;
     var up = Vector3.zero;
     var rotationReference = Quaternion.identity;
     switch (frame)
     {
         case ReferenceFrame.Orbit:
             forward = v.GetObtVelocity();
             up = (v.mainBody.position - v.CoM);
             break;
         case ReferenceFrame.Surface:
             forward = v.GetSrfVelocity();
             up = (v.mainBody.position - v.CoM);
             break;
         case ReferenceFrame.North:
             up = (v.mainBody.position - v.CoM);
             forward = Vector3.Exclude(up,
                 v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius - v.CoM
              );
             break;
         case ReferenceFrame.Maneuver:
             up = v.transform.up;
             if (f.DelayedManeuver != null)
             {
                 forward = f.DelayedManeuver.GetBurnVector(v.orbit);
                 up = (v.mainBody.position - v.CoM);
             }
             else
             {
                 forward = v.GetObtVelocity();
                 up = (v.mainBody.position - v.CoM);
             }
             break;
         case ReferenceFrame.TargetVelocity:
             if (f.DelayedTarget != null && f.DelayedTarget is Vessel)
             {
                 forward = v.GetObtVelocity() - f.DelayedTarget.GetObtVelocity();
                 up = (v.mainBody.position - v.CoM);
             }
             else
             {
                 up = (v.mainBody.position - v.CoM);
                 forward = v.GetObtVelocity();
             }
             break;
         case ReferenceFrame.TargetParallel:
             if (f.DelayedTarget != null && f.DelayedTarget is Vessel)
             {
                 forward = f.DelayedTarget.GetTransform().position - v.CoM;
                 up = (v.mainBody.position - v.CoM);
             }
             else
             {
                 up = (v.mainBody.position - v.CoM);
                 forward = v.GetObtVelocity();
             }
             break;
     }
     Vector3.OrthoNormalize(ref forward, ref up);
     rotationReference = Quaternion.LookRotation(forward, up);
     switch (attitude)
     {
         case FlightAttitude.Prograde:
             break;
         case FlightAttitude.Retrograde:
             rotationReference = rotationReference * Quaternion.AngleAxis(180, Vector3.up);
             break;
         case FlightAttitude.NormalPlus:
             rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.up);
             break;
         case FlightAttitude.NormalMinus:
             rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.down);
             break;
         case FlightAttitude.RadialPlus:
             rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.right);
             break;
         case FlightAttitude.RadialMinus:
             rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.left);
             break;
         case FlightAttitude.Surface:
             rotationReference = rotationReference * extra;
             break;
     }
     HoldOrientation(fs, f, rotationReference);
 }
Example #16
0
 /// <summary>
 /// Reset the modes
 /// </summary>
 public void Reset()
 {
     // get active command
     mMode = ComputerMode.Off;
     mAttitude = FlightAttitude.Null;
 }
Example #17
0
        /// <summary>
        /// Get the current active FlightMode and map it to the Computermode
        /// </summary>
        public void getActiveFlightMode()
        {
            // check the current flight mode
            if (mFlightComputer.currentFlightMode == null)
            {
                Reset();
                return;
            }

            // get active command
            SimpleTypes.ComputerModeMapper mappedCommand = mFlightComputer.currentFlightMode.mapFlightMode();
            mMode = mappedCommand.computerMode;
            mAttitude = FlightAttitude.Null;

            if(mMode == ComputerMode.Orbital || mMode == ComputerMode.Surface || mMode == ComputerMode.TargetPos || mMode == ComputerMode.TargetVel)
                mAttitude = mappedCommand.computerAttitude;
        }
Example #18
0
        public static void HoldAttitude(FlightCtrlState fs, FlightComputer f, ReferenceFrame frame, FlightAttitude attitude, Quaternion extra)
        {
            var v       = f.Vessel;
            var forward = Vector3.zero;
            var up      = Vector3.zero;

            switch (frame)
            {
            case ReferenceFrame.Orbit:
                forward = v.GetObtVelocity();
                up      = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.Surface:
                forward = v.GetSrfVelocity();
                up      = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.North:
                up      = (v.mainBody.position - v.CoM);
                forward = Vector3.Exclude(up,
                                          v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius - v.CoM
                                          );
                break;

            case ReferenceFrame.Maneuver:
                if (f.DelayedManeuver != null)
                {
                    forward = f.DelayedManeuver.GetBurnVector(v.orbit);
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    forward = v.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                break;

            case ReferenceFrame.TargetVelocity:
                if (f.DelayedTarget is Vessel)
                {
                    forward = v.GetObtVelocity() - f.DelayedTarget.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;

            case ReferenceFrame.TargetParallel:
                if (f.DelayedTarget is Vessel)
                {
                    forward = f.DelayedTarget.GetTransform().position - v.CoM;
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;
            }
            Vector3.OrthoNormalize(ref forward, ref up);
            Quaternion rotationReference = Quaternion.LookRotation(forward, up);

            switch (attitude)
            {
            case FlightAttitude.Prograde:
                break;

            case FlightAttitude.Retrograde:
                rotationReference = rotationReference * Quaternion.AngleAxis(180, Vector3.up);
                break;

            case FlightAttitude.NormalPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.up);
                break;

            case FlightAttitude.NormalMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.down);
                break;

            case FlightAttitude.RadialPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.right);
                break;

            case FlightAttitude.RadialMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.left);
                break;

            case FlightAttitude.Surface:
                rotationReference = rotationReference * extra;
                break;
            }
            HoldOrientation(fs, f, rotationReference);
        }
Example #19
0
        public static void HoldAttitude(FlightCtrlState fs, FlightComputer f, ReferenceFrame frame, FlightAttitude attitude, Quaternion extra)
        {
            var  v          = f.Vessel;
            var  forward    = Vector3.zero;
            var  up         = Vector3.zero;
            bool ignoreRoll = false;

            switch (frame)
            {
            case ReferenceFrame.Orbit:
                ignoreRoll = true;
                forward    = v.GetObtVelocity();
                up         = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.Surface:
                ignoreRoll = true;
                forward    = v.GetSrfVelocity();
                up         = (v.mainBody.position - v.CoM);
                break;

            case ReferenceFrame.North:
                up      = (v.mainBody.position - v.CoM);
                forward = Vector3.ProjectOnPlane(v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius - v.CoM, up);
                break;

            case ReferenceFrame.Maneuver:
                ignoreRoll = true;

                if (f.Vessel.patchedConicSolver == null)    //scenario: two vessels within physical range with FC attitude hold cmds. Unloaded one doesn't have solver instance
                {
                    f.Vessel.AttachPatchedConicsSolver();
                    f.Vessel.patchedConicSolver.Update();
                }

                if (f.Vessel.patchedConicSolver.maneuverNodes.Count != 0)
                {
                    forward = f.Vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(v.orbit);
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    forward = v.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                break;

            case ReferenceFrame.TargetVelocity:
                // f.DelayedTarget may be any ITargetable, including a planet
                // Velocity matching only makes sense for vessels and part modules
                // Can test for Vessel but not PartModule, so instead test that it's not the third case (CelestialBody)
                if (f.DelayedTarget != null && !(f.DelayedTarget is CelestialBody))
                {
                    forward = v.GetObtVelocity() - f.DelayedTarget.GetObtVelocity();
                    up      = (v.mainBody.position - v.CoM);
                }
                else
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;

            case ReferenceFrame.TargetParallel:
                if (f.DelayedTarget != null)     // either target vessel or celestial body
                {
                    forward = f.DelayedTarget.GetTransform().position - v.CoM;
                    up      = (v.mainBody.position - v.CoM);
                }
                else     // no target to aim; default to orbital prograde
                {
                    up      = (v.mainBody.position - v.CoM);
                    forward = v.GetObtVelocity();
                }
                break;
            }
            Vector3.OrthoNormalize(ref forward, ref up);
            Quaternion rotationReference = Quaternion.LookRotation(forward, up);

            switch (attitude)
            {
            case FlightAttitude.Prograde:
                break;

            case FlightAttitude.Retrograde:
                rotationReference = rotationReference * Quaternion.AngleAxis(180, Vector3.up);
                break;

            case FlightAttitude.NormalPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.up);
                break;

            case FlightAttitude.NormalMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.down);
                break;

            case FlightAttitude.RadialPlus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.right);
                break;

            case FlightAttitude.RadialMinus:
                rotationReference = rotationReference * Quaternion.AngleAxis(90, Vector3.left);
                break;

            case FlightAttitude.Surface:
                rotationReference = rotationReference * extra;
                break;
            }
            HoldOrientation(fs, f, rotationReference, ignoreRoll);
        }