Skip to content

Commit

Permalink
wip: calculate glideslope drift
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyTWF committed Dec 27, 2023
1 parent 4166861 commit 1db137a
Show file tree
Hide file tree
Showing 14 changed files with 265 additions and 5 deletions.
9 changes: 7 additions & 2 deletions src/plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ set(src__approach
approach/ApproachSequencerDisplayOptions.cpp approach/ApproachSequencerDisplayOptions.h
approach/ApproachSequencerDisplayAsrLoader.cpp approach/ApproachSequencerDisplayAsrLoader.h
approach/ToggleApproachSequencerDisplay.cpp approach/ToggleApproachSequencerDisplay.h
approach/SequencerAirfieldSelector.cpp approach/SequencerAirfieldSelector.h approach/AircraftSelectionProvider.cpp approach/AircraftSelectionProvider.h approach/TargetSelectorList.cpp approach/TargetSelectorList.h approach/ApproachSpacingCalculator.cpp approach/ApproachSpacingCalculator.h approach/ApproachSequencerOptions.cpp approach/ApproachSequencerOptions.h approach/AirfieldApproachOptions.h approach/ApproachSequencerOptionsLoader.cpp approach/ApproachSequencerOptionsLoader.h approach/AirfieldTargetSelectorList.cpp approach/AirfieldTargetSelectorList.h approach/ApproachSequencerDistanceOptions.cpp approach/ApproachSequencerDistanceOptions.h approach/RemoveLandedAircraft.cpp approach/RemoveLandedAircraft.h approach/ApproachFlightplanEventHandler.cpp approach/ApproachFlightplanEventHandler.h)
approach/SequencerAirfieldSelector.cpp approach/SequencerAirfieldSelector.h approach/AircraftSelectionProvider.cpp approach/AircraftSelectionProvider.h approach/TargetSelectorList.cpp approach/TargetSelectorList.h approach/ApproachSpacingCalculator.cpp approach/ApproachSpacingCalculator.h approach/ApproachSequencerOptions.cpp approach/ApproachSequencerOptions.h approach/AirfieldApproachOptions.h approach/ApproachSequencerOptionsLoader.cpp approach/ApproachSequencerOptionsLoader.h approach/AirfieldTargetSelectorList.cpp approach/AirfieldTargetSelectorList.h approach/ApproachSequencerDistanceOptions.cpp approach/ApproachSequencerDistanceOptions.h approach/RemoveLandedAircraft.cpp approach/RemoveLandedAircraft.h approach/ApproachFlightplanEventHandler.cpp approach/ApproachFlightplanEventHandler.h
approach/GlideslopeDriftEstimator.h
approach/GlideslopeDriftEstimator.cpp)
source_group("src\\approach" FILES ${src__approach})

