Skip to content

Commit

Permalink
Feat/RT/Weather: Correct interpolation of WDIRs; Control info in Status
Browse files Browse the repository at this point in the history
  • Loading branch information
TwinFan committed Jul 14, 2024
1 parent 59958c4 commit 27a2e17
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 32 deletions.
1 change: 0 additions & 1 deletion Include/LTRealTraffic.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

#define REALTRAFFIC_NAME "RealTraffic"

// TODO: Return to v3 endpoint
#define RT_ENDP "v4"
#define RT_METAR_UNKN "UNKN"

Expand Down
19 changes: 15 additions & 4 deletions Include/LTWeather.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@

/// Initialize Weather module, dataRefs
bool WeatherInit ();
/// Indicate that we are taking control now
void WeatherTakeControl ();
/// Are we controlling weather?
bool WeatherInControl ();
/// Return a human readable string on the weather source, is "LiveTraffic" if WeatherInControl()
std::string WeatherGetSource ();
/// Reset weather settings to what they were before X-Plane took over
void WeatherReset ();
/// Shutdown Weather module
void WeatherStop ();

// TODO: Need a WeatherReset() option to go back to the status before we defined weather

//
// MARK: Set X-Plane Weather
//
Expand Down Expand Up @@ -91,11 +97,16 @@ struct LTWeather
void Interpolate (const std::array<InterpolSet,13>& aInterpol,
const std::vector<float>& from,
std::array<float,13>& to);

/// @brief Fill directions/headings from a differently sized input vector based on interpolation
/// @details Headings need to be interpolate separately as the average of 359 and 001 is 000 rather than 180...
void InterpolateDir (const std::array<InterpolSet,13>& aInterpol,
const std::vector<float>& from,
std::array<float,13>& to);

};

/// Can we set weather? (X-Plane 12 forward only)
bool CanSetWeather ();
bool WeatherCanSet ();

//
// MARK: Fetch METAR
Expand Down
4 changes: 4 additions & 0 deletions Src/InfoListWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ void InfoListWnd::buildInterface()
}

// Weather
ImGui::TableNextRow();
if (ImGui::TableSetColumnIndex(0)) ImGui::TextUnformatted("Weather Source");
if (ImGui::TableSetColumnIndex(1)) ImGui::TextUnformatted(WeatherGetSource().c_str());

