Skip to content

Commit

Permalink
Update to landing analysis system
Browse files Browse the repository at this point in the history
  • Loading branch information
sushiat committed Dec 12, 2023
1 parent 1f0c945 commit c06853e
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
<Reference Include="Microsoft.Maps.MapControl.WPF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Maps.MapControl.WPF.1.0.0.3\lib\net40-Client\Microsoft.Maps.MapControl.WPF.dll</HintPath>
</Reference>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.7\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.8\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
</Reference>
<Reference Include="ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MSFT.ParallelExtensionsExtras.1.2.0\lib\ParallelExtensionsExtras.dll</HintPath>
Expand Down
2 changes: 1 addition & 1 deletion OpenSky.Agent.SimConnectMSFS/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<package id="Microsoft.CodeAnalysis.NetAnalyzers" version="8.0.0" targetFramework="net48" developmentDependency="true" />
<package id="Microsoft.Maps.MapControl.WPF" version="1.0.0.3" targetFramework="net48" />
<package id="MSFT.ParallelExtensionsExtras" version="1.2.0" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.7" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.8" targetFramework="net48" />
<package id="Serilog" version="3.1.1" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Diagnostics.DiagnosticSource" version="8.0.0" targetFramework="net48" />
Expand Down
4 changes: 2 additions & 2 deletions OpenSky.Agent.Simulator/OpenSky.Agent.Simulator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.7\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.8\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
</Reference>
<Reference Include="ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MSFT.ParallelExtensionsExtras.1.2.0\lib\ParallelExtensionsExtras.dll</HintPath>
Expand Down
98 changes: 90 additions & 8 deletions OpenSky.Agent.Simulator/Simulator.Process.Landing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,33 @@ public partial class Simulator
{
/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the landing reports.
/// (Immutable) The process landing analysis queue (to monitor values like g-force over a period
/// of reports)
/// </summary>
/// -------------------------------------------------------------------------------------------------
public ObservableCollection<TouchDown> LandingReports { get; }
private readonly LandingAnalysis[] plaQueue = new LandingAnalysis[100];

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// The last touchdown even recorded (to group bounces etc., before creating new touchdown event).
/// </summary>
/// -------------------------------------------------------------------------------------------------
private DateTime lastTouchdown = DateTime.MinValue;

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// The pla queue countdown after initial touchdown (to monitor values like g-force for a short
/// period after touchdown)
/// </summary>
/// -------------------------------------------------------------------------------------------------
private int plaQueueCountdown = -1;

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// The current pla queue index.
/// </summary>
/// -------------------------------------------------------------------------------------------------
private int plaQueueIndex;

/// -------------------------------------------------------------------------------------------------
/// <summary>
Expand All @@ -35,6 +58,21 @@ public partial class Simulator
/// -------------------------------------------------------------------------------------------------
public event EventHandler<LandingReportNotification> LandingReported;

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the zero-based index of the final touch down landing report (in case there are multiple
/// like a bounce on takeoff).
/// </summary>
/// -------------------------------------------------------------------------------------------------
public int FinalTouchDownIndex { get; private set; } = -1;

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the landing reports.
/// </summary>
/// -------------------------------------------------------------------------------------------------
public ObservableCollection<TouchDown> LandingReports { get; }

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Check for and analyse landings.
Expand All @@ -50,15 +88,26 @@ private void CheckForAndAnalyseLanding(ProcessLandingAnalysis pla)
{
if (this.TrackingStatus == TrackingStatus.Tracking && !pla.Old.OnGround && pla.New.OnGround)
{
// We have touchdown
// We have a touchdown
Debug.WriteLine("Adding new landing report");

// Check for max g-force before touchdown
var maxGeforce = Math.Max(pla.Old.Gforce, pla.New.Gforce);
for (var i = 0; i < 100; i++)
{
if (this.plaQueue[i] != null)
{
maxGeforce = Math.Max(maxGeforce, this.plaQueue[i].Gforce);
}
}

var landingReport = new TouchDown(
DateTime.UtcNow,
pla.New.Location.Latitude,
pla.New.Location.Longitude,
(int)pla.New.Location.Altitude,
pla.New.LandingRate * -1.0,
Math.Max(pla.Old.Gforce, pla.New.Gforce),
maxGeforce,
pla.New.SpeedLong,
pla.New.SpeedLat,
pla.New.WindLong,
Expand All @@ -68,14 +117,47 @@ private void CheckForAndAnalyseLanding(ProcessLandingAnalysis pla)
pla.New.AirspeedTrue
);

// Add to the list and start the countdown
this.LandingReports.Add(landingReport);

if (this.LandingReports.Count == 1)
if ((DateTime.UtcNow - this.lastTouchdown).TotalSeconds > 30)
{
// First landing for this flight
this.AddTrackingEvent(this.PrimaryTracking, this.SecondaryTracking, FlightTrackingEventType.Touchdown, OpenSkyColors.OpenSkyTeal, "Touchdown");
this.LandingReported?.Invoke(this, LandingReportNotification.AsSoonAsPossible);
this.FinalTouchDownIndex = this.LandingReports.Count - 1;
this.plaQueueCountdown = 100;
}

this.lastTouchdown = DateTime.UtcNow;
}

this.plaQueue[this.plaQueueIndex++] = pla.New;
if (this.plaQueueIndex == 100)
{
this.plaQueueIndex = 0;
}

if (this.plaQueueCountdown > 0)
{
this.plaQueueCountdown--;
}

if (this.plaQueueCountdown == 0 && this.FinalTouchDownIndex >= 0)
{
this.plaQueueCountdown = -1;

// Check for max g-force after touchdown
var maxGeforce = this.LandingReports[this.FinalTouchDownIndex].GForce;
for (var i = 0; i < 100; i++)
{
if (this.plaQueue[i] != null)
{
maxGeforce = Math.Max(maxGeforce, this.plaQueue[i].Gforce);
}
}

this.LandingReports[this.FinalTouchDownIndex].GForce = maxGeforce;

// First landing for this flight
this.LandingReported?.Invoke(this, LandingReportNotification.AsSoonAsPossible);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions OpenSky.Agent.Simulator/Simulator.SaveLoadXML.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ private XElement GenerateSaveFile()

log.PositionReports.AddRange(this.AircraftTrailLocations.Cast<AircraftTrailLocation>().Select(loc => loc.Position));
log.TouchDowns.AddRange(this.LandingReports);
log.FinalTouchDownIndex = this.FinalTouchDownIndex;
log.NavLogWaypoints.AddRange(this.simbriefWaypointMarkers.Select(w => w.WayPoint));

return log.GenerateFlightLog();
Expand Down Expand Up @@ -274,6 +275,8 @@ private void RestoreSaveFile(string saveFile)
this.LandingReports.Add(touchdown);
}

this.FinalTouchDownIndex = log.FinalTouchDownIndex;

// Restore simbrief waypoint markers
UpdateGUIDelegate restoreSimbrief = () =>
{
Expand Down
2 changes: 1 addition & 1 deletion OpenSky.Agent.Simulator/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<package id="Microsoft.Maps.MapControl.WPF" version="1.0.0.3" targetFramework="net48" />
<package id="MSFT.ParallelExtensionsExtras" version="1.2.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.7" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.8" targetFramework="net48" />
<package id="TomsToolbox.Essentials" version="2.10.0" targetFramework="net48" />
<package id="XDMessaging.Lite" version="5.0.6" targetFramework="net48" />
</packages>
4 changes: 2 additions & 2 deletions OpenSky.Agent.UdpXPlane11/OpenSky.Agent.UdpXPlane11.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
<Reference Include="JetBrains.Annotations, Version=4242.42.42.42, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
<HintPath>..\packages\JetBrains.Annotations.2023.3.0\lib\net20\JetBrains.Annotations.dll</HintPath>
</Reference>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.7\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
<Reference Include="OpenSky.FlightLogXML, Version=0.1.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\OpenSky.FlightLogXML.0.1.8\lib\net48\OpenSky.FlightLogXML.dll</HintPath>
</Reference>
<Reference Include="ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MSFT.ParallelExtensionsExtras.1.2.0\lib\ParallelExtensionsExtras.dll</HintPath>
Expand Down
2 changes: 1 addition & 1 deletion OpenSky.Agent.UdpXPlane11/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<packages>
<package id="JetBrains.Annotations" version="2023.3.0" targetFramework="net48" />
<package id="MSFT.ParallelExtensionsExtras" version="1.2.0" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.7" targetFramework="net48" />
<package id="OpenSky.FlightLogXML" version="0.1.8" targetFramework="net48" />
<package id="XPlaneConnector" version="1.3.0" targetFramework="net48" />
<package id="XPlaneConnector.DataRefs" version="11.51.0" targetFramework="net48" />
</packages>
2 changes: 1 addition & 1 deletion OpenSky.Agent/OpenSky.Agent.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="OpenSky.FlightLogXML">
<Version>0.1.7</Version>
<Version>0.1.8</Version>
</PackageReference>
<PackageReference Include="Syncfusion.SfChart.WPF">
<Version>23.2.7</Version>
Expand Down
89 changes: 59 additions & 30 deletions OpenSky.Agent/Views/Models/LandingReportViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ public LandingReportViewModel()
this.FlightNumberHeader = $"Flight #{this.Simulator.Flight?.FullFlightNumber}\r\nLanding Report";

// Fetch the initial already existing landing report(s)
foreach (var item in this.Simulator.LandingReports)
if (this.Simulator.FinalTouchDownIndex > 0)
{
this.landingReports.Add(item);
for (var i = this.Simulator.FinalTouchDownIndex; i < this.Simulator.LandingReports.Count; i++)
{
this.landingReports.Add(this.Simulator.LandingReports[i]);
}
}

// Subscribe to changes
Expand Down Expand Up @@ -144,7 +147,7 @@ private set

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the head wind (only from first touchdown).
/// Gets the head-wind (only from first touchdown).
/// </summary>
/// -------------------------------------------------------------------------------------------------
public string HeadWind => this.landingReports.Count > 0 ? this.landingReports[0].HeadWind.ToString("Tail, 0.00;Head, 0.00;None, 0") : "0";
Expand Down Expand Up @@ -198,79 +201,105 @@ public string LandingGrade
// E Dangerous <-5 or >5

var landingRateAbs = Math.Abs(this.MaxLandingRate);
var grade = "A+";
var desc = "Butter landing";
var geforceAbs = Math.Abs(this.MaxGForce);
var grade = "?";
var desc = "Unknown";

if (landingRateAbs > 1000)
if (landingRateAbs > 1000 || geforceAbs > 3)
{
grade = "F";
desc = "Crash landing";
}

if (grade == "A+" && (this.MaxBankAngle is < -5.0 or > 5.0))
if (grade == "?" && (this.MaxBankAngle is < -5.0 or > 5.0))
{
grade = "E";
desc = "Dangerous bank angle";
}

if (grade == "A+" && (this.MaxSideSlipAngle is < -15.0 or > 15.0))
if (grade == "?" && (this.MaxSideSlipAngle is < -15.0 or > 15.0))
{
grade = "E";
desc = "Dangerous sideslip angle";
}

if (grade == "A+" && landingRateAbs is > 600 and <= 1000)
if (grade == "?" && (landingRateAbs is > 840 and <= 1000 || geforceAbs > 2.86))
{
grade = "E";
desc = "Severe hard landing";
}

if (grade == "A+" && (landingRateAbs is > 600 and <= 840 || geforceAbs is > 2.6 and <= 2.86))
{
grade = "D";
desc = "Rough landing";
desc = "Hard landing";
}

if (grade == "A+" && this.Bounces > 2)
if (grade == "?" && this.Bounces > 2)
{
grade = "D";
desc = "Porpoising landing";
}

if (grade == "A+" && (this.MaxGForce is < -2.1 or > 2.1))
if (grade == "?" && geforceAbs is > 2.1 and <= 2.6)
{
grade = "C";
desc = "Hard landing";
desc = "Rough landing";
}

if (grade == "A+" && landingRateAbs is > 240 and <= 600)
if (grade == "?" && this.Bounces > 1)
{
grade = "C";
desc = "Hard landing";
desc = "Bouncy landing";
}

if (grade == "A+" && this.Bounces > 1)
if (grade == "?" && geforceAbs is > 1.5 and <= 2.1)
{
grade = "C";
desc = "Bouncy landing";
grade = "B-";
desc = "Uncomfortable landing";
}

if (grade == "A+" && landingRateAbs is > 180 and <= 240)

if (grade == "?" && geforceAbs is > 1.25 and <= 1.5)
{
grade = "B";
desc = "OK landing";
desc = "Good landing";
}

if (grade == "A+" && landingRateAbs is > 60 and <= 180)
if (grade == "?" && geforceAbs is >= 0.75 and <= 1.25)
{
grade = "A";
desc = "Good landing";
desc = "Great landing";

if (landingRateAbs <= 130 && this.Simulator.AircraftIdentity.EngineType == EngineType.Jet)
if (this.Simulator.AircraftIdentity.EngineType == EngineType.Jet)
{

if (landingRateAbs is <= 160 and >= 80)
{
grade = "A+";
desc = "Perfect landing";
}

if (landingRateAbs < 50)
{
grade = "A-";
desc = "Lading too soft";
}
}
else
{
grade = "A+";
desc = "Perfect landing";
if (landingRateAbs < 80)
{
grade = "A+";
desc = "Butter landing";
}
}
}

if (grade == "A+" && this.Simulator.AircraftIdentity.EngineType == EngineType.Jet)
if (grade == "?" && geforceAbs < 0.75)
{
grade = "A-";
desc = "Lading too soft";
grade = "B-";
desc = "Negative-G landing";
}

this.LandingGradeDescription = desc;
Expand Down Expand Up @@ -342,7 +371,7 @@ public double MaxBankAngle

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the maximum side slip angle.
/// Gets the maximum side-slip angle.
/// </summary>
/// -------------------------------------------------------------------------------------------------
public double MaxSideSlipAngle
Expand All @@ -362,7 +391,7 @@ public double MaxSideSlipAngle

/// -------------------------------------------------------------------------------------------------
/// <summary>
/// Gets the maximum side slip angle info text.
/// Gets the maximum side-slip angle info text.
/// </summary>
/// -------------------------------------------------------------------------------------------------
public string MaxSideSlipAngleInfo => this.MaxSideSlipAngle.ToString("Left, 0.00;Right, 0.00;None, 0");
Expand Down

0 comments on commit c06853e

Please sign in to comment.