Skip to content

Commit 2c7fb0c

Browse files
committed
Adjust altitude based on airport temperature
In newer flight simulators true altitude is affected by the temperature. In cold weather aircraft will be shown higher than they actually are, unless we correct for it. PS: people with older flight sims might be displayed with incorrect height on the glideslope when this option is enabled.
1 parent ed246cf commit 2c7fb0c

File tree

5 files changed

+58
-6
lines changed

5 files changed

+58
-6
lines changed

ILS_Window_Plugin/IWDataTypes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string>
44
#include <vector>
55
#include <memory>
6+
#include <map>
67

78
class IWWindow;
89

@@ -11,7 +12,7 @@ struct RGB {
1112
};
1213

1314
struct IWTargetPosition {
14-
int trueAltitude;
15+
int pressureCorrectedAltitude;
1516
double latitude;
1617
double longitude;
1718
};
@@ -26,6 +27,7 @@ struct IWRadarTarget {
2627

2728
struct IWLiveData {
2829
std::vector<IWRadarTarget> radarTargets;
30+
std::map<std::string, float> airportTemperatures;
2931
};
3032

3133
struct IWApproachDefinition {

ILS_Window_Plugin/IWPlugin.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ void IWPlugin::OnTimer(int seconds)
143143
aircraftWtc,
144144
positionHistory
145145
});
146+
liveData.airportTemperatures = airportTemperatures;
146147
}
147148
}
148149

@@ -156,6 +157,23 @@ void IWPlugin::OnAirportRunwayActivityChanged()
156157
SyncWithActiveRunways();
157158
}
158159

160+
void IWPlugin::OnNewMetarReceived(const char* sStation, const char* sFullMetar)
161+
{
162+
// Extract temperature from METAR to be used for altitude correction
163+
std::string station = std::string(sStation);
164+
std::string fullMetar = std::string(sFullMetar);
165+
std::regex temperatureRegex(R"((M?\d{2})\/(M?\d{2}))");
166+
std::smatch temperatureMatch;
167+
if (std::regex_search(fullMetar, temperatureMatch, temperatureRegex)) {
168+
std::string temperatureString = temperatureMatch[1];
169+
bool isNegative = temperatureString[0] == 'M';
170+
int temperature = std::stoi(temperatureString.substr(1));
171+
if (isNegative) {
172+
temperature = -temperature;
173+
}
174+
airportTemperatures[station] = temperature;
175+
}
176+
}
159177