ImGui::TableNextRow();
if (ImGui::TableSetColumnIndex(0)) ImGui::TextUnformatted("Live Weather");
if (ImGui::TableSetColumnIndex(1)) {
Expand Down
18 changes: 4 additions & 14 deletions Src/LTMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1022,23 +1022,13 @@ float LoopCBAircraftMaintenance (float inElapsedSinceLastCall, float, int, void*
int MPIntPrefsFunc (const char*, const char* key, int iDefault)
{
// debug XPMP's CSL model matching if requested
if (!strcmp(key, XPMP_CFG_ITM_MODELMATCHING)) {
if constexpr (LIVETRAFFIC_VERSION_BETA) // force logging of model-matching in BETA versions
return true;
else
return dataRefs.GetDebugModelMatching();
}
if (!strcmp(key, XPMP_CFG_ITM_MODELMATCHING)) return dataRefs.GetDebugModelMatching();
// logging level to match ours
if (!strcmp(key, XPMP_CFG_ITM_LOGLEVEL)) {
if constexpr (LIVETRAFFIC_VERSION_BETA) // force DEBUG-level logging in BETA versions
return logDEBUG;
else
return dataRefs.GetLogLevel();
}
if (!strcmp(key, XPMP_CFG_ITM_LOGLEVEL)) return dataRefs.GetLogLevel();
// We don't want clamping to the ground, we take care of the ground ourselves
if (!strcmp(key, XPMP_CFG_ITM_CLAMPALL)) return 0;
if (!strcmp(key, XPMP_CFG_ITM_CLAMPALL)) return 0;
// We want XPMP2 to assign unique modeS_ids if we feed duplicates (which can happen due to different id systems in use, especially ICAO vs FLARM)
if (!strcmp(key, XPMP_CFG_ITM_HANDLE_DUP_ID)) return 1;
if (!strcmp(key, XPMP_CFG_ITM_HANDLE_DUP_ID)) return 1;
// Copying .obj files is an advanced setting
if (!strcmp(key, XPMP_CFG_ITM_REPLDATAREFS) ||
!strcmp(key, XPMP_CFG_ITM_REPLTEXTURE))
Expand Down
10 changes: 7 additions & 3 deletions Src/LTRealTraffic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ void RealTrafficConnection::MainDirect ()
rtWx.nErr = 0;
lTotalFlights = -1;
// If we could theoretically set weather we prepare the interpolation settings
if (CanSetWeather()) {
if (WeatherCanSet()) {
rtWx.interp = LTWeather::ComputeInterpol(RT_ATMOS_LAYERS,
rtWx.w.atmosphere_alt_levels_m);
}
Expand Down Expand Up @@ -257,6 +257,10 @@ void RealTrafficConnection::MainDirect ()
LOG_MSG(logERR, ERR_TOP_LEVEL_EXCEPTION, "(unknown type)");
IncErrCnt();
}

// Reset weather control (this assumes noone else can control weather and
// would need to change once any other source in LiveTraffic can do so)
WeatherReset();
}

// Which request do we need now?
Expand Down Expand Up @@ -551,7 +555,7 @@ bool RealTrafficConnection::ProcessFetchedData ()
}

// If requested to set X-Plane's weather process the detailed weather data
if (dataRefs.ShallSetRTWeather())
if (WeatherCanSet() && dataRefs.ShallSetRTWeather())
ProcessWeather (json_object_get_object(pObj, "data"));

// Successfully received local pressure information
Expand Down Expand Up @@ -868,7 +872,7 @@ void RealTrafficConnection::ProcessWeather(const JSON_Object* pData)
[](float& f){ f *= float(NM_per_KM); }); // convert from km/h to kn=nm/h
}
if (pWDIRs)
rtWx.w.Interpolate(rtWx.interp, jag_f_vector(pWDIRs), rtWx.w.wind_direction_degt); // TODO: Interpolating wind directions needs to be handled specially...the middle between 359 and 001 is 000....
rtWx.w.InterpolateDir(rtWx.interp, jag_f_vector(pWDIRs), rtWx.w.wind_direction_degt);
if (pDZDTs) {
rtWx.w.Interpolate(rtWx.interp, jag_f_vector(pDZDTs), rtWx.w.turbulence);
std::for_each(rtWx.w.turbulence.begin(), rtWx.w.turbulence.end(),
Expand Down
119 changes: 109 additions & 10 deletions Src/LTWeather.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,13 @@ LTWeather::LTWeather()
void LTWeather::Set (bool bForceImmediately)
{
// Set weather with immediate effect if first time, or if position changed dramatically
const bool bImmediately = bForceImmediately || !lastPos.isNormal() || lastPos.dist(dataRefs.GetViewPos()) > WEATHER_MAX_DIST;
const bool bImmediately = !WeatherInControl() || bForceImmediately || !lastPos.isNormal() || lastPos.dist(dataRefs.GetViewPos()) > WEATHER_MAX_DIST;
if (bImmediately) {
SHOW_MSG(logINFO, "LiveTraffic is setting X-Plane's weather");
if (!WeatherInControl()) {
WeatherTakeControl();
} else {
SHOW_MSG(logINFO, "LiveTraffic is re-setting X-Plane's weather");
}
}
wdr_update_immediately.set(bImmediately);
lastPos = dataRefs.GetViewPos();
Expand Down Expand Up @@ -368,7 +372,7 @@ std::array<LTWeather::InterpolSet,13> LTWeather::ComputeInterpol (const std::vec
return ret;
}

/// Fill values from a differently sized input vector based on interpolation
// Fill values from a differently sized input vector based on interpolation
void LTWeather::Interpolate (const std::array<InterpolSet,13>& aInterpol,
const std::vector<float>& from,
std::array<float,13>& to)
Expand All @@ -382,6 +386,28 @@ void LTWeather::Interpolate (const std::array<InterpolSet,13>& aInterpol,
}
}

// Fill directions/headings from a differently sized input vector based on interpolation
// Headings need to be interpolate separately as the average of 359 and 001 is 000 rather than 180...
void LTWeather::InterpolateDir (const std::array<InterpolSet,13>& aInterpol,
const std::vector<float>& from,
std::array<float,13>& to)
{
for (size_t i = 0; i < aInterpol.size(); ++i) {
const InterpolSet& is = aInterpol[i];
if (is.i+1 < from.size()) {
double h1 = HeadingNormalize(from[is.i]);
double h2 = HeadingNormalize(from[is.i+1]);
const double hDiff = h1 - h2;
if (hDiff > 180.0) // case of 359 and 001
h2 += 360.0;
else if (hDiff < -180.0) // case of 001 and 359
h1 += 360.0;
to[i] = (float)HeadingNormalize(h1 * is.w + h2 * (1-is.w));
}
else to[i] = NAN;
}
}


//
// MARK: Weather Network Request handling
Expand Down Expand Up @@ -606,13 +632,16 @@ bool WeatherFetch (float _lat, float _lon, float _radius_nm)
// MARK: Global functions
//

static bool bCanSetWeather = false;
static bool bWeatherCanSet = false; ///< Would it be possible for LiveTraffic to control weather? (XP12 onwards)
static bool bWeatherControlling = false; ///< Is LiveTraffic in control of weather?
static int weatherOrigSource = -1; ///< Original value of `sim/weather/region/weather_source` before LiveTraffic took over
static int weatherOrigChangeMode = -1; ///< Original value of `sim/weather/region/change_mode` before LiveTraffic took over

// Initialize Weather module, dataRefs
bool WeatherInit ()
{
bCanSetWeather = WeatherInitDataRefs();
if (!bCanSetWeather) {
bWeatherCanSet = WeatherInitDataRefs();
if (!bWeatherCanSet) {
LOG_MSG(logWARN, "Could not find all Weather dataRefs, cannot set X-Plane's weather (X-Plane < v12?)");
}
#if DEBUG
Expand All @@ -621,19 +650,89 @@ bool WeatherInit ()
dataRefs.SetDebugLogWeather(true);
}
#endif
return bCanSetWeather;
return bWeatherCanSet;
}

// Indicate that we are taking control now
void WeatherTakeControl ()
{
if (!WeatherCanSet()) {
SHOW_MSG(logWARN, "Requested to take control of weather, but cannot due to missing dataRefs");
return;
}

weatherOrigSource = wdr_weather_source.get();
weatherOrigChangeMode = wdr_change_mode.get();
if (dataRefs.ShallLogWeather()) {
SHOW_MSG(logDEBUG, "Weather originally %s (source = %d, change mode = %d)",
WeatherGetSource().c_str(),
weatherOrigSource, weatherOrigChangeMode);
LTWeather().Get("Weather just prior to LiveTraffic taking over:");
}
SHOW_MSG(logINFO, "LiveTraffic takes over controlling X-Plane's weather");
bWeatherControlling = true;
}

// Are we controlling weather?
bool WeatherInControl ()
{
return bWeatherControlling;
}

/// Return a human readable string on the weather source, is "LiveTraffic" if WeatherInControl()
std::string WeatherGetSource ()
{
// Preset closest to current conditions
static std::array<const char*,10> WEATHER_PRESETS = {
"Clear", "VFR Few", "VFR Scattered", "VFR Broken", "VFR Marginal", "IFR Non-precision", "IFR Precision", "Convective", "Large-cell Storms", "Unknown"
};
int preset = wdr_weather_preset.get();
if (preset < 0 || preset > 8) preset = 9; // 'Unknown'

// Weather Source
static std::array<const char*,5> WEATHER_SOURCES = {
"X-Plane Preset", "X-Plane Real Weather", "Controlpad", "Plugin", "Unknown"
};
int source = wdr_weather_source.get();
if (source < 0 || source > 3) source = 4;

// Are we in control? Say so!
if (WeatherInControl())
return std::string("LiveTraffic using RealTraffic data, ") + WEATHER_PRESETS[size_t(preset)];
else
return std::string(WEATHER_SOURCES[size_t(source)]) + ", " + WEATHER_PRESETS[size_t(preset)];
}

// Reset weather settings to what they were before X-Plane took over
void WeatherReset ()
{
if (weatherOrigSource >= 0) wdr_weather_source.set(weatherOrigSource);
if (weatherOrigChangeMode >= 0) wdr_change_mode.set(weatherOrigChangeMode);

if (bWeatherControlling) {
bWeatherControlling = false;
SHOW_MSG(logINFO, "LiveTraffic no longer controls X-Plane's weather, reset to previous settings");
if (dataRefs.ShallLogWeather()) {
LOG_MSG(logDEBUG, "Weather reset to %s (source = %d, change mode = %d)",
WeatherGetSource().c_str(),
weatherOrigSource, weatherOrigChangeMode);
}
}

weatherOrigSource = -1;
weatherOrigChangeMode = -1;
}

// Shutdown Weather module
void WeatherStop ()
{

WeatherReset();
}

// Can we set weather? (X-Plane 12 forward only)
bool CanSetWeather ()
bool WeatherCanSet ()
{
return bCanSetWeather;
return bWeatherCanSet;
}


Expand Down

0 comments on commit 27a2e17

Please sign in to comment.