private Tuple <double, double, double> inerVectorToRPY(Tuple <double, double, double> unitVector) { double roll = 0; double pitch = 0; double yaw = 0; // VECTOR INFO: X = Arbitrary out of Equator, Y = Through North Pole of body, Z = Arbitrary out of Equator (90° between X and Z) // YAW yaw = Helper.rad2deg(Math.Atan2(unitVector.Item1, unitVector.Item3) * -1) + 90; if (yaw < 0) { yaw += 360; // Limit values } // PITCH double yawLength = Math.Sqrt(Math.Pow(unitVector.Item1, 2) + Math.Pow(unitVector.Item3, 2)); pitch = Helper.rad2deg(Math.Atan2(unitVector.Item2, yawLength)); return(new Tuple <double, double, double>(roll, pitch, yaw)); }
private Tuple <double, double, double> surfVectorToRPY(Tuple <double, double, double> unitVector) { double roll = 0; double pitch = 0; double yaw = 0; double angle = 0; // VECTOR INFO: X = Up, Y = North, Z = East // YAW yaw = Helper.rad2deg(Math.Atan2(unitVector.Item2, unitVector.Item3) * -1) + 90; if (yaw < 0) { yaw += 360; // Limit values } // PITCH double yawLength = Math.Sqrt(Math.Pow(unitVector.Item2, 2) + Math.Pow(unitVector.Item3, 2)); pitch = Helper.rad2deg(Math.Atan2(unitVector.Item1, yawLength)); return(new Tuple <double, double, double>(roll, pitch, yaw)); }
public override void updateLocalElements(object sender, EventArgs e) { // Re-usable data variable for graph data List <List <KeyValuePair <double, double?> > > data = new List <List <KeyValuePair <double, double?> > >(); List <Plot.Type> types = new List <Plot.Type>(); if (form.form.connected && form.form.krpc.CurrentGameScene == GameScene.Flight) { inertRotation = screenStreams.GetData(DataType.flight_inertial_rotation); MET = screenStreams.GetData(DataType.vessel_MET); MeanAltitude = screenStreams.GetData(DataType.flight_meanAltitude); SurfaceAltitude = screenStreams.GetData(DataType.flight_surfaceAltitude); ApoapsisAltitude = screenStreams.GetData(DataType.orbit_apoapsisAltitude); PeriapsisAltitude = screenStreams.GetData(DataType.orbit_periapsisAltitude); TimeToApoapsis = screenStreams.GetData(DataType.orbit_timeToApoapsis); TimeToPeriapsis = screenStreams.GetData(DataType.orbit_timeToPeriapsis); Inclination = screenStreams.GetData(DataType.orbit_inclination); Eccentricity = screenStreams.GetData(DataType.orbit_eccentricity); OrbSpeed = screenStreams.GetData(DataType.orbit_speed); Speed = screenStreams.GetData(DataType.flight_speed); EquatorialRadius = screenStreams.GetData(DataType.body_radius); GravitationalParameter = screenStreams.GetData(DataType.body_gravityParameter); Roll = screenStreams.GetData(DataType.flight_roll); Pitch = screenStreams.GetData(DataType.flight_pitch); Yaw = screenStreams.GetData(DataType.flight_heading); BodyName = screenStreams.GetData(DataType.body_name); lat = screenStreams.GetData(DataType.flight_latitude); lon = screenStreams.GetData(DataType.flight_longitude); AtmosphereDensity = screenStreams.GetData(DataType.flight_atmosphereDensity); StaticPressure = screenStreams.GetData(DataType.flight_staticPressure); DynamicPressure = screenStreams.GetData(DataType.flight_dynamicPressure); LiquidFuelMax = screenStreams.GetData(DataType.resource_stage_max_liquidFuel); LiquidFuelAmount = screenStreams.GetData(DataType.resource_stage_amount_liquidFuel); OxidizerMax = screenStreams.GetData(DataType.resource_stage_max_oxidizer); OxidizerAmount = screenStreams.GetData(DataType.resource_stage_amount_oxidizer); MonoPropellantMax = screenStreams.GetData(DataType.resource_stage_max_monoPropellant); MonoPropellantAmount = screenStreams.GetData(DataType.resource_stage_amount_monoPropellant); ElectricChargeMax = screenStreams.GetData(DataType.resource_stage_max_electricCharge); ElectricChargeAmount = screenStreams.GetData(DataType.resource_stage_amount_electricCharge); SAS = screenStreams.GetData(DataType.control_SAS); RCS = screenStreams.GetData(DataType.control_RCS); Gear = screenStreams.GetData(DataType.control_gear); Brakes = screenStreams.GetData(DataType.control_brakes); Lights = screenStreams.GetData(DataType.control_lights); Abort = screenStreams.GetData(DataType.control_abort); GForce = screenStreams.GetData(DataType.flight_gForce); screenLabels[0].Text = " LT: " + Helper.timeString(DateTime.Now.TimeOfDay.TotalSeconds); screenLabels[1].Text = "MET: " + Helper.timeString(MET, 3); // Orbit info screenLabels[30].Text = " Alt: " + Helper.prtlen(Math.Round(MeanAltitude).ToString(), 9, Helper.Align.RIGHT); // Altitude screenLabels[31].Text = " Apoapsis: " + Helper.prtlen(Math.Round(ApoapsisAltitude).ToString(), 9, Helper.Align.RIGHT); // Apoapsis screenLabels[32].Text = "Periapsis: " + Helper.prtlen(Math.Round(PeriapsisAltitude).ToString(), 9, Helper.Align.RIGHT); // Periapasis screenLabels[33].Text = " TtA: " + Helper.prtlen(Helper.timeString(TimeToApoapsis), 9, Helper.Align.RIGHT); // Time to Apoapsis screenLabels[34].Text = " TtP: " + Helper.prtlen(Helper.timeString(TimeToPeriapsis), 9, Helper.Align.RIGHT); // Time to Periapsis screenLabels[35].Text = " Inc: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(Inclination), 3), 9, Helper.Align.RIGHT); // Inclination screenLabels[36].Text = " Ecc: " + Helper.prtlen(Helper.toFixed(Eccentricity, 3), 9, Helper.Align.RIGHT); // Eccentricity screenLabels[37].Text = " Orb. Vel: " + Helper.prtlen(Helper.toFixed(OrbSpeed, 1), 9, Helper.Align.RIGHT); // Orbit Velocity screenLabels[38].Text = " Sur. Vel: " + Helper.prtlen(Helper.toFixed(Speed, 1), 9, Helper.Align.RIGHT); // Surface Velocity // Orbit Targets and Deltas double tgtA = 0, tgtP = 0; if (double.TryParse(screenInputs[0].Text, out tgtA) && double.TryParse(screenInputs[1].Text, out tgtP)) { double sMa = (tgtA + tgtP + (EquatorialRadius * 2)) / 2; double tgtEcc = (sMa - (tgtP + EquatorialRadius)) / sMa; screenLabels[60].Text = Helper.prtlen(Helper.toFixed(tgtEcc, 3), 8, Helper.Align.RIGHT); // Target Eccentricity screenLabels[67].Text = Helper.prtlen(Helper.toFixed(Eccentricity - tgtEcc, 3), 8, Helper.Align.RIGHT); // Delta Eccentricity } if (double.TryParse(screenInputs[0].Text, out tgtA)) { screenLabels[65].Text = Helper.prtlen(Math.Round(tgtA - ApoapsisAltitude).ToString(), 8, Helper.Align.RIGHT); } // Delta Apoapsis if (double.TryParse(screenInputs[1].Text, out tgtP)) { screenLabels[66].Text = Helper.prtlen(Math.Round(tgtP - PeriapsisAltitude).ToString(), 8, Helper.Align.RIGHT); } // Delta Periapsis double u = GravitationalParameter; double a = EquatorialRadius + tgtA; double r = EquatorialRadius + tgtA; double v = Math.Sqrt(u * ((2 / r) - (1 / a))); screenLabels[61].Text = Helper.prtlen(Helper.toFixed(v, 1), 8, Helper.Align.RIGHT); // Target Obital Velocity at Apoapsis // POSITION AND ROTATION INFO Tuple <double, double, double> iRPY = Helper.RPYFromQuaternion(inertRotation, "INER"); inertRoll = (float)iRPY.Item1; inertPitch = (float)iRPY.Item2; inertYaw = (float)iRPY.Item3; screenLabels[46].Text = "R: " + Helper.prtlen(Helper.toFixed(Roll, 2), 7, Helper.Align.RIGHT) + " " + Helper.prtlen(Helper.toFixed(inertRoll, 2), 7, Helper.Align.RIGHT); screenLabels[47].Text = "P: " + Helper.prtlen(Helper.toFixed(Pitch, 2), 7, Helper.Align.RIGHT) + " " + Helper.prtlen(Helper.toFixed(inertPitch, 2), 7, Helper.Align.RIGHT); screenLabels[48].Text = "Y: " + Helper.prtlen(Helper.toFixed(Yaw, 2), 7, Helper.Align.RIGHT) + " " + Helper.prtlen(Helper.toFixed(inertYaw, 2), 7, Helper.Align.RIGHT); screenLabels[40].Text = " Body: " + Helper.prtlen(BodyName, 9, Helper.Align.RIGHT); screenLabels[41].Text = " Lat: " + Helper.prtlen(Helper.toFixed(lat, 5), 9, Helper.Align.RIGHT); screenLabels[42].Text = " Lon: " + Helper.prtlen(Helper.toFixed(lon, 5), 9, Helper.Align.RIGHT); screenLabels[43].Text = " Atm.Den: " + Helper.prtlen(Helper.toFixed(AtmosphereDensity, 1), 9, Helper.Align.RIGHT) + " Radar Alt: " + Helper.prtlen(Math.Round(SurfaceAltitude).ToString(), 7, Helper.Align.RIGHT); screenLabels[44].Text = " Atm.Pre: " + Helper.prtlen(Math.Round(StaticPressure).ToString(), 9, Helper.Align.RIGHT); screenLabels[45].Text = " Dyn.Pre: " + Helper.prtlen(Math.Round(DynamicPressure).ToString(), 9, Helper.Align.RIGHT) + " G-Force: " + Helper.prtlen(Helper.toFixed(GForce, 2), 7, Helper.Align.RIGHT); // Supplies double mF = LiquidFuelMax; double cF = LiquidFuelAmount; double mO = OxidizerMax; double cO = OxidizerAmount; double mM = MonoPropellantMax; double cM = MonoPropellantAmount; double mE = ElectricChargeMax; double cE = ElectricChargeAmount; screenLabels[50].Text = " LF LO MP EC"; screenLabels[51].Text = "STAGE:" + Helper.prtlen(Math.Round(cF).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round(cO).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Helper.toFixed(cM, 2), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round(cE).ToString(), 7, Helper.Align.RIGHT); screenLabels[52].Text = " %:" + Helper.prtlen(Math.Round((cF / mF) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cO / mO) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cM / mM) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cE / mE) * 100).ToString(), 7, Helper.Align.RIGHT); mF = screenStreams.GetData(DataType.resource_total_max_liquidFuel); cF = screenStreams.GetData(DataType.resource_total_amount_liquidFuel); mO = screenStreams.GetData(DataType.resource_total_max_oxidizer); cO = screenStreams.GetData(DataType.resource_total_amount_oxidizer); mM = screenStreams.GetData(DataType.resource_total_max_monoPropellant); cM = screenStreams.GetData(DataType.resource_total_amount_monoPropellant); mE = screenStreams.GetData(DataType.resource_total_max_electricCharge); cE = screenStreams.GetData(DataType.resource_total_amount_electricCharge); screenLabels[54].Text = " TOT:" + Helper.prtlen(Math.Round(cF).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round(cO).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Helper.toFixed(cM, 2), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round(cE).ToString(), 7, Helper.Align.RIGHT); screenLabels[55].Text = " %:" + Helper.prtlen(Math.Round((cF / mF) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cO / mO) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cM / mM) * 100).ToString(), 7, Helper.Align.RIGHT) + Helper.prtlen(Math.Round((cE / mE) * 100).ToString(), 7, Helper.Align.RIGHT); // Status if (SAS) { screenIndicators[0].setStatus(Indicator.status.GREEN); } else { screenIndicators[0].setStatus(Indicator.status.OFF); } // SAS if (RCS) { screenIndicators[1].setStatus(Indicator.status.GREEN); } else { screenIndicators[1].setStatus(Indicator.status.OFF); } // RCS if (Gear) { screenIndicators[2].setStatus(Indicator.status.GREEN); } else { screenIndicators[2].setStatus(Indicator.status.OFF); } // GEAR if (Brakes) { screenIndicators[3].setStatus(Indicator.status.RED); } else { screenIndicators[3].setStatus(Indicator.status.OFF); } // Break if (Lights) { screenIndicators[4].setStatus(Indicator.status.AMBER); } else { screenIndicators[4].setStatus(Indicator.status.OFF); } // Lights if (Abort) { screenIndicators[5].setStatus(Indicator.status.RED); } else { screenIndicators[5].setStatus(Indicator.status.OFF); } // Abort if (GForce > 4) { screenIndicators[7].setStatus(Indicator.status.AMBER); } else { screenIndicators[7].setStatus(Indicator.status.OFF); } // G High double maxR = mE; double curR = cE; if (curR / maxR > 0.95) { screenIndicators[6].setStatus(Indicator.status.GREEN); } else { screenIndicators[6].setStatus(Indicator.status.OFF); } // Power High if (curR / maxR < 0.1) { screenIndicators[9].setStatus(Indicator.status.RED); } else { screenIndicators[9].setStatus(Indicator.status.OFF); } // Power Low maxR = mM; curR = cM; if (curR / maxR < 0.1) { screenIndicators[10].setStatus(Indicator.status.RED); } else { screenIndicators[10].setStatus(Indicator.status.OFF); } // Monopropellant Low maxR = mF; curR = cF; if (curR / maxR < 0.1) { screenIndicators[11].setStatus(Indicator.status.RED); } else { screenIndicators[11].setStatus(Indicator.status.OFF); } // Fuel Low maxR = mO; curR = cO; if (curR / maxR < 0.1) { screenIndicators[8].setStatus(Indicator.status.RED); } else { screenIndicators[8].setStatus(Indicator.status.OFF); } // LOW Low // Graphs int xMin = screenCharts[0].findMinX(chartData["altitudeTime"]); int xMax = screenCharts[0].findMaxX(chartData["altitudeTime"]); List <KeyValuePair <double, double?> > targetA = new List <KeyValuePair <double, double?> >(); targetA.Add(new KeyValuePair <double, double?>(xMin, tgtA)); targetA.Add(new KeyValuePair <double, double?>(xMax, tgtA)); List <KeyValuePair <double, double?> > targetP = new List <KeyValuePair <double, double?> >(); targetP.Add(new KeyValuePair <double, double?>(xMin, tgtP)); targetP.Add(new KeyValuePair <double, double?>(xMax, tgtP)); data = new List <List <KeyValuePair <double, double?> > >(); types = new List <Plot.Type>(); data.Add(targetA); types.Add(Plot.Type.LINE); data.Add(targetP); types.Add(Plot.Type.LINE); data.Add(chartData["apoapsisTime"]); types.Add(Plot.Type.LINE); data.Add(chartData["periapsisTime"]); types.Add(Plot.Type.LINE); data.Add(chartData["altitudeTime"]); types.Add(Plot.Type.LINE); screenCharts[0].setData(data, types, false); data = new List <List <KeyValuePair <double, double?> > >(); types = new List <Plot.Type>(); data.Add(chartData["geeTime"]); types.Add(Plot.Type.LINE); data.Add(chartData["dynPresTime"]); types.Add(Plot.Type.LINE); screenCharts[1].setData(data, types, true); } }
public override void updateLocalElements(object sender, EventArgs e) { screenLabels[2].Text = "LT: " + Helper.timeString(DateTime.Now.TimeOfDay.TotalSeconds); if (form.form.connected && form.form.krpc.CurrentGameScene == GameScene.Flight) { MET = screenStreams.GetData(DataType.vessel_MET); UT = screenStreams.GetData(DataType.spacecenter_universial_time); nodes = screenStreams.GetData(DataType.control_nodes); frame = screenStreams.GetData(DataType.body_nonRotatingReferenceFrame); vesselFrame = screenStreams.GetData(DataType.vessel_referenceFrame); screenLabels[3].Text = "MET: " + Helper.timeString(MET, 3); for (int i = 1; i <= 2; i++) { if (nodes != null && nodes.Count >= i) { string metS = Helper.timeString(nodes[i - 1].UT - UT + MET, true, 3); string remS = Helper.timeString(nodes[i - 1].TimeTo, true, 3); screenLabels[(i * 20) + 0].Text = "────────────── NODE " + (i - 1).ToString() + " ─────────────"; screenLabels[(i * 20) + 1].Text = " MET: " + metS; screenLabels[(i * 20) + 2].Text = " TIME TO: " + remS; screenLabels[(i * 20) + 4].Text = " PROGRADE: " + Helper.prtlen(Helper.toFixed(nodes[i - 1].Prograde, 2), 10); screenLabels[(i * 20) + 5].Text = " NORMAL: " + Helper.prtlen(Helper.toFixed(nodes[i - 1].Normal, 2), 10); screenLabels[(i * 20) + 6].Text = " RADIAL: " + Helper.prtlen(Helper.toFixed(nodes[i - 1].Radial, 2), 10); screenLabels[(i * 20) + 8].Text = " TOTAL ΔV: " + Helper.prtlen(Helper.toFixed(nodes[i - 1].DeltaV, 2), 10); screenLabels[(i * 20) + 9].Text = " REM. ΔV: " + Helper.prtlen(Helper.toFixed(nodes[i - 1].RemainingDeltaV, 2), 10); Tuple <double, double, double> rot = Helper.RPYfromVector(nodes[i - 1].Direction(frame), vesselFrame, frame, "INER"); screenLabels[(i * 20) + 11].Text = " ┌──────── INER ────────┐"; screenLabels[(i * 20) + 12].Text = " ROLL PITCH YAW"; screenLabels[(i * 20) + 13].Text = " ROT: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(rot.Item1), 2), 7) + " " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(rot.Item2), 2), 7) + " " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(rot.Item3), 2), 7); Tuple <double, double, double> dir = nodes[i - 1].BurnVector(frame); Tuple <double, double, double> rem = nodes[i - 1].RemainingBurnVector(frame); screenLabels[(i * 20) + 15].Text = " ┌──────── INER ────────┐"; screenLabels[(i * 20) + 16].Text = " Vx Vy Vz"; screenLabels[(i * 20) + 17].Text = " VECTOR: " + Helper.prtlen(Helper.toFixed(dir.Item1, 2), 7) + " " + Helper.prtlen(Helper.toFixed(dir.Item3, 2), 7) + " " + Helper.prtlen(Helper.toFixed(dir.Item2, 2), 7); screenLabels[(i * 20) + 18].Text = " REM VECT: " + Helper.prtlen(Helper.toFixed(rem.Item1, 2), 7) + " " + Helper.prtlen(Helper.toFixed(rem.Item3, 2), 7) + " " + Helper.prtlen(Helper.toFixed(rem.Item2, 2), 7); } else { screenLabels[(i * 20) + 0].Text = "───────────────────────────────────"; for (int n = 1; n <= 9; n++) { screenLabels[(i * 20) + n].Text = ""; } } } } }
private void MakeOrbitConstants(Graphics g, Orbit orbit, bool relativeToParent, double time, string debugstr, bool relativeREF) { float x, y; double alpha; double r; double REF = 0; // Degress from x-right double bodyInc; if (orbit.Body.Name == "Sun") { bodyInc = 0; } else { bodyInc = orbit.Body.Orbit.Inclination; if (relativeREF) { if (time != -1) { if (bodyInc > Helper.deg2rad(90) && bodyInc <= Helper.deg2rad(270)) { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode + orbit.Body.Orbit.ArgumentOfPeriapsis + orbit.Body.Orbit.TrueAnomalyAtUT(time); } else { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode - orbit.Body.Orbit.ArgumentOfPeriapsis - orbit.Body.Orbit.TrueAnomalyAtUT(time); } } else { if (bodyInc > Helper.deg2rad(90) && bodyInc <= Helper.deg2rad(270)) { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode + orbit.Body.Orbit.ArgumentOfPeriapsis + orbit.Body.Orbit.TrueAnomaly; } else { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode - orbit.Body.Orbit.ArgumentOfPeriapsis - orbit.Body.Orbit.TrueAnomaly; } } } } eccentricity = orbit.Eccentricity; inclination = orbit.Inclination; trueAnomaly = orbit.TrueAnomaly; bodyOrbit = orbit.Body.Orbit; if (eccentricity <= 0.00001) { // SET EVERYTHING TO 0 thetaZero = 0; thetaZeroNoREF = 0; alphaZero = 0; directrix = orbit.Periapsis; x = (float)((orbit.Periapsis * scaler) + graphCenterX); P1 = new PointF(x, (float)(graphCenterY + satY)); P2 = new PointF(-x, (float)(graphCenterY - satY)); } else { if (inclination > Helper.deg2rad(90) && inclination <= Helper.deg2rad(270)) { thetaZeroNoREF = 0 - orbit.LongitudeOfAscendingNode + orbit.ArgumentOfPeriapsis; // Rotation clockwise from x-direction (Right) of Apoapse thetaZero = REF + thetaZeroNoREF; alphaZero = REF - orbit.LongitudeOfAscendingNode; // Decending Node } else { thetaZeroNoREF = 0 - orbit.LongitudeOfAscendingNode - orbit.ArgumentOfPeriapsis; // Rotation counterclockwise from x-direction (Right) of Apoapse thetaZero = REF + thetaZeroNoREF; alphaZero = REF - orbit.LongitudeOfAscendingNode; // Decending Node } directrix = (orbit.Periapsis / eccentricity) + orbit.Periapsis; //Inclination point 1 alpha = alphaZero; r = (eccentricity * directrix) / (1 + (eccentricity * Math.Cos(alpha - thetaZero))); x = (float)((r * Math.Cos(alpha) * scaler) + graphCenterX + satX); y = (float)((r * Math.Sin(alpha) * scaler) + graphCenterY - satY); P1 = new PointF(x, y); //g.FillEllipse(burnBrush, x - 5, y - 5, 10, 10); //Inclination point 2 alpha = Helper.deg2rad(180) + alphaZero; r = (eccentricity * directrix) / (1 + (eccentricity * Math.Cos(alpha - thetaZero))); x = (float)((r * Math.Cos(alpha) * scaler) + graphCenterX + satX); y = (float)((r * Math.Sin(alpha) * scaler) + graphCenterY - satY); P2 = new PointF(x, y); //g.FillEllipse(burnBrush, x - 5, y - 5, 10, 10); } // DEBUG LINES if (debug) { PointF center = new PointF((float)(graphCenterX + satX), (float)(graphCenterY - satY)); x = (float)((200 * Math.Cos(thetaZero)) + center.X); y = (float)((200 * Math.Sin(thetaZero)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("ThetaZero " + debugstr, font, textBrush, x, y); x = (float)((200 * Math.Cos(alphaZero)) + center.X); y = (float)((200 * Math.Sin(alphaZero)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("AlphaZero " + debugstr, font, textBrush, x, y); x = (float)((200 * Math.Cos(REF)) + center.X); y = (float)((200 * Math.Sin(REF)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("REF " + debugstr, font, textBrush, x, y); g.DrawArc(burnPen, center.X - 180, center.Y - 180, 360, 360, (float)Helper.rad2deg(REF), (float)Helper.rad2deg(alphaZero - REF)); g.DrawArc(burnPen, center.X - 160, center.Y - 160, 320, 320, (float)Helper.rad2deg(alphaZero), (float)Helper.rad2deg(thetaZero - alphaZero)); } }
protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; // DEBUG TEST //g.FillRectangle(new SolidBrush(Color.Maroon), 0, 0, this.Width, this.Height); // Check for body and orbitset if (currentOrbit != null) { // Determine scaler int maxSizePx; if (this.Width < this.Height) { maxSizePx = this.Width; } else { maxSizePx = this.Height; } // Get biggest apopapsis of satellites double satMaxApo = 0; // Check of vessel orbit is biggest if (currentOrbit.Apoapsis > satMaxApo) { double maxDist = (currentOrbit.Apoapsis * 2.25) / zoom; // The .25 is to have some margin to the edges of the graph scaler = maxSizePx / maxDist; } else { scaler = maxSizePx / ((satMaxApo * 2.25) / zoom); } // Set Center of graph graphCenterX = (Width / 2); graphCenterY = (Height / 2); // Add manual offset graphCenterX += (float)(slideX + slideXtmp); graphCenterY += (float)(slideY + slideYtmp); // Draw Body float left = graphCenterX - (float)(currentOrbit.Body.EquatorialRadius * scaler); float top = graphCenterY - (float)(currentOrbit.Body.EquatorialRadius * scaler); float width = (float)(currentOrbit.Body.EquatorialRadius * 2 * scaler); float height = (float)(currentOrbit.Body.EquatorialRadius * 2 * scaler); RectangleF rect = new RectangleF(left, top, width, height); g.FillEllipse(bodyBrush, rect); // Draw satellites foreach (CelestialBody sat in bodySatellites) { Orbit orbit = sat.Orbit; MakeOrbitConstants(g, orbit); drawPatchedConic(g, orbit, 0, 360, orbitColor); drawCurrentPosition(g, orbit); } MakeOrbitConstants(g, currentOrbit, false, "CurrentOrbit"); drawPatchedConic(g, currentOrbit, 0, 360, orbitColor); drawPeriapse(g, currentOrbit); drawApoapse(g, currentOrbit); drawAscDescNodes(g, currentOrbit); drawCurrentPosition(g, currentOrbit); if (burnNodes != null) { int s = 0; for (int i = 0; i < burnNodes.Count; i++) { Node burnNode = burnNodes[i]; drawBurnPoint(g, burnNode); if (!double.IsNaN(burnNode.Orbit.TimeToSOIChange)) { double SOIUT = burnNode.Orbit.TimeToSOIChange + UT; double TAatSOI = burnNode.Orbit.TrueAnomalyAtUT(SOIUT); double burnTA = burnNode.Orbit.TrueAnomalyAtUT(burnNode.UT); // Swap thetaStart and thetaEnd is orbit is retrograde if (burnNode.Orbit.Inclination > Helper.deg2rad(90) && burnNode.Orbit.Inclination <= Helper.deg2rad(275)) { double tmp = burnTA; burnTA = TAatSOI; TAatSOI = tmp; } MakeOrbitConstants(g, burnNode.Orbit, false, "Node " + i.ToString()); drawPatchedConic(g, burnNode.Orbit, Helper.rad2deg(burnTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[i + s % 3]); Orbit SOIorbit = burnNode.Orbit.NextOrbit; while (SOIorbit != null) { s++; double entryTA = SOIorbit.TrueAnomalyAtUT(SOIUT); SOIUT = SOIorbit.TimeToSOIChange + UT; if (!double.IsNaN(SOIUT)) { TAatSOI = SOIorbit.TrueAnomalyAtUT(SOIUT); } else { TAatSOI = Helper.deg2rad(360); entryTA = 0; } // Swap thetaStart and thetaEnd is orbit is retrograde if (SOIorbit.Inclination > Helper.deg2rad(90) && SOIorbit.Inclination <= Helper.deg2rad(275)) { double tmp = entryTA; entryTA = TAatSOI; TAatSOI = tmp; } satX = 0; satY = 0; if (SOIorbit.Body.Name != body.Name && SOIorbit.Body.Name != "Sun") { // ORBIT AROUND ANTOHER BODY double CloseTime = SOIorbit.TimeToPeriapsis + burnNode.Orbit.TimeToSOIChange + UT; MakeOrbitConstants(g, SOIorbit.Body.Orbit, false, "SOI Orbit Blob"); drawBlob(g, SOIorbit.Body.Orbit, CloseTime); // This need to be done with satX/Y at 0, becouse it is relative to main body satX = SOIorbit.Body.Orbit.PositionAt(UT, bodyNonRotFrame).Item1 *scaler; satY = SOIorbit.Body.Orbit.PositionAt(UT, bodyNonRotFrame).Item3 *scaler; MakeOrbitConstants(g, SOIorbit, false, -1, "SOI Orbit local", true); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, SOIorbit); // Main body relative orbit satX = SOIorbit.Body.Orbit.PositionAt(CloseTime, bodyNonRotFrame).Item1 *scaler; satY = SOIorbit.Body.Orbit.PositionAt(CloseTime, bodyNonRotFrame).Item3 *scaler; relPeriapse = -1; MakeOrbitConstants(g, SOIorbit, true, CloseTime, "SOI Orbit Relative", true); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3], true); drawPeriapse(g, relPeriapseX, relPeriapseY); } else { MakeOrbitConstants(g, SOIorbit, false, "SOI Orbit " + s.ToString()); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, SOIorbit); } if (SOIorbit.Eccentricity < 1 && double.IsNaN(SOIorbit.TimeToSOIChange)) { drawApoapse(g, SOIorbit); drawAscDescNodes(g, SOIorbit); } SOIorbit = SOIorbit.NextOrbit; } } else { satX = 0; satY = 0; MakeOrbitConstants(g, burnNode.Orbit, false, "Burn Orbit"); drawPatchedConic(g, burnNode.Orbit, 0, 360, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, burnNode.Orbit); drawApoapse(g, burnNode.Orbit); drawAscDescNodes(g, burnNode.Orbit); } } } } }
private void updateOrbit(int c, Orbit orbit, double met, string title) { int b = (c * 20) + 10; if (title != "") { screenLabels[b + 0].Text = title; } else { screenLabels[b + 0].Text = "───────────────────────────────────"; } if (met != 0) { screenLabels[b + 2].Text = " MET: " + Helper.prtlen(Helper.timeString(met), 12, Helper.Align.RIGHT); } else { screenLabels[b + 2].Text = ""; } if (orbit != null) { screenLabels[b + 4].Text = " BODY: " + Helper.prtlen(orbit.Body.Name.ToUpper(), 12, Helper.Align.RIGHT); screenLabels[b + 6].Text = " APOAPSIS: " + Helper.prtlen(Math.Round(orbit.ApoapsisAltitude).ToString(), 12, Helper.Align.RIGHT); screenLabels[b + 7].Text = " PERIAPSIS: " + Helper.prtlen(Math.Round(orbit.PeriapsisAltitude).ToString(), 12, Helper.Align.RIGHT); if (double.IsInfinity(orbit.Period)) { screenLabels[b + 9].Text = " PERIOD: ESCAPE"; } else { screenLabels[b + 9].Text = " PERIOD: " + Helper.prtlen(Helper.timeString(orbit.Period, 2), 12, Helper.Align.RIGHT); } screenLabels[b + 11].Text = " ECCENTRICITY: " + Helper.prtlen(Helper.toFixed(orbit.Eccentricity, 5), 12, Helper.Align.RIGHT); screenLabels[b + 12].Text = " INCLINATION: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(orbit.Inclination), 3), 12, Helper.Align.RIGHT); screenLabels[b + 13].Text = " LONG OF ASC NODE: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(orbit.LongitudeOfAscendingNode), 3), 12, Helper.Align.RIGHT); screenLabels[b + 14].Text = " ARG OF PERIAPSIS: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(orbit.ArgumentOfPeriapsis), 2), 12, Helper.Align.RIGHT); } else { for (int i = 4; i < 15; i++) { screenLabels[b + i].Text = ""; } } }
public void updateChartData(object sender, EventArgs e) { if (connected && krpc.CurrentGameScene == KRPC.Client.Services.KRPC.GameScene.Flight && graphStreams != null) { double altitude = graphStreams.GetData(DataType.flight_meanAltitude); double apoapsis = graphStreams.GetData(DataType.orbit_apoapsisAltitude); double periapsis = graphStreams.GetData(DataType.orbit_periapsisAltitude); double speed = graphStreams.GetData(DataType.orbit_speed); double MET = graphStreams.GetData(DataType.vessel_MET); double elevation = graphStreams.GetData(DataType.flight_elevation); float gee = graphStreams.GetData(DataType.flight_gForce); float dynPress = graphStreams.GetData(DataType.flight_dynamicPressure); float roll = graphStreams.GetData(DataType.flight_inertial_roll); float pitch = graphStreams.GetData(DataType.flight_inertial_pitch); Tuple <double, double, double> prograde = graphStreams.GetData(DataType.flight_prograde); float aoa = graphStreams.GetData(DataType.flight_angleOfAttack); float yaw = graphStreams.GetData(DataType.flight_inertial_yaw); double tapo = graphStreams.GetData(DataType.orbit_timeToApoapsis); double lat = graphStreams.GetData(DataType.flight_map_latitude); double lon = graphStreams.GetData(DataType.flight_map_longitude); // Limit taop to 120 minutes if (tapo > 120 * 60) { tapo = 120 * 60; } // Calculate Range double RANGE = 0; if (originLat != null) { float R = graphStreams.GetData(DataType.body_radius); // body radius in metres double lat1 = (double)originLat; double lon1 = originLon; double rad1 = Helper.deg2rad(lat); double rad2 = Helper.deg2rad(lat1); double deltaRad = Helper.deg2rad((lat1 - lat)); double deltaLambda = Helper.deg2rad((lon1 - lon)); double a = Math.Sin(deltaRad / 2) * Math.Sin(deltaRad / 2) + Math.Cos(rad1) * Math.Cos(rad2) * Math.Sin(deltaLambda / 2) * Math.Sin(deltaLambda / 2); double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); RANGE = R * c; } addValueToChart(chartData["lat"], MET, lat, 10000); addValueToChart(chartData["lon"], MET, lon, 10000); // HDOT if (prevAlt.Key != 0) { double HDOT = (double)((altitude - prevAlt.Value) / (MET - prevAlt.Key)); addValueToChart(chartData["hdot"], MET, HDOT, 3000); addValueToChart(chartData["hhdot"], HDOT, altitude, 3000); } prevAlt = new KeyValuePair <double, double?>(MET, altitude); // FLIGHT PATH ANGLE // Flight path angle is the angle between the velocity vector (prograde), and the local horizon. // Surface direction unit length double surf = Math.Sqrt(Math.Pow(prograde.Item2, 2) + Math.Pow(prograde.Item3, 2)); // Flight path angle double fpa; if (surf < 0.00001) { fpa = 90; } else { fpa = Helper.rad2deg(Math.Atan(prograde.Item1 / surf)); } addValueToChart(chartData["FlightangleVelocity"], speed, fpa, 3000); addValueToChart(chartData["geeVel"], speed, gee, 3000); addValueToChart(chartData["altitudeTime"], MET, altitude); addValueToChart(chartData["apoapsisTime"], MET, apoapsis); addValueToChart(chartData["periapsisTime"], (int)MET, periapsis); addValueToChart(chartData["geeTime"], (int)MET, gee); addValueToChart(chartData["terrainTime"], (int)MET, elevation); addValueToChart(chartData["dynPresTime"], (int)MET, dynPress); addValueToChart(chartData["rollTime"], (int)MET, roll); addValueToChart(chartData["pitchTime"], (int)MET, pitch); addValueToChart(chartData["yawTime"], (int)MET, yaw); addValueToChart(chartData["altitudeSpeed"], (int)speed, altitude, 3000); addValueToChart(chartData["timeToApoSpeed"], (int)speed, tapo, 3000); addValueToChart(chartData["altitudeRange"], (int)RANGE, altitude, 3000); } }
public override void updateLocalElements(object sender, EventArgs e) { // Always update Local Time screenLabels[1].Text = " LT: " + Helper.timeString(DateTime.Now.TimeOfDay.TotalSeconds); if (form.form.connected && form.form.krpc.CurrentGameScene == GameScene.Flight) { period = screenStreams.GetData(DataType.orbit_period); apopapsis = screenStreams.GetData(DataType.orbit_apoapsis); periapsis = screenStreams.GetData(DataType.orbit_periapsis); sMa = screenStreams.GetData(DataType.orbit_semiMajorAxis); sma = screenStreams.GetData(DataType.orbit_semiMinorAxis); argOP = screenStreams.GetData(DataType.orbit_argumentOfPeriapsis); lOAN = screenStreams.GetData(DataType.orbit_longitudeOfAscendingNode); eccentricity = screenStreams.GetData(DataType.orbit_eccentricity); inclination = screenStreams.GetData(DataType.orbit_inclination); radius = screenStreams.GetData(DataType.orbit_radius); trueAnomaly = screenStreams.GetData(DataType.orbit_trueAnomaly); timeToPe = screenStreams.GetData(DataType.orbit_timeToPeriapsis); timeToAp = screenStreams.GetData(DataType.orbit_timeToApoapsis); MET = screenStreams.GetData(DataType.vessel_MET); UT = screenStreams.GetData(DataType.spacecenter_universial_time); screenLabels[2].Text = "MET: " + Helper.timeString(MET, 3); screenLabels[3].Text = "UT: " + Helper.timeString(UT, 5); // ORBIT DATA DATA AND LABELS double nextAp = MET + timeToAp; double nextPe = MET + timeToPe; screenLabels[30].Text = "NEXT PER: " + Helper.timeString(nextPe, 4); screenLabels[31].Text = "NEXT APO: " + Helper.timeString(nextAp, 4); // BURN-RESULTANT ORBIT double TIG = -1; try { if (screenInputs[0].Text != "") { TIG += int.Parse(screenInputs[0].Text) * 3600; } if (screenInputs[1].Text != "") { TIG += int.Parse(screenInputs[1].Text) * 60; } if (screenInputs[2].Text != "") { TIG += double.Parse(screenInputs[2].Text, format); } TIG += (UT - MET); } catch (Exception) { //MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } double TAAUT = form.connection.SpaceCenter().ActiveVessel.Orbit.TrueAnomalyAtUT(TIG); my = form.connection.SpaceCenter().ActiveVessel.Orbit.Body.GravitationalParameter; // Make orbital plane vectors Tuple <double, double, double> velocityVectorInPlane = getVelocityVector(sMa, TAAUT, eccentricity, my); Tuple <double, double, double> positionVectorInPlane = getPositionVector(sMa, TAAUT, eccentricity); referencePlane = getGeocentricReferenceFrame(lOAN, inclination, argOP); double alpha = Math.Acos(velocityVectorInPlane.Item1 / Math.Sqrt(Math.Pow(velocityVectorInPlane.Item1, 2) + Math.Pow(velocityVectorInPlane.Item2, 2))); if (velocityVectorInPlane.Item1 > 0) { if (velocityVectorInPlane.Item2 > 0) { // Leave alpha as is } else { alpha = -alpha; } } else { if (velocityVectorInPlane.Item2 > 0) { alpha = Math.PI - alpha; } else { alpha = -(Math.PI - alpha); } } String totalV = "N.A."; Tuple <double, double, double> burnVector = new Tuple <double, double, double>(0, 0, 0); try { double bX = 0; double bY = 0; double bZ = 0; if (screenInputs[3].Text != "") { bX = double.Parse(screenInputs[3].Text, format); } // Pro/retro if (screenInputs[4].Text != "") { bY = double.Parse(screenInputs[4].Text, format); } // Radial in/out if (screenInputs[5].Text != "") { bZ = double.Parse(screenInputs[5].Text, format); } // Normal / AntiNormal totalV = Helper.toFixed(Math.Sqrt((bX * bX) + (bY * bY) + (bZ * bZ)), 3); burnVector = new Tuple <double, double, double>(bX, bY, bZ); velocityVectorInPlane = vectorChangeMagnitude(velocityVectorInPlane, bX); velocityVectorInPlane = vectorAddLeftMagnitude(velocityVectorInPlane, bY); velocityVectorInPlane = vectorAddUpMagnitude(velocityVectorInPlane, bZ); } catch (Exception) { //MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } // Tranform vectors Tuple <double, double, double> burnVectorInPlane = rotateVectorAroundZ(burnVector, alpha); velocityVector = transform(velocityVectorInPlane, referencePlane); positionVector = transform(positionVectorInPlane, referencePlane); Tuple <double, double, double> inertialBurnVector = transform(burnVectorInPlane, referencePlane); screenLabels[20].Text = "│ Total ΔV: " + totalV; // BURN ANGLES //Console.WriteLine(inertialBurnVector); double yaw = Helper.rad2deg(Math.Atan(inertialBurnVector.Item2 / inertialBurnVector.Item1)); if (inertialBurnVector.Item1 > 0) { if (inertialBurnVector.Item2 > 0) { // Kepp yaw as is } else { yaw = 360 + yaw; } } else { yaw = 180 + yaw; } double pitch = Helper.rad2deg(Math.Asin(inertialBurnVector.Item3 / vectorMagnitude(inertialBurnVector))); screenLabels[21].Text = "│ BURN ANGLES: " + Helper.prtlen(Helper.toFixed(0, 2), 6) + " " + Helper.prtlen(Helper.toFixed(pitch, 2), 6) + " " + Helper.prtlen(Helper.toFixed(yaw, 2), 6); double yawOffset = 0; if (yaw >= 180) { yawOffset = 360 - yaw; } else { yawOffset = -yaw; } screenLabels[22].Text = "│ FDAI OFFSET: " + Helper.prtlen(Helper.toFixed(0, 2), 6) + " " + Helper.prtlen(Helper.toFixed(-pitch, 2), 6) + " " + Helper.prtlen(Helper.toFixed(yawOffset, 2), 6); //screenOrbit.setBurnData(TAAUT, velocityVector,positionVector,my); //screenOrbit.setOrbit(apopapsis, periapsis, sMa, sma, argOP, lOAN, radius, trueAnomaly, inclination); // Make positionalBurnData List <Tuple <List <Tuple <double?, double?> >, Color> > burnPos = new List <Tuple <List <Tuple <double?, double?> >, Color> >(); burnPos.Add(new Tuple <List <Tuple <double?, double?> >, Color>(posB, Color.FromArgb(255, 0, 0, 255))); burnPos.Add(new Tuple <List <Tuple <double?, double?> >, Color>(posC, Color.FromArgb(255, 0, 255, 0))); screenOrbit.positionalData = burnPos; screenOrbit.Invalidate(); // ZOOM screenLabels[23].Text = "ZOOM: " + Helper.toFixed(screenOrbit.getZoom(), 1); // ITERATE THROUGH ORBITS AND PATCHES String orbitsData = ""; Orbit orbit = form.connection.SpaceCenter().ActiveVessel.Orbit; for (int i = 0; i < 4; i++) { orbitsData += getOrbitsData(orbit) + "\n\n"; if (orbit.NextOrbit == null) { break; } else { orbit = orbit.NextOrbit; } } screenLabels[32].Text = orbitsData; // TARGET DATA double vesselX = positionVector.Item1; double vesselY = positionVector.Item2; double vesselZ = positionVector.Item3; double satX = 0; // = satPositionVector.Item1; double satY = 0; double satZ = 0; CelestialBody sat; Orbit satOrbit; if (screenDropdowns[0].SelectedItem != null) { sat = (CelestialBody)screenDropdowns[0].SelectedItem; satOrbit = sat.Orbit; double satSMA = satOrbit.SemiMajorAxis; double satTA = satOrbit.TrueAnomaly; double satEcc = satOrbit.Eccentricity; Tuple <double, double, double> satPositionVectorInPlane = getPositionVector(satSMA, satTA, satEcc); Tuple <double, double, double> satPositionVector = transform(satPositionVectorInPlane, referencePlane); satX = satPositionVector.Item1; satY = satPositionVector.Item2; satZ = satPositionVector.Item3; } double deltaX = vesselX - satX; double deltaY = vesselY - satY; double deltaZ = vesselZ - satZ; double total = Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ)); screenLabels[45].Text = "│ X: " + Helper.prtlen(Math.Round(vesselX).ToString(), 8) + " " + Helper.prtlen(Math.Round(satX).ToString(), 8) + " " + Helper.prtlen(Math.Round(deltaX).ToString(), 8) + " │"; screenLabels[46].Text = "│ Y: " + Helper.prtlen(Math.Round(vesselY).ToString(), 8) + " " + Helper.prtlen(Math.Round(satY).ToString(), 8) + " " + Helper.prtlen(Math.Round(deltaY).ToString(), 8) + " │"; screenLabels[47].Text = "│ Z: " + Helper.prtlen(Math.Round(vesselZ).ToString(), 8) + " " + Helper.prtlen(Math.Round(satZ).ToString(), 8) + " " + Helper.prtlen(Math.Round(deltaZ).ToString(), 8) + " │"; screenLabels[49].Text = "│CURRENT TOTAL DISTANCE: " + Helper.prtlen(Math.Round(total).ToString(), 8) + " │"; screenLabels[52].Text = "┘ MET: " + Helper.timeString(minDistMETB, 3) + " DIST: " + Helper.prtlen(Math.Round(minDistB).ToString(), 8) + " │"; // GRAPH IT List <Dictionary <double, double?> > data = new List <Dictionary <double, double?> >(); List <Plot.Type> types = new List <Plot.Type>(); data = new List <Dictionary <double, double?> >(); types = new List <Plot.Type>(); data.Add(distancesB); types.Add(Plot.Type.LINE); data.Add(distancesC); types.Add(Plot.Type.LINE); screenCharts[0].setData(data, types, false); data = new List <Dictionary <double, double?> >(); types = new List <Plot.Type>(); data.Add(zedB); types.Add(Plot.Type.LINE); data.Add(zedC); types.Add(Plot.Type.LINE); screenCharts[1].setData(data, types, false); } }
public static Tuple <double, double, double> RPYFromQuaternion(Tuple <double, double, double, double> q, string mode) { double x, y, z, w; // 1:X, 2:Y, 3:Z, 4:W if (mode == "INER") // Body Non-Rotating Reference Frame { /* Inertial reference frame is different from the surface one. * * Euler kRPC * X Z (90° CCW from X) * Y X (arbitrary point out the equator) * Z Y (Up, or through the North Pole) */ x = q.Item3; y = q.Item1; z = q.Item2; w = q.Item4; } else // Vessel Surface Reference Frame { /* kRPC-angles are XYZW, but reference frame is different. * * Euler kRPC * X Y (North) * Y Z (East) * Z X (Up) */ x = q.Item2; y = q.Item3; z = q.Item1; w = q.Item4; } double roll, pitch, yaw; double a = 0; double b = 0; double c = 0; double d = 0; double e = 0; a = 2 * ((w * x) + (y * z)); b = 1 - (2 * ((x * x) + (y * y))); c = 2 * ((w * y) - (z * x)); d = 2 * ((w * z) + (x * y)); e = 1 - (2 * ((y * y) + (z * z))); roll = Helper.rad2deg(Math.Atan2(a, b)); // X pitch = Helper.rad2deg(Math.Asin(c)); // Y yaw = Helper.rad2deg(Math.Atan2(d, e)); // Z /**/ // CHECK FOR OUT OF BOUNDS PITCH if (Double.IsNaN(pitch)) { if (c < -1) { pitch = -90f; } else { pitch = 90f; } } return(new Tuple <double, double, double>(roll, pitch, yaw)); }
public override void updateLocalElements(object sender, EventArgs e) { screenLabels[2].Text = "LT: " + Helper.timeString(DateTime.Now.TimeOfDay.TotalSeconds, 2); if (form.form.connected && form.form.krpc.CurrentGameScene == GameScene.Flight) { // GET DATA screenLabels[3].Text = "MET: " + Helper.timeString(screenStreams.GetData(DataType.vessel_MET), 3); //surfaceRefsmmat = form.connection.SpaceCenter().ActiveVessel.SurfaceReferenceFrame; //inertialRefsmmat = form.connection.SpaceCenter().ActiveVessel.Orbit.Body.NonRotatingReferenceFrame; positionVector = screenStreams.GetData(DataType.vessel_position); velocityVector = screenStreams.GetData(DataType.vessel_velocity); vesselSurfDirection = screenStreams.GetData(DataType.flight_direction); vesselInerDirection = screenStreams.GetData(DataType.flight_inertial_direction); vesselInerRotation = screenStreams.GetData(DataType.flight_inertial_rotation); surfaceRefsmmat = screenStreams.GetData(DataType.vessel_surfaceReferenceFrame); vesselRefsmmat = screenStreams.GetData(DataType.vessel_referenceFrame); inertialRefsmmat = screenStreams.GetData(DataType.body_nonRotatingReferenceFrame); // ROTATION // Ref (AGC NOUN 20) double ds; if (double.TryParse(dataStorage.getData("AGC_N20R1"), out ds)) { rR = ds / 100d; } else { rR = 0; } if (double.TryParse(dataStorage.getData("AGC_N20R2"), out ds)) { rP = ds / 100d; } else { rP = 0; } if (double.TryParse(dataStorage.getData("AGC_N20R3"), out ds)) { rY = ds / 100d; } else { rY = 0; } Tuple <double, double, double> iRPY = Helper.RPYFromQuaternion(vesselInerRotation, "INER"); iR = iRPY.Item1; iP = iRPY.Item2; iY = iRPY.Item3; bR = 0; bP = 0; bY = 0; sR = screenStreams.GetData(DataType.flight_roll); sP = screenStreams.GetData(DataType.flight_pitch); sY = screenStreams.GetData(DataType.flight_heading); // DIRECTION VECTORS inerPrograde = screenStreams.GetData(DataType.flight_inertial_prograde); inerRetrograde = screenStreams.GetData(DataType.flight_inertial_retrograde); inerNormal = screenStreams.GetData(DataType.flight_inertial_normal); inerAntiNormal = screenStreams.GetData(DataType.flight_inertial_antiNormal); inerRadial = screenStreams.GetData(DataType.flight_inertial_radial); inerAntiRadial = screenStreams.GetData(DataType.flight_inertial_antiRadial); surfPrograde = screenStreams.GetData(DataType.flight_prograde); surfRetrograde = screenStreams.GetData(DataType.flight_retrograde); surfNormal = screenStreams.GetData(DataType.flight_normal); surfAntiNormal = screenStreams.GetData(DataType.flight_antiNormal); surfRadial = screenStreams.GetData(DataType.flight_radial); surfAntiRadial = screenStreams.GetData(DataType.flight_antiRadial); // ORBIT ELEMENTS eccentricity = screenStreams.GetData(DataType.orbit_eccentricity); semiMajorAxis = screenStreams.GetData(DataType.orbit_semiMajorAxis); Inclination = screenStreams.GetData(DataType.orbit_inclination); LongitudeOfNode = screenStreams.GetData(DataType.orbit_longitudeOfAscendingNode); ArgumentOfPeriapsis = screenStreams.GetData(DataType.orbit_argumentOfPeriapsis); TrueAnomaly = screenStreams.GetData(DataType.orbit_trueAnomaly); OrbitPeriod = screenStreams.GetData(DataType.orbit_period); SOIChange = screenStreams.GetData(DataType.orbit_timeToSOIChange); OrbitalSpeed = screenStreams.GetData(DataType.orbit_speed); // FLIGHT ELEMENTS altitude = screenStreams.GetData(DataType.flight_meanAltitude); apoapsis = screenStreams.GetData(DataType.orbit_apoapsisAltitude); periapsis = screenStreams.GetData(DataType.orbit_periapsisAltitude); timeToPeriapsis = screenStreams.GetData(DataType.orbit_timeToPeriapsis); timeToApoapsis = screenStreams.GetData(DataType.orbit_timeToApoapsis); // STATE VECTORS screenLabels[32].Text = "Px: " + Helper.prtlen(Helper.toFixed(positionVector.Item1 / 1000d, 3, true), 9, Helper.Align.RIGHT); screenLabels[33].Text = "Py: " + Helper.prtlen(Helper.toFixed(positionVector.Item2 / 1000d, 3, true), 9, Helper.Align.RIGHT); screenLabels[34].Text = "Pz: " + Helper.prtlen(Helper.toFixed(positionVector.Item3 / 1000d, 3, true), 9, Helper.Align.RIGHT); // SPEED VECTORS screenLabels[41].Text = "Vx: " + Helper.prtlen(Helper.toFixed(velocityVector.Item1, 3, true), 9, Helper.Align.RIGHT); screenLabels[42].Text = "Vy: " + Helper.prtlen(Helper.toFixed(velocityVector.Item2, 3, true), 9, Helper.Align.RIGHT); screenLabels[43].Text = "Vz: " + Helper.prtlen(Helper.toFixed(velocityVector.Item3, 3, true), 9, Helper.Align.RIGHT); // ROTATION string iRs = Helper.prtlen(Helper.toFixed(iR, 2), 7, Helper.Align.RIGHT); string iPs = Helper.prtlen(Helper.toFixed(iP, 2), 7, Helper.Align.RIGHT); string iYs = Helper.prtlen(Helper.toFixed(iY, 2), 7, Helper.Align.RIGHT); string bRs = Helper.prtlen(Helper.toFixed(bR, 2), 7, Helper.Align.RIGHT); string bPs = Helper.prtlen(Helper.toFixed(bP, 2), 7, Helper.Align.RIGHT); string bYs = Helper.prtlen(Helper.toFixed(bY, 2), 7, Helper.Align.RIGHT); string sRs = Helper.prtlen(Helper.toFixed(sR, 2), 7, Helper.Align.RIGHT); string sPs = Helper.prtlen(Helper.toFixed(sP, 2), 7, Helper.Align.RIGHT); string sYs = Helper.prtlen(Helper.toFixed(sY, 2), 7, Helper.Align.RIGHT); string rRs = Helper.prtlen(Helper.toFixed(rR, 2), 7, Helper.Align.RIGHT); string rPs = Helper.prtlen(Helper.toFixed(rP, 2), 7, Helper.Align.RIGHT); string rYs = Helper.prtlen(Helper.toFixed(rY, 2), 7, Helper.Align.RIGHT); ifR = normalize(iR + rR, -180, 180); ifP = normalize(iP + rP, -90, 90); ifY = normalize(iY + rY, 0, 360); sfR = normalize(sR + rR, -180, 180); sfP = normalize(sP + rP, -90, 90); sfY = normalize(sY + rY, 0, 360); string ifRs = Helper.prtlen(Helper.toFixed(ifR, 2), 7, Helper.Align.RIGHT); string ifPs = Helper.prtlen(Helper.toFixed(ifP, 2), 7, Helper.Align.RIGHT); string ifYs = Helper.prtlen(Helper.toFixed(ifY, 2), 7, Helper.Align.RIGHT); string sfRs = Helper.prtlen(Helper.toFixed(sfR, 2), 7, Helper.Align.RIGHT); string sfPs = Helper.prtlen(Helper.toFixed(sfP, 2), 7, Helper.Align.RIGHT); string sfYs = Helper.prtlen(Helper.toFixed(sfY, 2), 7, Helper.Align.RIGHT); screenLabels[52].Text = "│ INER ATT:" + iRs + " " + iPs + " " + iYs + " │"; screenLabels[53].Text = "│ BURN :" + bRs + " " + bPs + " " + bYs + " │"; screenLabels[54].Text = "│ REF :" + rRs + " " + rPs + " " + rYs + " │"; screenLabels[55].Text = "│ FDAI :" + ifRs + " " + ifPs + " " + ifYs + " │"; screenLabels[57].Text = "│ SURF ATT:" + sRs + " " + sPs + " " + sYs + " │"; screenLabels[58].Text = "│ REF :" + rRs + " " + rPs + " " + rYs + " │"; screenLabels[59].Text = "│ FDAI :" + sfRs + " " + sfPs + " " + sfYs + " │"; // ORBITAL ELEMENTS screenLabels[10].Text = " ECCENTRICITY: " + Helper.prtlen(Helper.toFixed(eccentricity, 5), 11, Helper.Align.RIGHT); screenLabels[11].Text = " SEMIMAJOR AXIS: " + Helper.prtlen(Helper.toFixed(semiMajorAxis, 3), 11, Helper.Align.RIGHT); screenLabels[12].Text = " INCLINATION: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(Inclination), 3), 11, Helper.Align.RIGHT); screenLabels[13].Text = "LONGITUDE OF NODE: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(LongitudeOfNode), 3), 11, Helper.Align.RIGHT); screenLabels[14].Text = "ARG. OF PERIAPSIS: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(ArgumentOfPeriapsis), 3), 11, Helper.Align.RIGHT); screenLabels[15].Text = " TRUE ANOMALY: " + Helper.prtlen(Helper.toFixed(Helper.rad2deg(TrueAnomaly), 3), 11, Helper.Align.RIGHT); screenLabels[16].Text = " ORB PERIOD: " + Helper.prtlen(Helper.timeString(OrbitPeriod, true, 2), 11, Helper.Align.RIGHT); screenLabels[17].Text = " SOI CHANGE: " + Helper.prtlen(Helper.timeString(SOIChange, true, 2), 11, Helper.Align.RIGHT); screenLabels[18].Text = " ORB SPEED: " + Helper.prtlen(Helper.toFixed(OrbitalSpeed, 3), 11, Helper.Align.RIGHT); // FLIGHT ELEMENTS screenLabels[21].Text = " ALTITUDE: " + Helper.prtlen(Helper.toFixed(altitude, 3), 11, Helper.Align.RIGHT); screenLabels[22].Text = " APOAPSIS: " + Helper.prtlen(Helper.toFixed(apoapsis, 3), 11, Helper.Align.RIGHT); screenLabels[23].Text = " PERIAPSIS: " + Helper.prtlen(Helper.toFixed(periapsis, 3), 11, Helper.Align.RIGHT); screenLabels[24].Text = " TIME TO APOAPSIS: " + Helper.prtlen(Helper.timeString(timeToApoapsis, true, 2), 11, Helper.Align.RIGHT); screenLabels[25].Text = "TIME TO PERIAPSIS: " + Helper.prtlen(Helper.timeString(timeToPeriapsis, true, 2), 11, Helper.Align.RIGHT); // DIRECTION VECTORS Tuple <double, double, double> inerProgradeRPY = inerVectorToRPY(inerPrograde); Tuple <double, double, double> inerRetrogradeRPY = inerVectorToRPY(inerRetrograde); Tuple <double, double, double> inerNormalRPY = inerVectorToRPY(inerNormal); Tuple <double, double, double> inerAntiNormalRPY = inerVectorToRPY(inerAntiNormal); Tuple <double, double, double> inerRadialRPY = inerVectorToRPY(inerRadial); Tuple <double, double, double> inerAntiRadialRPY = inerVectorToRPY(inerAntiRadial); Tuple <double, double, double> surfProgradeRPY = surfVectorToRPY(surfPrograde); Tuple <double, double, double> surfRetrogradeRPY = surfVectorToRPY(surfRetrograde); Tuple <double, double, double> surfNormalRPY = surfVectorToRPY(surfNormal); Tuple <double, double, double> surfAntiNormalRPY = surfVectorToRPY(surfAntiNormal); Tuple <double, double, double> surfRadialRPY = surfVectorToRPY(surfRadial); Tuple <double, double, double> surfAntiRadialRPY = surfVectorToRPY(surfAntiRadial); // INERTIAL REFERENCE DIRECTIONS string prR = Helper.prtlen(Helper.toFixed(inerProgradeRPY.Item1, 2), 8, Helper.Align.RIGHT); string prP = Helper.prtlen(Helper.toFixed(inerProgradeRPY.Item2, 2), 10, Helper.Align.RIGHT); string prY = Helper.prtlen(Helper.toFixed(inerProgradeRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[82].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(inerRetrogradeRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(inerRetrogradeRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(inerRetrogradeRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[83].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(inerNormalRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(inerNormalRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(inerNormalRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[84].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(inerAntiNormalRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(inerAntiNormalRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(inerAntiNormalRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[85].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(inerRadialRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(inerRadialRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(inerRadialRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[86].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(inerAntiRadialRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(inerAntiRadialRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(inerAntiRadialRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[87].Text = prR + prP + prY; // SURFACE REFERENCE DIRECTIONS prR = Helper.prtlen(Helper.toFixed(surfProgradeRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfProgradeRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfProgradeRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[92].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(surfRetrogradeRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfRetrogradeRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfRetrogradeRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[93].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(surfNormalRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfNormalRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfNormalRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[94].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(surfAntiNormalRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfAntiNormalRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfAntiNormalRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[95].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(surfRadialRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfRadialRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfRadialRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[96].Text = prR + prP + prY; prR = Helper.prtlen(Helper.toFixed(surfAntiRadialRPY.Item1, 2), 8, Helper.Align.RIGHT); prP = Helper.prtlen(Helper.toFixed(surfAntiRadialRPY.Item2, 2), 10, Helper.Align.RIGHT); prY = Helper.prtlen(Helper.toFixed(surfAntiRadialRPY.Item3, 2), 10, Helper.Align.RIGHT); screenLabels[97].Text = prR + prP + prY; } }