160178
void IWPlugin::SyncWithActiveRunways()
161179
{

ILS_Window_Plugin/IWPlugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class IWPlugin : public EuroScopePlugIn::CPlugIn, IIWWndEventListener {
2222
IWStyling windowStyling;
2323
IWBehaviourSettings behaviourSettings;
2424
std::map<std::string, CRect> savedWindowPositions;
25+
std::map<std::string, float> airportTemperatures;
2526

2627
void OpenNewWindow(IWApproachDefinition* approach);
2728
void SyncWithActiveRunways();
@@ -34,6 +35,7 @@ class IWPlugin : public EuroScopePlugIn::CPlugIn, IIWWndEventListener {
3435
bool OnCompileCommand(const char* sCommandLine) override;
3536
void OnTimer(int seconds) override;
3637
void OnAirportRunwayActivityChanged() override;
38+
void OnNewMetarReceived(const char* sStation, const char* sFullMetar) override;
3739

3840
// Events from a window
3941
void OnWindowClosed(IWWindow* window) override;

ILS_Window_Plugin/IWWindow.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
#define MAX_PROCEDURES 100
66

7-
#define MENU_ITEM_FLIP 10000
8-
#define MENU_ITEM_SHOW_LABELS 10001
9-
#define MENU_ITEM_PROCEDURES_SEL_START 20000
10-
#define MENU_ITEM_PROCEDURES_NEW_START 30000
7+
#define MENU_ITEM_FLIP 10000
8+
#define MENU_ITEM_SHOW_LABELS 10001
9+
#define MENU_ITEM_CORRECT_FOR_TEMPERATURE 10002
10+
#define MENU_ITEM_PROCEDURES_SEL_START 20000
11+
#define MENU_ITEM_PROCEDURES_NEW_START 30000
1112

1213
BEGIN_MESSAGE_MAP(IWWindow, CWnd)
1314
ON_WM_PAINT()
@@ -28,6 +29,7 @@ BEGIN_MESSAGE_MAP(IWWindow, CWnd)
2829
ON_MESSAGE(WM_EXITSIZEMOVE, &IWWindow::OnExitSizeMove)
2930
ON_COMMAND_EX(MENU_ITEM_FLIP, &IWWindow::OnMenuOptionSelected)
3031
ON_COMMAND_EX(MENU_ITEM_SHOW_LABELS, &IWWindow::OnMenuOptionSelected)
32+
ON_COMMAND_EX(MENU_ITEM_CORRECT_FOR_TEMPERATURE, &IWWindow::OnMenuOptionSelected)
3133
ON_COMMAND_RANGE(MENU_ITEM_PROCEDURES_SEL_START, MENU_ITEM_PROCEDURES_SEL_START + MAX_PROCEDURES, &IWWindow::OnProcedureSelected)
3234
ON_COMMAND_RANGE(MENU_ITEM_PROCEDURES_NEW_START, MENU_ITEM_PROCEDURES_NEW_START + MAX_PROCEDURES, &IWWindow::OnProcedureSelected)
3335
END_MESSAGE_MAP()
@@ -476,10 +478,18 @@ void IWWindow::OnLButtonDown(UINT nFlags, CPoint point)
476478
bool IWWindow::CalculateTargetCoordinates(const IWTargetPosition& position, CPoint& ptTopView, CPoint& ptSideView)
477479
{
478480
// Calculate position relative to the runway
479-
double heightAboveThreshold = position.trueAltitude - selectedApproach.thresholdAltitude;
480481
double distanceToThreshold = CalculateDistance(position.latitude, position.longitude, selectedApproach.thresholdLatitude, selectedApproach.thresholdLongitude);
481482
double directionToThreshold = CalculateBearing(position.latitude, position.longitude, selectedApproach.thresholdLatitude, selectedApproach.thresholdLongitude);
482483
double angleDiff = (selectedApproach.localizerCourse - directionToThreshold) / 180.0 * PI; // anglediff in radians
484+
double heightAboveThreshold = position.pressureCorrectedAltitude - selectedApproach.thresholdAltitude;
485+
486+
if (applyTemperatureCorrection) {
487+
// In newer flight simulators true altitude is affected by the temperature.
488+
// In cold weather aircraft will be shown higher than they actually are, unless we correct for it.
489+
// See: https://forums.flightsimulator.com/t/vatsim-ivao-pilotedge-users-be-aware-of-an-important-bug/426142/468
490+
int temperatureCorrection = CalculateTemperatureCorrection(position.pressureCorrectedAltitude, selectedApproach.thresholdAltitude, m_latestLiveData.airportTemperatures[selectedApproach.airport]);
491+
heightAboveThreshold -= temperatureCorrection;
492+
}
483493

484494
double projectedDistanceFromThreshold = distanceToThreshold * cos(angleDiff);
485495
double projectedDistanceFromExtendedCenterline = distanceToThreshold * tan(angleDiff);
@@ -559,6 +569,13 @@ double IWWindow::CalculateBearing(double lat1, double lon1, double lat2, double
559569
return bearing * 180.0 / PI;
560570
}
561571

572+
double IWWindow::CalculateTemperatureCorrection(int planePressAlt, int airportPressureAlt, double surfTemp) {
573+
double isaDeviation = surfTemp - 15;
574+
575+
// Formula is from here: https://www.pprune.org/tech-log/573002-accurate-temperature-correction-formula.html
576+
return ((-isaDeviation / -0.0019812) * std::log(1 + (-0.0019812 * planePressAlt) / (288.15 + -0.0019812 * airportPressureAlt)));
577+
}
578+
562579
std::string IWWindow::GetActiveApproachName() const
563580
{
564581
std::lock_guard<std::mutex> lock(approachDataMutex);
@@ -611,6 +628,11 @@ void IWWindow::CreatePopupMenu(CPoint point)
611628
MENU_ITEM_SHOW_LABELS,
612629
_T("Show labels by default")
613630
);
631+
menu.AppendMenu(
632+
MF_STRING | (this->applyTemperatureCorrection ? MF_CHECKED : MF_UNCHECKED),
633+
MENU_ITEM_CORRECT_FOR_TEMPERATURE,
634+
_T("Apply temperature correction")
635+
);
614636
menu.AppendMenu(
615637
MF_STRING,
616638
MENU_ITEM_FLIP,
@@ -619,6 +641,7 @@ void IWWindow::CreatePopupMenu(CPoint point)
619641

620642
// Display the menu
621643
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
644+
622645
}
623646

624647
BOOL IWWindow::OnMenuOptionSelected(UINT nID)
@@ -634,6 +657,11 @@ BOOL IWWindow::OnMenuOptionSelected(UINT nID)
634657
this->showTagsByDefault = !this->showTagsByDefault;
635658
Invalidate();
636659
}
660+
else if (nID == MENU_ITEM_CORRECT_FOR_TEMPERATURE)
661+
{
662+
this->applyTemperatureCorrection = !this->applyTemperatureCorrection;
663+
Invalidate();
664+
}
637665
return TRUE;
638666
}
639667

ILS_Window_Plugin/IWWindow.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class IWWindow : public CWnd, IWTitleBarEventListener {
8181

8282
double CalculateDistance(double lat1, double lon1, double lat2, double lon2);
8383
double CalculateBearing(double lat1, double lon1, double lat2, double lon2);
84+
double CalculateTemperatureCorrection(int planePressAlt, int airportPressureAlt, double surfTemp);
8485

8586
COLORREF rangeStatusTextColor;
8687
COLORREF windowBackground;
@@ -99,6 +100,7 @@ class IWWindow : public CWnd, IWTitleBarEventListener {
99100

100101
int approachLength;
101102
bool leftToRight;
103+
bool applyTemperatureCorrection = true;
102104

103105
// Dimentions
104106
float approachHeightFt;

0 commit comments

Comments
 (0)