static void Fly(Vessel vessel) { if (!controlDelegates.ContainsKey(vessel)) { Action <FlightCtrlState> action = s => OnFlyByWire(vessel, s); controlDelegates [vessel] = action; vessel.OnFlyByWire += new FlightInputCallback(action); } if (RemoteTech.IsAvailable && !remoteTechSanctionedDelegates.Contains(vessel) && RemoteTech.HasFlightComputer(vessel.id)) { RemoteTech.AddSanctionedPilot(vessel.id, controlDelegates [vessel]); remoteTechSanctionedDelegates.Add(vessel); } }
/// <summary> /// Handle throttle quirky operation... /// </summary> static void HandleThrottle(Vessel vessel, ControlInputs inputs) { if (!inputs.ThrottleUpdated) { return; } if (FlightGlobals.ActiveVessel != vessel) { return; } if (RemoteTech.IsAvailable && !(RemoteTech.HasLocalControl(vessel.id) || RemoteTech.HasAnyConnection(vessel.id))) { return; } FlightInputHandler.state.mainThrottle = inputs.Throttle; inputs.Throttle = 0f; inputs.ThrottleUpdated = false; }
public double SignalDelayToVessel(Vessel other) { return(RemoteTech.GetSignalDelayToSatellite(vesselId, other.Id)); }
private bool Coord(RemoteTech.FlightComputer.Commands.DriveCommand dc, FlightCtrlState fs) { float deg = RTUtil.AngleBetween(RoverHDG, TargetHDG), speed = RoverSpeed; Delta = Vector3.Distance(mVessel.CoM, TargetPos); DeltaT = Delta / speed; if (Delta > Math.Abs(deg) / 36) { fs.wheelThrottle = mThrottlePID.Control(BrakeSpeed(dc.speed, speed) - speed); if (ForwardAxis != Vector3.zero) fs.wheelSteer = mWheelPID.Control(deg); return false; } else { fs.wheelThrottle = 0; fs.wheelSteer = 0; mVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); dc.mode = RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Off; return true; } }
public void InitMode(RemoteTech.FlightComputer.Commands.DriveCommand dc) { if (mVessel == null) { MonoBehaviour.print("mVessel was null!!!!!!!!!!!!!!!!!!!!!!!!!!"); } ForwardAxis = Vector3.zero; mRoverAlt = (float)mVessel.altitude; mRoverLat = (float)mVessel.latitude; mRoverLon = (float)mVessel.longitude; Delta = 0; DeltaT = 0; brakeDist = 0; switch (dc.mode) { case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Turn: mRoverRot = mVessel.ReferenceTransform.rotation; break; case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Distance: mWheelPID.setClamp(-1, 1); break; case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.DistanceHeading: mWheelPID.setClamp(-dc.steering, dc.steering); break; case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Coord: mWheelPID.setClamp(-dc.steering, dc.steering); mTargetLat = dc.target; mTargetLon = dc.target2; break; } mThrottlePID.Reset(); mWheelPID.Reset(); mVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, false); }
private bool DistanceHeading(RemoteTech.FlightComputer.Commands.DriveCommand dc, FlightCtrlState fs) { float speed = RoverSpeed; Delta = Math.Abs(dc.target) - Vector3.Distance(RoverOrigPos, mVessel.CoM); DeltaT = Delta / speed; if (Delta > 0) { fs.wheelThrottle = mThrottlePID.Control(BrakeSpeed(dc.speed, speed) - speed); if (ForwardAxis != Vector3.zero) fs.wheelSteer = mWheelPID.Control(RTUtil.AngleBetween(RoverHDG, dc.target2)); return false; } else { fs.wheelThrottle = 0; fs.wheelSteer = 0; mVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); dc.mode = RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Off; return true; } }
private bool Turn(RemoteTech.FlightComputer.Commands.DriveCommand dc, FlightCtrlState fs) { Delta = Math.Abs(Quaternion.Angle(mRoverRot, mVessel.ReferenceTransform.rotation)); DeltaT = Delta / mVessel.angularVelocity.magnitude; if (Delta < dc.target) { fs.wheelThrottle = mThrottlePID.Control(dc.speed - RoverSpeed); fs.wheelSteer = dc.steering; return false; } else { fs.wheelThrottle = 0; fs.wheelSteer = 0; mVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); dc.mode = RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Off; return true; } }
public bool Drive(RemoteTech.FlightComputer.Commands.DriveCommand dc, FlightCtrlState fs) { if (dc != null) { if (mVessel.srf_velocity.magnitude > 0.5) { float degForward = Mathf.Abs(RTUtil.ClampDegrees90(Vector3.Angle(mVessel.srf_velocity, mVessel.ReferenceTransform.forward))); float degUp = Mathf.Abs(RTUtil.ClampDegrees90(Vector3.Angle(mVessel.srf_velocity, mVessel.ReferenceTransform.up))); float degRight = Mathf.Abs(RTUtil.ClampDegrees90(Vector3.Angle(mVessel.srf_velocity, mVessel.ReferenceTransform.right))); if (degForward < degUp && degForward < degRight) ForwardAxis = Vector3.forward; else if (degRight < degUp && degRight < degForward) ForwardAxis = Vector3.right; else ForwardAxis = Vector3.up; } switch (dc.mode) { case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Turn: return Turn(dc, fs); case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Distance: return Distance(dc, fs); case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.DistanceHeading: return DistanceHeading(dc, fs); case RemoteTech.FlightComputer.Commands.DriveCommand.DriveMode.Coord: return Coord(dc, fs); } return true; } return true; }
public static void Config(this Panel p, Vessel v) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get info from the cache Vessel_Info vi = Cache.VesselInfo(v); // if not a valid vessel, leave the panel empty if (!vi.is_valid) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>VESSEL CONFIG</color>")); // time-out simulation if (p.Timeout(vi)) { return; } // get data from db VesselData vd = DB.Vessel(v); // toggle rendering string tooltip; if (Features.Signal || Features.Reliability) { p.SetSection("RENDERING"); } if (Features.Signal) { tooltip = "Render the connection line\nin mapview and tracking station"; p.SetContent("show links", string.Empty, tooltip); p.SetIcon(vd.cfg_showlink ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_showlink)); } if (Features.Reliability) { tooltip = "Highlight failed components"; p.SetContent("highlight malfunctions", string.Empty, tooltip); p.SetIcon(vd.cfg_highlights ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_highlights)); } // toggle messages p.SetSection("MESSAGES"); tooltip = "Receive a message when\nElectricCharge level is low"; p.SetContent("battery", string.Empty, tooltip); p.SetIcon(vd.cfg_ec ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_ec)); if (Features.Supplies) { tooltip = "Receive a message when\nsupply resources level is low"; p.SetContent("supply", string.Empty, tooltip); p.SetIcon(vd.cfg_supply ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_supply)); } if (Features.Signal || Features.KCommNet || RemoteTech.Enabled()) { tooltip = "Receive a message when signal is lost or obtained"; p.SetContent("signal", string.Empty, tooltip); p.SetIcon(vd.cfg_signal ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_signal)); } if (Features.Reliability) { tooltip = "Receive a message\nwhen a component fail"; p.SetContent("reliability", string.Empty, tooltip); p.SetIcon(vd.cfg_malfunction ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_malfunction)); } if (Features.SpaceWeather) { tooltip = "Receive a message\nduring CME events"; p.SetContent("storm", string.Empty, tooltip); p.SetIcon(vd.cfg_storm ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_storm)); } if (Features.Automation) { tooltip = "Receive a message when\nscripts are executed"; p.SetContent("script", string.Empty, tooltip); p.SetIcon(vd.cfg_script ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_script)); } }
/// <summary> /// Automatically guides the ship to face a desired orientation /// </summary> /// <param name="target">The desired orientation</param> /// <param name="c">The FlightCtrlState for the current vessel.</param> /// <param name="fc">The flight computer carrying out the slew</param> public static void SteerShipToward(Quaternion target, FlightCtrlState c, RemoteTech.FlightComputer fc) { // Add support for roll-less targets later -- Starstrider42 var fixedRoll = true; var vessel = fc.Vessel; var momentOfInertia = GetTrueMoI(vessel); var vesselReference = vessel.GetTransform(); //--------------------------------------- // Copied almost verbatim from MechJeb master on June 27, 2014 -- Starstrider42 Quaternion delta = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vesselReference.rotation) * target); Vector3d torque = GetTorque(vessel, c.mainThrottle); Vector3d inertia = GetEffectiveInertia(vessel, torque); //err.Scale(SwapYZ(Vector3d.Scale(MoI, Inverse(torque)))); Vector3d normFactor = SwapYZ(Vector3d.Scale(momentOfInertia, Inverse(torque))); // Find out the real shorter way to turn were we want to. // Thanks to HoneyFox Vector3d tgtLocalUp = vesselReference.transform.rotation.Inverse() * target * Vector3d.forward; Vector3d curLocalUp = Vector3d.up; double turnAngle = Math.Abs(Vector3d.Angle(curLocalUp, tgtLocalUp)); var rotDirection = new Vector2d(tgtLocalUp.x, tgtLocalUp.z); rotDirection = rotDirection.normalized * turnAngle / 180.0f; var err = new Vector3d( -rotDirection.y * Math.PI, rotDirection.x * Math.PI, fixedRoll ? ((delta.eulerAngles.z > 180) ? (delta.eulerAngles.z - 360.0F) : delta.eulerAngles.z) * Math.PI / 180.0F : 0F ); err += SwapYZ(inertia) / 2; err = new Vector3d(Math.Max(-Math.PI, Math.Min(Math.PI, err.x)), Math.Max(-Math.PI, Math.Min(Math.PI, err.y)), Math.Max(-Math.PI, Math.Min(Math.PI, err.z))); err.Scale(normFactor); // angular velocity: Vector3d omega = SwapYZ(vessel.angularVelocity); omega.Scale(normFactor); Vector3d pidAction = fc.pid.Compute(err, omega); // low pass filter, wf = 1/Tf: Vector3d act = fc.lastAct + (pidAction - fc.lastAct) * (1 / ((fc.Tf / TimeWarp.fixedDeltaTime) + 1)); fc.lastAct = act; // end MechJeb import //--------------------------------------- float precision = Mathf.Clamp((float)(torque.x * 20f / momentOfInertia.magnitude), 0.5f, 10f); float driveLimit = Mathf.Clamp01((float)(err.magnitude * 380.0f / precision)); act.x = Mathf.Clamp((float)act.x, -driveLimit, driveLimit); act.y = Mathf.Clamp((float)act.y, -driveLimit, driveLimit); act.z = Mathf.Clamp((float)act.z, -driveLimit, driveLimit); c.roll = Mathf.Clamp((float)(c.roll + act.z), -driveLimit, driveLimit); c.pitch = Mathf.Clamp((float)(c.pitch + act.x), -driveLimit, driveLimit); c.yaw = Mathf.Clamp((float)(c.yaw + act.y), -driveLimit, driveLimit); }