set(src__bootstrap
Expand Down Expand Up @@ -282,7 +284,10 @@ set(src__flightrule
source_group("src\\flightrule" FILES ${src__flightrule})

set(src__geometry
geometry/Line.cpp geometry/Line.h geometry/DistanceRadiusToScreenRadius.cpp geometry/DistanceRadiusToScreenRadius.h geometry/MeasurementUnitType.h geometry/MeasurementUnitFactory.cpp geometry/MeasurementUnitFactory.h geometry/Measurement.cpp geometry/Measurement.h geometry/MeasurementUnit.cpp geometry/MeasurementUnit.h)
geometry/Line.cpp geometry/Line.h geometry/DistanceRadiusToScreenRadius.cpp geometry/DistanceRadiusToScreenRadius.h geometry/MeasurementUnitType.h geometry/MeasurementUnitFactory.cpp geometry/MeasurementUnitFactory.h geometry/Measurement.cpp geometry/Measurement.h geometry/MeasurementUnit.cpp geometry/MeasurementUnit.h
geometry/Angle.cpp
geometry/Angle.h
)
source_group("src\\geometry" FILES ${src__geometry})

set(src__graphics
Expand Down
27 changes: 27 additions & 0 deletions src/plugin/approach/GlideslopeDriftEstimator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "GlideslopeDriftEstimator.h"
#include "euroscope/EuroScopeCRadarTargetInterface.h"
#include "runway/Runway.h"

namespace UKControllerPlugin::Approach {

auto GlideslopeDriftEstimator::CalculateGlideslopeDrift(
const Euroscope::EuroScopeCRadarTargetInterface& radarTarget, const Runway::Runway& runway) -> int
{
// Calculate the slope of each line
const auto runwaySlope = runway.RunwayHeadingLineSlope();
const auto runwayPerpendicularSlope = runway.RunwayPerpendicularHeadingLineSlope();

// Calculate the distance between the intersection and the threshold
EuroScopePlugIn::CPosition intersection;
intersection.m_Latitude = (runwaySlope * runway.Threshold().m_Latitude -
runwayPerpendicularSlope * radarTarget.GetPosition().m_Latitude +
radarTarget.GetPosition().m_Longitude - runway.Threshold().m_Longitude) /
(runwaySlope - runwayPerpendicularSlope);
intersection.m_Longitude =
runwaySlope * (intersection.m_Latitude - runway.Threshold().m_Latitude) + runway.Threshold().m_Longitude;
const auto distance = runway.Threshold().DistanceTo(intersection);

// Calculate the difference between the glideslope altitude and the aircraft altitude
return runway.GlideslopeAltitudeAtDistance(distance) - radarTarget.GetAltitude();
}
} // namespace UKControllerPlugin::Approach
20 changes: 20 additions & 0 deletions src/plugin/approach/GlideslopeDriftEstimator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

namespace UKControllerPlugin {
namespace Euroscope {
class EuroScopeCRadarTargetInterface;
} // namespace Euroscope
namespace Runway {
class Runway;
} // namespace Runway
} // namespace UKControllerPlugin

namespace UKControllerPlugin::Approach {

class GlideslopeDriftEstimator
{
public:
[nodiscard] auto CalculateGlideslopeDrift(
const Euroscope::EuroScopeCRadarTargetInterface& radarTarget, const Runway::Runway& runway) -> int;
};
} // namespace UKControllerPlugin::Approach
21 changes: 21 additions & 0 deletions src/plugin/geometry/Angle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "Angle.h"

namespace UKControllerPlugin::Geometry {

const double pi = 3.14159265358979323846;

auto DegreesToRadians(const double degrees) -> double
{
return degrees * pi / 180;
}

auto RadiansToDegrees(const double radians) -> double
{
return radians * 180 / pi;
}

auto Slope(const double radians) -> double
{
return std::tan(radians);
}
} // namespace UKControllerPlugin::Geometry
8 changes: 8 additions & 0 deletions src/plugin/geometry/Angle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

namespace UKControllerPlugin::Geometry {
[[nodiscard]] auto DegreesToRadians(const double degrees) -> double;
[[nodiscard]] auto RadiansToDegrees(const double radians) -> double;
[[nodiscard]] auto Slope(const double radians) -> double;

} // namespace UKControllerPlugin::Geometry
10 changes: 10 additions & 0 deletions src/plugin/headings/Heading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,14 @@ namespace UKControllerPlugin::Headings {
{
return first == static_cast<unsigned int>(second);
}

[[nodiscard]] auto TruncateHeading(unsigned int heading) -> unsigned int
{
return heading % 360;
}

[[nodiscard]] auto PerpendicularHeading(unsigned int heading) -> unsigned int
{
return TruncateHeading(heading + 90);
}
} // namespace UKControllerPlugin::Headings
3 changes: 3 additions & 0 deletions src/plugin/headings/Heading.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ namespace UKControllerPlugin::Headings {
auto operator<(double first, Heading second) -> bool;
auto operator>=(double first, Heading second) -> bool;
auto operator==(unsigned int first, Heading second) -> bool;

[[nodiscard]] auto TruncateHeading(unsigned int heading) -> unsigned int;
[[nodiscard]] auto PerpendicularHeading(unsigned int heading) -> unsigned int;
} // namespace UKControllerPlugin::Headings
26 changes: 25 additions & 1 deletion src/plugin/runway/Runway.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
#include "Runway.h"
#include "geometry/Angle.h"
#include "headings/Heading.h"

namespace UKControllerPlugin::Runway {

Runway::Runway(int id, int airfieldId, std::string identifier, int heading, EuroScopePlugIn::CPosition threshold)
: id(id), airfieldId(airfieldId), identifier(std::move(identifier)), heading(heading), threshold(threshold)
// TODO: Remove hard-coded threshold elevation and glideslope angle
: id(id), airfieldId(airfieldId), identifier(std::move(identifier)), heading(heading),
headingRadians(Geometry::DegreesToRadians(heading)),
perpendicularHeading(Headings::PerpendicularHeading(heading)),
perpendicularHeadingRadians(Geometry::DegreesToRadians(perpendicularHeading)),
runwayHeadingLineSlope(Geometry::Slope(headingRadians)),
runwayPerpendicularHeadingLineSlope(Geometry::Slope(perpendicularHeadingRadians)), threshold(threshold),
thresholdElevation(196), glideslopeAngleRadians(Geometry::DegreesToRadians(3))
{
}

Expand Down Expand Up @@ -31,4 +40,19 @@ namespace UKControllerPlugin::Runway {
{
return threshold;
}

auto Runway::GlideslopeAltitudeAtDistance(const double distanceInNauticalMiles) const -> int
{
return (glideslopeAngleRadians * (distanceInNauticalMiles * 6076.12)) + thresholdElevation;
}

auto Runway::RunwayHeadingLineSlope() const -> double
{
return runwayHeadingLineSlope;
}

auto Runway::RunwayPerpendicularHeadingLineSlope() const -> double
{
return runwayPerpendicularHeadingLineSlope;
}
} // namespace UKControllerPlugin::Runway
27 changes: 27 additions & 0 deletions src/plugin/runway/Runway.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ namespace UKControllerPlugin::Runway {
[[nodiscard]] auto Identifier() const -> const std::string&;
[[nodiscard]] auto Heading() const -> int;
[[nodiscard]] auto Threshold() const -> const EuroScopePlugIn::CPosition&;
[[nodiscard]] auto GlideslopeAltitudeAtDistance(const double distanceInNauticalMiles) const -> int;
[[nodiscard]] auto RunwayHeadingLineSlope() const -> double;
[[nodiscard]] auto RunwayPerpendicularHeadingLineSlope() const -> double;

private:
// A convenient calculation of pi
const double pi = std::atan(1) * 4;

// The id of the runway in the API
int id;

Expand All @@ -27,7 +33,28 @@ namespace UKControllerPlugin::Runway {
// The heading of the runway
int heading;

// The heading of the runway in radians
double headingRadians;

// The perpendicular heading of the runway
int perpendicularHeading;

// The perpendicular heading of the runway in radians
double perpendicularHeadingRadians;

// The slope of the runway heading line
double runwayHeadingLineSlope;

// The slope of the runway perpendicular heading line
double runwayPerpendicularHeadingLineSlope;

// The coordinates of the runway threshold
EuroScopePlugIn::CPosition threshold;

// The elevation of the runway threshold
int thresholdElevation;

// The glideslope angle (in radians)
double glideslopeAngleRadians;
};
} // namespace UKControllerPlugin::Runway
6 changes: 4 additions & 2 deletions test/plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ set(test__approach
approach/ApproachSequencerDisplayOptionsTest.cpp
approach/ApproachSequencerDisplayAsrLoaderTest.cpp
approach/ToggleApproachSequencerDisplayTest.cpp
approach/SequencerAirfieldSelectorTest.cpp approach/ApproachModuleFactoryTest.cpp approach/AircraftSelectionProviderTest.cpp approach/TargetSelectorListTest.cpp wake/ApproachSpacingCalculatorTest.cpp approach/ApproachSequencerOptionsTest.cpp approach/ApproachSequencerOptionsLoaderTest.cpp approach/AirfieldTargetSelectorListTest.cpp approach/ApproachSequencerDistanceOptionsTest.cpp approach/AirfieldMinimumSeparationSelectorListTest.cpp approach/RemoveLandedAircraftTest.cpp approach/ApproachFlightplanEventHandlerTest.cpp)
approach/SequencerAirfieldSelectorTest.cpp approach/ApproachModuleFactoryTest.cpp approach/AircraftSelectionProviderTest.cpp approach/TargetSelectorListTest.cpp wake/ApproachSpacingCalculatorTest.cpp approach/ApproachSequencerOptionsTest.cpp approach/ApproachSequencerOptionsLoaderTest.cpp approach/AirfieldTargetSelectorListTest.cpp approach/ApproachSequencerDistanceOptionsTest.cpp approach/AirfieldMinimumSeparationSelectorListTest.cpp approach/RemoveLandedAircraftTest.cpp approach/ApproachFlightplanEventHandlerTest.cpp
approach/GlideslopeDriftEstimatorTest.cpp)
source_group("test\\approach" FILES ${test__approach})

set(test__bootstrap
Expand Down Expand Up @@ -152,7 +153,8 @@ set(test__flightrule
source_group("test\\flightrule" FILES ${test__flightrule})

set(test__geometry
geometry/LineTest.cpp geometry/DistanceRadiusToScreenRadiusTest.cpp geometry/MeasurementUnitFactoryTest.cpp)
geometry/LineTest.cpp geometry/DistanceRadiusToScreenRadiusTest.cpp geometry/MeasurementUnitFactoryTest.cpp
geometry/AngleTest.cpp)
source_group("test\\geometry" FILES ${test__geometry})

set(test__handoff
Expand Down
37 changes: 37 additions & 0 deletions test/plugin/approach/GlideslopeDriftEstimatorTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "approach/GlideslopeDriftEstimator.h"
#include "runway/Runway.h"

namespace UKControllerPluginTest::Approach {
class GlideslopeDriftEstimatorTest : public ::testing::Test
{
public:
GlideslopeDriftEstimatorTest() : runway(1, 1, "26L", 257, RunwayPosition())
{
}

[[nodiscard]] auto RunwayPosition() -> EuroScopePlugIn::CPosition
{
EuroScopePlugIn::CPosition pos;
pos.m_Latitude = 51.150675;
pos.m_Longitude = -0.171925;
return pos;
}

UKControllerPlugin::Runway::Runway runway;
testing::NiceMock<Euroscope::MockEuroScopeCRadarTargetInterface> radarTarget;
UKControllerPlugin::Approach::GlideslopeDriftEstimator glideslopeDriftEstimator;
};

TEST_F(GlideslopeDriftEstimatorTest, CalculateGlideslopeDrift)
{
EuroScopePlugIn::CPosition aircraftPosition;
// Approx 8DME
aircraftPosition.m_Latitude = 51.17575;
aircraftPosition.m_Longitude = 0.00829;
ON_CALL(radarTarget, GetPosition()).WillByDefault(testing::Return(aircraftPosition));
ON_CALL(radarTarget, GetAltitude()).WillByDefault(testing::Return(2000));

const auto result = glideslopeDriftEstimator.CalculateGlideslopeDrift(radarTarget, runway);
ASSERT_DOUBLE_EQ(result, 448);
}
} // namespace UKControllerPluginTest::Approach
32 changes: 32 additions & 0 deletions test/plugin/geometry/AngleTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "geometry/Angle.h"

namespace UKControllerPluginTest::Geometry {
class AngleTest : public ::testing::Test
{
public:
const double pi = 3.14159265358979323846;
};

TEST_F(AngleTest, DegreesToRadians)
{
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::DegreesToRadians(0), 0);
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::DegreesToRadians(90), pi / 2);
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::DegreesToRadians(180), pi);
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::DegreesToRadians(270), pi * 1.5);
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::DegreesToRadians(360), pi * 2);
}

