private void updateLandingRoll(APIAircraftState state) { if (_pLastState == null) { _pLastState = state; } else if (!state.IsOnGround) { _pLastState = state; _pLastLandingRoll = 0.0; _pLandingLocation = null; _txtLandingRoll.IsVisible = false; _txtLandingRollLabel.IsVisible = false; //btnViewLandingStats.Visibility = Visibility.Hidden; } else if (!_pLastState.IsLanded && state.IsLanded ) //Just transitioned to "landed" state, so start the roll accumulation { _pLandingLocation = state.Location; _pStateJustBeforeTouchdown = _pLastState; _pStateJustAfterTouchdown = state; _pLastState = state; } else if (state.IsLanded && _pLandingLocation != null) //We are in landed state. Calc the roll length. { var currentPosition = state.Location; var R = 3959; // Radius of the earth in miles var dLat = (currentPosition.Latitude - _pLandingLocation.Latitude) * (Math.PI / 180); var dLon = (currentPosition.Longitude - _pLandingLocation.Longitude) * (Math.PI / 180); var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(currentPosition.Latitude * (Math.PI / 180)) * Math.Cos(_pLandingLocation.Latitude * (Math.PI / 180)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2) ; var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); var d = R * c; // Distance in miles d *= 5280; //Distance in ft _txtLandingRoll.Text = string.Format("{0:0.00}", d) + " ft"; _txtLandingRoll.IsVisible = true; _txtLandingRollLabel.IsVisible = true; _pLastState = state; _landingDetails.updateLandingStats(_pLandingLocation, _pAircraftState.Location, _pStateJustBeforeTouchdown, _pStateJustAfterTouchdown, ""); } if (_pLandingLocation != null && state.IsLanded && state.IsOnGround && state.GroundSpeedKts < 10) { _pLandingStatDlg = new LandingStats(); _pLandingStatDlg.updateLandingStats(_pLandingLocation, _pAircraftState.Location, _pStateJustBeforeTouchdown, _pStateJustAfterTouchdown, ""); _landingDetails.updateLandingStats(_pLandingLocation, _pAircraftState.Location, _pStateJustBeforeTouchdown, _pStateJustAfterTouchdown, ""); //btnViewLandingStats.Visibility = Visibility.Visible; } }
public void updateLandingStats(Coordinate touchdownPosition, Coordinate positionAtEndOfRoll, APIAircraftState stateJustBeforeTouchdown, APIAircraftState stateJustAfterTouchdown, string aircraftType) { pTouchdownInfo = new touchdownInfo(); pTouchdownInfo.touchdownGroundSpeed = stateJustBeforeTouchdown.GroundSpeedKts; pTouchdownInfo.touchdownIAS = stateJustBeforeTouchdown.IndicatedAirspeedKts; pTouchdownInfo.touchdownPitch = stateJustBeforeTouchdown.Pitch; pTouchdownInfo.touchdownGforce = stateJustBeforeTouchdown.GForce > stateJustAfterTouchdown.GForce ? stateJustBeforeTouchdown.GForce : stateJustAfterTouchdown.GForce; pTouchdownInfo.touchdownVS = stateJustBeforeTouchdown.VerticalSpeed; pTouchdownInfo.wasStalling = stateJustBeforeTouchdown.Stalling; pTouchdownInfo.wasNearStall = stateJustBeforeTouchdown.StallWarning; pTouchdownInfo.wasOverMLW = stateJustBeforeTouchdown.IsOverLandingWeight; pTouchdownInfo.rollDistance = calcRollDistance(touchdownPosition, positionAtEndOfRoll); _gridLandingStats.DataContext = pTouchdownInfo; }
public void performHold(APIAircraftState acState) { pAircraftState = acState; Double degChg = 0; switch (holdLeg) { case 0: //Get initial fix and heading if (initialHoldStart == null) { initialHoldStart = pAircraftState.Location; } if (initialHdg == -1) { initialHdg = pAircraftState.HeadingMagnetic; } //turn to back-bearing backBearing = initialHdg < 180 ? initialHdg + 180 : initialHdg - 180; if (lblHoldInfo.Content.ToString() != ("Holding: Turn " + Math.Floor(backBearing).ToString())) { lblHoldInfo.Content = ("Holding: Turn " + Math.Floor(backBearing).ToString()); } if (!hdgSetComplete) { hdgSet = initialHdg; } degChg = 0; while (Math.Abs(hdgSet - Math.Floor(backBearing)) > 5) { if (leftTurns) { hdgSet -= 45; } else { hdgSet += 45; } hdgSet %= 360; setAutoPilotParams(-1, Math.Floor(hdgSet), 999999, -1); degChg = 0; // while degChg < requiredchange then wait System.Threading.Thread.Sleep(15000); } setAutoPilotParams(-1, backBearing, 999999, -1); hdgSetComplete = true; if (Math.Abs(Math.Floor(pAircraftState.HeadingMagnetic) - Math.Floor(backBearing)) < 2) { //hit backbearing setAutoPilotParams(-1, backBearing, 999999, -1); leg2start = pAircraftState.Location; holdLeg = 1; } break; case 1: //maintain back-bearing for legLength if (lblHoldInfo.Content.ToString() != ("Holding: Leg 1")) { lblHoldInfo.Content = "Holding: Leg 1"; } double err = acState.CourseTrue - acState.HeadingTrue; setAutoPilotParams(-1, backBearing - err, 999999, -1); hdgSetComplete = false; if (getDistBtwnPoints(leg2start, pAircraftState.Location) > legLength) { holdLeg = 2; } break; case 2: //turn back to initial heading if (lblHoldInfo.Content.ToString() != ("Holding: Turn " + Math.Floor(initialHdg).ToString())) { lblHoldInfo.Content = ("Holding: Turn " + Math.Floor(initialHdg).ToString()); } degChg = 0; while (Math.Abs(hdgSet - Math.Floor(initialHdg)) > 1) { if (leftTurns) { hdgSet -= 90; } else { hdgSet += 90; } hdgSet %= 360; setAutoPilotParams(-1, hdgSet, 999999, -1); degChg = 0; System.Threading.Thread.Sleep(2000); } setAutoPilotParams(-1, initialHdg, 999999, -1); hdgSetComplete = true; if (Math.Abs(Math.Floor(pAircraftState.HeadingMagnetic) - Math.Floor(initialHdg)) < 2) { //hit initial hdg setAutoPilotParams(-1, initialHdg, 999999, -1); //initialHoldStart = pAircraftState.Location; holdLeg = 3; } break; case 3: //Maintain initial heading for legLength back to the hold fix if (lblHoldInfo.Content.ToString() != "Holding: To Fix") { lblHoldInfo.Content = "Holding: To Fix"; } hdgSetComplete = false; //if (getDistBtwnPoints(initialHoldStart, pAircraftState.Location) > legLength) { holdLeg = 1; } //Fly to initial Fix double declination = acState.HeadingTrue - acState.HeadingMagnetic; double hdg = getHeadingToPoint(pAircraftState.Location, initialHoldStart) - declination; err = acState.CourseTrue - acState.HeadingTrue; setAutoPilotParams(-1, hdg - err, 999999, -1); if (getDistBtwnPoints(initialHoldStart, pAircraftState.Location) < 0.25) { holdLeg = 0; } break; default: break; } return; }
public void handleAtcMessage(APIATCMessage AtcMsg, APIAircraftState acState) { logMessage(AtcMsg.Message); //Only act on messages received by us that are directed at us. if (AtcControlledAutopilotEnabled == true && AtcMsg.Received && AtcMsg.Message.Contains(Callsign)) { string msg = AtcMsg.Message.ToLower(); //Just to make things easier //Heading if (msg.Contains("heading")) { Match mtch = Regex.Match(msg, "heading\\W+(?<hdg>\\d+)"); if (mtch.Success) { string sHdg = mtch.Groups["hdg"].Value; double hdg = Convert.ToDouble(sHdg); setHeading(hdg); } } //Altitude if (msg.Contains("descend") || msg.Contains("climb")) { Match mtch = Regex.Match(msg, "maintain\\W+(?<fl>FL)*(?<alt>\\d+,*\\d+)(ft)*"); if (mtch.Success) { double alt = 1000.0; if (mtch.Groups["fl"].Success) //Convert flight level { alt = Convert.ToDouble(mtch.Groups["alt"].Value) * 100; } else //Else it is just in ft, but remove comma { alt = Convert.ToDouble(mtch.Groups["alt"].Value.Replace(",", "")); } if (msg.Contains("descend")) { setAltitude(alt, -1800); } else { setAltitude(alt, 1800); } } } //Speed if (msg.Contains("kts")) { Match mtch = Regex.Match(msg, "\\W+(?<speed>\\d+)kts"); if (mtch.Success) { double speed = Convert.ToDouble(mtch.Groups["speed"].Value); if (msg.Contains("do not exceed")) { speed -= 5; } setSpeed(speed); if (acState.IndicatedAirspeedKts > (speed + 30)) { client.ExecuteCommand("Commands.Spoilers"); } } } //Acknowledge ATC client.ExecuteCommand("Commands.ATCEntry2"); if (msg.Contains("contact") && !msg.Contains("exit runway")) { //contact next freq if handed off (but not if exiting runway to contact gnd) client.ExecuteCommand("Commands.ATCEntry2"); //send & switch on second menu } } }
public void updateAutoNav(APIAircraftState acState) { if (pFplState == null) { client.ExecuteCommand("FlightPlan.GetFlightPlan"); } //Set initial next waypoint as first waypoint if (pFplState.nextWpt == null) { pFplState.legIndex = 0; pFplState.nextWpt = pFplState.fpl.Waypoints[1]; pFplState.dest = pFplState.fpl.Waypoints.Last(); pFplState.nextAltitude = pFplState.fplDetails.waypoints[pFplState.legIndex + 1].Altitude; pFplState.thisSpeed = pFplState.fplDetails.waypoints[pFplState.legIndex].Airspeed; pFplState.nextSpeed = pFplState.fplDetails.waypoints[pFplState.legIndex + 1].Airspeed; } //Get dist to next wpt pFplState.distToNextWpt = getDistToWaypoint(acState.Location, pFplState.nextWpt); //If dist<2nm, go to next wpt if (pFplState.distToNextWpt < 2) { pFplState.legIndex++; //next leg pFplState.prevWpt = pFplState.nextWpt; //current wpt is not prev wpt if (pFplState.legIndex >= pFplState.fpl.Waypoints.Count()) { //We hit the destination! lblNextWpt.Content = "Destination Reached!"; lblDist2Next.Content = ""; lblHdg2Next.Content = ""; autoFplDirectActive = false; return; } pFplState.nextWpt = pFplState.fpl.Waypoints[pFplState.legIndex]; //target next wpt pFplState.nextAltitude = pFplState.fplDetails.waypoints[pFplState.legIndex].Altitude; pFplState.thisSpeed = pFplState.fplDetails.waypoints[pFplState.legIndex - 1].Airspeed; pFplState.nextSpeed = pFplState.fplDetails.waypoints[pFplState.legIndex].Airspeed; //Get dist to new next wpt pFplState.distToNextWpt = getDistToWaypoint(acState.Location, pFplState.nextWpt); } lblNextWpt.Content = pFplState.nextWpt.Name; lblDist2Next.Content = String.Format("{0:0.000}", pFplState.distToNextWpt); lblAirspeedSet.Content = String.Format("{0:0.000}", pFplState.thisSpeed); lblAltitudeSet.Content = pFplState.nextAltitude.ToString(); //Adjust heading for magnetic declination double declination = acState.HeadingTrue - acState.HeadingMagnetic; //Get heading to next pFplState.hdgToNextWpt = getHeadingToWaypoint(acState.Location, pFplState.nextWpt) - declination; lblHdg2Next.Content = String.Format("{0:0.000}", pFplState.hdgToNextWpt); //Calculate VS to hit target altitude if (pFplState.nextAltitude > 0) { //double vs = calcVs(acState.AltitudeMSL, pFplState.nextAltitude, acState.GroundSpeedKts, pFplState.distToNextWpt); double vs = 0; var airspeed = pFplState.thisSpeed; if (airspeed > 0 && airspeed <= 60) { vs = 700; } else if (airspeed > 60 && airspeed <= 160) { vs = 1100; } else if (airspeed > 160 && airspeed <= 225) { vs = 1500; } else if (airspeed > 225 && airspeed <= 285) { vs = 1900; } else if (airspeed > 285 && airspeed <= 320) { vs = 2200; } else { vs = 2300; } lblVsSet.Content = string.Format("{0:0.000}", vs); //Adjust AutoPilot setAutoPilotParams(pFplState.nextAltitude, pFplState.hdgToNextWpt, vs, pFplState.nextSpeed); } else { //Adjust AutoPilot setAutoPilotParams(pFplState.nextAltitude, pFplState.hdgToNextWpt, 999999, pFplState.nextSpeed); } ////Dont think we need this //APIWaypoint closestWpt = pFplState.fpl.Waypoints.First(); //foreach (APIWaypoint wpt in pFplState.fpl.Waypoints) //{ // double distToClosest = getDistToWaypoint(acState.Location, closestWpt); // if (getDistToWaypoint(acState.Location,wpt) < distToClosest) // { // closestWpt = wpt; // } //} }
void client_CommandReceived(object sender, CommandReceivedEventArgs e) { Dispatcher.BeginInvoke((Action)(() => { try { var type = typeof(IFAPIStatus).Assembly.GetType(e.Response.Type); if (type == typeof(APIAircraftState)) { var state = Serializer.DeserializeJson <APIAircraftState>(e.CommandString); Console.WriteLine(state.VerticalSpeed); // convert to fpm state.VerticalSpeed = float.Parse(Convert.ToString(state.VerticalSpeed * 200, CultureInfo.InvariantCulture.NumberFormat), CultureInfo.InvariantCulture.NumberFormat); // multiply by 200, this somehow gets it accurate.. airplaneStateGrid.DataContext = null; airplaneStateGrid.DataContext = state; pAircraftState = state; if (FMSControl.autoFplDirectActive) { FMSControl.updateAutoNav(state); } AircraftStateControl.AircraftState = state; AttitudeIndicator.updateAttitude(state.Pitch, state.Bank); updateLandingRoll(state); } else if (type == typeof(GetValueResponse)) { var state = Serializer.DeserializeJson <GetValueResponse>(e.CommandString); Console.WriteLine("{0} -> {1}", state.Parameters[0].Name, state.Parameters[0].Value); } else if (type == typeof(LiveAirplaneList)) { LiveAirplaneList airplaneList = Serializer.DeserializeJson <LiveAirplaneList>(e.CommandString); //airplaneDataGrid.ItemsSource = airplaneList.Airplanes; } else if (type == typeof(FacilityList)) { var facilityList = Serializer.DeserializeJson <FacilityList>(e.CommandString); //facilitiesDataGrid.ItemsSource = facilityList.Facilities; } else if (type == typeof(IFAPIStatus)) { var status = Serializer.DeserializeJson <IFAPIStatus>(e.CommandString); } else if (type == typeof(APIATCMessage)) { var msg = Serializer.DeserializeJson <APIATCMessage>(e.CommandString); // TODO client.ExecuteCommand("Live.GetCurrentCOMFrequencies"); } else if (type == typeof(APIFrequencyInfoList)) { var msg = Serializer.DeserializeJson <APIFrequencyInfoList>(e.CommandString); } else if (type == typeof(ATCMessageList)) { var msg = Serializer.DeserializeJson <ATCMessageList>(e.CommandString); atcMessagesDataGrid.ItemsSource = msg.ATCMessages; } else if (type == typeof(APIFlightPlan)) { var msg = Serializer.DeserializeJson <APIFlightPlan>(e.CommandString); Console.WriteLine("Flight Plan: {0} items", msg.Waypoints.Length); FMSControl.fplReceived(msg); //Update FMS with FPL from IF. foreach (var item in msg.Waypoints) { Console.WriteLine(" -> {0} {1} - {2}, {3}", item.Name, item.Code, item.Latitude, item.Longitude); } } } catch (System.NullReferenceException) { Console.WriteLine("Disconnected from server!"); //Let the client handle the lost connection. //connectionStatus = false; } })); }
void client_CommandReceived(object sender, CommandReceivedEventArgs e) { Dispatcher.BeginInvoke((Action)(() => { var type = typeof(IFAPIStatus).Assembly.GetType(e.Response.Type); //System.IO.File.AppendAllText("C:\\IfApi\\IfApiCommandResp.txt", e.Response.Type + ": " + e.CommandString + "\n"); //if (pCustomCmdSent) //{ // txtResp.AppendText(e.Response.Type + " " + e.CommandString + "\n\n"); // txtResp.ScrollToEnd(); // pCustomCmdSent = false; //} if (type == typeof(APIAircraftState)) { var state = Serializer.DeserializeJson <APIAircraftState>(e.CommandString); //Console.WriteLine(e.CommandString); //airplaneStateGrid.DataContext = null; //airplaneStateGrid.DataContext = state; pAircraftState = state; if (FMSControl.autoFplDirectActive) { FMSControl.updateAutoNav(state); } AircraftStateControl.AircraftState = state; AttitudeIndicator.updateAttitude(pAircraftState.Pitch, pAircraftState.Bank); } else if (type == typeof(GetValueResponse)) { var state = Serializer.DeserializeJson <GetValueResponse>(e.CommandString); Console.WriteLine("{0} -> {1}", state.Parameters[0].Name, state.Parameters[0].Value); } else if (type == typeof(LiveAirplaneList)) { var airplaneList = Serializer.DeserializeJson <LiveAirplaneList>(e.CommandString); //airplaneDataGrid.ItemsSource = airplaneList.Airplanes; } else if (type == typeof(FacilityList)) { var facilityList = Serializer.DeserializeJson <FacilityList>(e.CommandString); //facilitiesDataGrid.ItemsSource = facilityList.Facilities; } else if (type == typeof(IFAPIStatus)) { var status = Serializer.DeserializeJson <IFAPIStatus>(e.CommandString); updateConnectionStatus(status); //versionTextBlock.Text = status.AppVersion; //userNameTextBlock.Text = status.LoggedInUser; //deviceNameTextBlock.Text = status.DeviceName; //displayResolutionTextBlock.Text = string.Format("{0}x{1}", status.DisplayWidth, status.DisplayHeight); } else if (type == typeof(APIATCMessage)) { var msg = Serializer.DeserializeJson <APIATCMessage>(e.CommandString); //atcMessagesListBox.Items.Add(msg.Message); client.ExecuteCommand("Live.GetCurrentCOMFrequencies"); } else if (type == typeof(APIFrequencyInfoList)) { var msg = Serializer.DeserializeJson <APIFrequencyInfoList>(e.CommandString); //frequenciesDataGrid.ItemsSource = msg.Frequencies; } else if (type == typeof(ATCMessageList)) { var msg = Serializer.DeserializeJson <ATCMessageList>(e.CommandString); //atcMessagesDataGrid.ItemsSource = msg.ATCMessages; } else if (type == typeof(APIFlightPlan)) { var msg = Serializer.DeserializeJson <APIFlightPlan>(e.CommandString); Console.WriteLine("Flight Plan: {0} items", msg.Waypoints.Length); FMSControl.fplReceived(msg); foreach (var item in msg.Waypoints) { Console.WriteLine(" -> {0} {1} - {2}, {3}", item.Name, item.Code, item.Latitude, item.Longitude); } } })); }
private void client_CommandReceived(object sender, IFConnect.CommandReceivedEventArgs e) { Dispatcher.UIThread.InvokeAsync(() => { try { // System.Diagnostics.Debug.WriteLine(e.CommandString); var type = typeof(IFAPIStatus).Assembly.GetType(e.Response.Type); if (type == typeof(APIAircraftState)) { var state = JsonSerializer.Deserialize <APIAircraftState>(e.CommandString); // convert to fpm state.VerticalSpeed = float.Parse( Convert.ToString(state.VerticalSpeed * 200, CultureInfo.InvariantCulture.NumberFormat), CultureInfo.InvariantCulture .NumberFormat); // multiply by 200, this somehow gets it accurate.. _airplaneStateGrid.DataContext = null; _airplaneStateGrid.DataContext = state; _pAircraftState = state; if (_FMSControl.autoFplDirectActive) { _FMSControl.updateAutoNav(state); } if (_FMSControl.HoldingActive) { _FMSControl.performHold(state); } _AircraftStateControl.AircraftState = state; _AttitudeIndicator.updateAttitude(state.Pitch, state.Bank); updateLandingRoll(state); } else if (type == typeof(GetValueResponse)) { var state = JsonSerializer.Deserialize <GetValueResponse>(e.CommandString); Console.WriteLine("{0} -> {1}", state.Parameters[0].Name, state.Parameters[0].Value); } else if (type == typeof(APIATCMessage)) { var msg = JsonSerializer.Deserialize <APIATCMessage>(e.CommandString); //Handle the ATC message to control the autopilot if enabled by checkbox _FMSControl.handleAtcMessage(msg, _pAircraftState); // TODO client.ExecuteCommand("Live.GetCurrentCOMFrequencies"); } else if (type == typeof(ATCMessageList)) { var msg = JsonSerializer.Deserialize <ATCMessageList>(e.CommandString); _atcMessagesDataGrid.Items = msg.ATCMessages; } else if (type == typeof(APIFlightPlan)) { var msg = JsonSerializer.Deserialize <APIFlightPlan>(e.CommandString); Console.WriteLine("Flight Plan: {0} items", msg.Waypoints.Length); _FMSControl.FplReceived(msg); //Update FMS with FPL from IF. foreach (var item in msg.Waypoints) { Console.WriteLine(" -> {0} {1} - {2}, {3}", item.Name, item.Code, item.Latitude, item.Longitude); } } else if (type == typeof(APIAutopilotState)) { _FMSControl.APState = Serializer.DeserializeJson <APIAutopilotState>(e.CommandString); } } catch (NullReferenceException) { Console.WriteLine("Disconnected from server!"); //Let the client handle the lost connection. //connectionStatus = false; } }); }