TEST_F(AngleTest, RadiansToDegrees)
{
EXPECT_EQ(UKControllerPlugin::Geometry::RadiansToDegrees(0), 0);
EXPECT_EQ(UKControllerPlugin::Geometry::RadiansToDegrees(pi / 2), 90);
EXPECT_EQ(UKControllerPlugin::Geometry::RadiansToDegrees(pi), 180);
EXPECT_EQ(UKControllerPlugin::Geometry::RadiansToDegrees(pi * 1.5), 270);
EXPECT_EQ(UKControllerPlugin::Geometry::RadiansToDegrees(pi * 2), 360);
}

TEST_F(AngleTest, Slope)
{
EXPECT_DOUBLE_EQ(UKControllerPlugin::Geometry::Slope(pi / 2), 1.633123935319537e+16);
}
} // namespace UKControllerPluginTest::Geometry
25 changes: 25 additions & 0 deletions test/plugin/headings/HeadingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,29 @@ namespace UKControllerPluginTest::Headings {
{
EXPECT_FALSE(225.0 >= Heading::W);
}

TEST_F(HeadingTest, ItDoesntTruncateHeadingLessThan360)
{
EXPECT_EQ(45, UKControllerPlugin::Headings::TruncateHeading(45));
}

TEST_F(HeadingTest, ItTruncatesHeadingGreaterThan360)
{
EXPECT_EQ(45, UKControllerPlugin::Headings::TruncateHeading(405));
}

TEST_F(HeadingTest, ItTruncatesHeadingEqualTo360)
{
EXPECT_EQ(0, UKControllerPlugin::Headings::TruncateHeading(360));
}

TEST_F(HeadingTest, ItCalculatesPerpendicularHeadingWithNoTruncate)
{
EXPECT_EQ(90, UKControllerPlugin::Headings::PerpendicularHeading(0));
}

TEST_F(HeadingTest, ItCalculatesPerpendicularHeadingWithTruncate)
{
EXPECT_EQ(90, UKControllerPlugin::Headings::PerpendicularHeading(360));
}
} // namespace UKControllerPluginTest::Headings
19 changes: 19 additions & 0 deletions test/plugin/runway/RunwayTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,23 @@ namespace UKControllerPluginTest::Runway {
EXPECT_EQ(3, runway.Threshold().m_Latitude);
EXPECT_EQ(4, runway.Threshold().m_Longitude);
}

TEST_F(RunwayTest, ItCalculatesGlideslopeAltitudeAtDistance)
{
// At the threshold
EXPECT_EQ(196, runway.GlideslopeAltitudeAtDistance(0));

// 6.95 nm (8 miles)
EXPECT_EQ(2407, runway.GlideslopeAltitudeAtDistance(6.95));
}

TEST_F(RunwayTest, ItCalculatesRunwayHeadingLineSlope)
{
EXPECT_DOUBLE_EQ(-1.5398649638145827, runway.RunwayHeadingLineSlope());
}

TEST_F(RunwayTest, ItCalculatesRunwayPerpendicularHeadingLineSlope)
{
EXPECT_DOUBLE_EQ(0.64940759319751062, runway.RunwayPerpendicularHeadingLineSlope());
}
} // namespace UKControllerPluginTest::Runway

0 comments on commit 1db137a

Please sign in to comment.