Skip to content

Commit

Permalink
Feat: Synthetic channel to keep parked aircraft, closes #255
Browse files Browse the repository at this point in the history
  • Loading branch information
TwinFan committed Jan 6, 2024
1 parent 451718c commit 8f61296
Show file tree
Hide file tree
Showing 20 changed files with 409 additions and 41 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ set(Header_Files
Include/LTOpenGlider.h
Include/LTOpenSky.h
Include/LTRealTraffic.h
Include/LTSynthetic.h
Include/LTWeather.h
Include/Network.h
Include/SettingsUI.h
Expand Down Expand Up @@ -196,6 +197,7 @@ set(Source_Files
Src/LTOpenGlider.cpp
Src/LTOpenSky.cpp
Src/LTRealTraffic.cpp
Src/LTSynthetic.cpp
Src/LTVersion.cpp
Src/LTWeather.cpp
Src/Network.cpp
Expand Down
1 change: 1 addition & 0 deletions Include/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ constexpr double AC_MAINT_INTVL = 2.0; // seconds (calling a/c maintena
constexpr double TIME_REQU_POS = 0.5; // seconds before reaching current 'to' position we request calculation of next position
constexpr double SIMILAR_TS_INTVL = 3; // seconds: Less than that difference and position-timestamps are considered "similar" -> positions are merged rather than added additionally
constexpr double SIMILAR_POS_DIST = 7; // [m] if distance between positions less than this then favor heading from flight data over vector between positions
constexpr double GND_COLLISION_DIST = 10; // [m] If another aircraft comes this close to a parked aircraft then the parked aircraft is removed
constexpr double FD_GND_AGL = 10; // [m] consider pos 'ON GRND' if this close to YProbe
constexpr double FD_GND_AGL_EXT = 20; // [m] consider pos 'ON GRND' if this close to YProbe - extended, e.g. for RealTraffic
constexpr double PROBE_HEIGHT_LIM[] = {5000,1000,500,-999999}; // if height AGL is more than ... feet
Expand Down
1 change: 1 addition & 0 deletions Include/DataRefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ enum dataRefsLT {
// channels, in ascending order of priority
DR_CHANNEL_FUTUREDATACHN_ONLINE, // placeholder, first channel
DR_CHANNEL_FORE_FLIGHT_SENDER,
DR_CHANNEL_SYNTHETIC,
DR_CHANNEL_FSCHARTER,
DR_CHANNEL_OPEN_GLIDER_NET,
DR_CHANNEL_ADSB_HUB,
Expand Down
2 changes: 1 addition & 1 deletion Include/LTADSBHub.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ADSBHubConnection : public LTFlightDataChannel
public:
/// Constructor
ADSBHubConnection ();
/// Invokes APRS thread, or returns URL to fetch current data from live.glidernet.org
/// No URL involved
std::string GetURL (const positionTy&) override { return ""; }
/// @brief Processes the fetched data
bool ProcessFetchedData () override { return true; };
Expand Down
9 changes: 9 additions & 0 deletions Include/LTApt.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ inline positionTy LTAptFindRwy (const LTAircraft& _ac, std::string& _rwyId, bool
bDoLogging ? std::string(_ac) : "");
}

/// @brief Find close-by startup position
/// @param pos Searching around this position
/// @param maxDist Max search distance
/// @param[out] outDist Receives distances between search pos and startup location, or `NAN` if no startup location found
/// @return Position of search position, heading is set to startup heading
positionTy LTAptFindStartupLoc (const positionTy& pos,
double maxDist = NAN,
double* outDist = nullptr);

/// @brief Snaps the passed-in position to the nearest rwy or taxiway if appropriate
/// @param fd Flight data object to be analyzed
/// @param[in,out] posIter Iterator into LTFlightData::posDeque, points to position to analyze, might change due to inserted taxi positions
Expand Down
7 changes: 5 additions & 2 deletions Include/LTChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class LTChannel
enum LTChannelType {
CHT_UNKNOWN = 0,
CHT_TRACKING_DATA,
CHT_SYNTHETIC_DATA, ///< data created internally by LiveTraffic, like kept parked aircraft, has lower priority than any real-life data
CHT_MASTER_DATA,
CHT_TRAFFIC_SENDER, // sends out data (not receiving)
};
Expand Down Expand Up @@ -192,8 +193,8 @@ class LTFlightDataChannel : public LTOnlineChannel {
mutable float timeLastAcCnt = 0.0; ///< when did we last count the a/c served by this channel?
mutable int numAcServed = 0; ///< how many a/c do we feed when counted last?
public:
LTFlightDataChannel (dataRefsLT ch, const char* chName) :
LTOnlineChannel(ch, CHT_TRACKING_DATA, chName) {}
LTFlightDataChannel (dataRefsLT ch, const char* chName, LTChannelType eType = CHT_TRACKING_DATA) :
LTOnlineChannel(ch, eType, chName) {}
int GetNumAcServed () const override; ///< how many a/c do we feed when counted last?
};

Expand Down Expand Up @@ -315,6 +316,8 @@ class LTACMasterdataChannel : public LTOnlineChannel
/// @brief Register a master data channel, that will be called to process requests
/// @note The order, in which registration happens, serves as a priority
static void RegisterMasterDataChn (LTACMasterdataChannel* pChn);
/// Unregister a mster data channel
static void UnregisterMasterDataChn (LTACMasterdataChannel* pChn);
/// Generically, uniquely add request to fetch data (returns `true` if added, `false` if duplicate)
static bool RequestMasterData (const LTFlightData::FDKeyTy& keyAc,
const std::string& callSign,
Expand Down
14 changes: 9 additions & 5 deletions Include/LTRealTraffic.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/// @file LTRealTraffic.h
/// @brief RealTraffic: Receives and processes live tracking data
/// @see https://rtweb.flyrealtraffic.com/
/// @details Defines RealTrafficConnection:\n
/// - Sends current position to RealTraffic app\n
/// - Receives tracking data via UDP\n
/// - Interprets the response and passes the tracking data on to LTFlightData.\n
/// @details Defines RealTrafficConnection in two different variants:\n
/// - Direct Connection:
/// - Expects RealTraffic license information
/// - Sends authentication, weather, and tracking data requests to RealTraffic servcers
/// - via RealTraffic app
/// - Sends current position to RealTraffic app\n
/// - Receives tracking data via UDP\n
/// - Interprets the response and passes the tracking data on to LTFlightData.\n
/// @author Birger Hoppe
/// @copyright (c) 2019-2020 Birger Hoppe
/// @copyright (c) 2019-2024 Birger Hoppe
/// @copyright Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
Expand Down
63 changes: 63 additions & 0 deletions Include/LTSynthetic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/// @file LTSynthetic.h
/// @brief Synthetic tracking data, e.g. for parked aircraft
/// @details Defines SyntheticConnection:
/// - Scans mapFd (all available tracking data in LiveTraffic)
/// for parked aircraft and keeps a position copy
/// - For any parked aircraft no longer actively served by any other channel,
/// send the same position data regularly
/// @author Birger Hoppe
/// @copyright (c) 2024 Birger Hoppe
/// @copyright Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:\n
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.\n
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.

#ifndef LTSynthetic_h
#define LTSynthetic_h

#include "LTChannel.h"

//
// MARK: SyntheticConnection
//

/// Synthetic tracking data creation
class SyntheticConnection : public LTFlightDataChannel
{
protected:
/// What information are we storing for parked planes
struct SynDataTy {
LTFlightData::FDStaticData stat; // plane's static data
positionTy pos; // plane's position
};
/// Stores position per tracked plane
typedef std::map<LTFlightData::FDKeyTy, SynDataTy> mapSynDataTy;
/// @brief Position information per tracked plane
/// @note Defined `static` to preserve information across restarts
static mapSynDataTy mapSynData;
public:
/// Constructor
SyntheticConnection ();
/// No URL involved
std::string GetURL (const positionTy&) override { return ""; }
/// Scan for relevant flight data
bool FetchAllData(const positionTy&) override;
/// Processes the available stored data
bool ProcessFetchedData () override;

protected:
void Main () override; ///< virtual thread main function
};

#endif /* LTSynthetic_h */
1 change: 1 addition & 0 deletions Include/LiveTraffic.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ extern DataRefs dataRefs;
#include "LTADSBHub.h"
#include "LTOpenGlider.h"
#include "LTFSCharter.h"
#include "LTSynthetic.h"

//MARK: Global Control functions
bool LTMainInit ();
Expand Down
2 changes: 1 addition & 1 deletion Lib/ImGui/imstb_truetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -3168,7 +3168,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
stbtt__active_edge * z = *step;
if (z->ey <= scan_y_top) {
*step = z->next; // delete from list
STBTT_assert(z->direction);
STBTT_assert(bool(z->direction)); // TwinFan: Silenced compiler warning on implicit type cast
z->direction = 0;
stbtt__hheap_free(&hh, z);
} else {
Expand Down
6 changes: 6 additions & 0 deletions LiveTraffic.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
25D293F725C625710007C72E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25D293F625C625710007C72E /* Cocoa.framework */; };
25D293FD25C625C10007C72E /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 25D293FC25C625C10007C72E /* libcurl.tbd */; };
25E9C2AF207D5B8100D3C642 /* LTFlightData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25E9C2AE207D5B8100D3C642 /* LTFlightData.cpp */; };
25EF90042B497C6100D7C805 /* LTSynthetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF90032B497C6100D7C805 /* LTSynthetic.cpp */; };
25F3471C24D2C7DE004574E7 /* parson.c in Sources */ = {isa = PBXBuildFile; fileRef = 25F3471B24D2C7DE004574E7 /* parson.c */; settings = {COMPILER_FLAGS = "-Wno-sign-conversion"; }; };
25F3471F24D2CB20004574E7 /* ACTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25F3471E24D2CB20004574E7 /* ACTable.cpp */; };
25FEB7B9224D7B10002A051F /* LTForeFlight.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25FEB7B8224D7B10002A051F /* LTForeFlight.cpp */; };
Expand Down Expand Up @@ -177,6 +178,8 @@
25D811002402D60A00A8723B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
25DC1E2A21B72922008D0F8B /* Data */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Data; sourceTree = "<group>"; };
25E9C2AE207D5B8100D3C642 /* LTFlightData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LTFlightData.cpp; sourceTree = "<group>"; };
25EF90032B497C6100D7C805 /* LTSynthetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LTSynthetic.cpp; sourceTree = "<group>"; };
25EF90052B497C7900D7C805 /* LTSynthetic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LTSynthetic.h; sourceTree = "<group>"; };
25EFC76B249567BF005DB0A6 /* IconsFontAwesome5.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IconsFontAwesome5.h; sourceTree = "<group>"; };
25EFC76C249567BF005DB0A6 /* fa-solid-900.inc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.pascal; path = "fa-solid-900.inc"; sourceTree = "<group>"; };
25F3471A24D2C7DE004574E7 /* parson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parson.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -307,6 +310,7 @@
259EC47925057815009B86F3 /* LTOpenGlider.cpp */,
2573631F22233CDA005210C5 /* LTOpenSky.cpp */,
2573631922233008005210C5 /* LTRealTraffic.cpp */,
25EF90032B497C6100D7C805 /* LTSynthetic.cpp */,
25ABEEFD219A1C2100F61413 /* LTVersion.cpp */,
254F278824EF230400CACCDA /* LTWeather.cpp */,
257363162222C879005210C5 /* Network.cpp */,
Expand Down Expand Up @@ -440,6 +444,7 @@
259EC47825057802009B86F3 /* LTOpenGlider.h */,
2573631C22233CCA005210C5 /* LTOpenSky.h */,
2573631B22233041005210C5 /* LTRealTraffic.h */,
25EF90052B497C7900D7C805 /* LTSynthetic.h */,
254F278724EF22FE00CACCDA /* LTWeather.h */,
257363182222C8E2005210C5 /* Network.h */,
25A095C32203B01300658AA8 /* SettingsUI.h */,
Expand Down Expand Up @@ -678,6 +683,7 @@
25ABEEFE219A1C2100F61413 /* LTVersion.cpp in Sources */,
254F278924EF230400CACCDA /* LTWeather.cpp in Sources */,
257363172222C879005210C5 /* Network.cpp in Sources */,
25EF90042B497C6100D7C805 /* LTSynthetic.cpp in Sources */,
25AE00D9213887AF00908E65 /* SettingsUI.cpp in Sources */,
25C59458207A296500E52073 /* TextIO.cpp in Sources */,
);
Expand Down
4 changes: 3 additions & 1 deletion Src/DataRefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ DataRefs::dataRefDefinitionT DATA_REFS_LT[CNT_DATAREFS_LT] = {
// channels, in ascending order of priority
{"livetraffic/channel/futuredatachn/online", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, false },
{"livetraffic/channel/fore_flight/sender", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, true, true },
{"livetraffic/channel/synthetic/intern", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, true, true },
{"livetraffic/channel/fscharter/online", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, true, true },
{"livetraffic/channel/open_glider/online", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, true, true },
{"livetraffic/channel/adsbhub/online", DataRefs::LTGetInt, DataRefs::LTSetBool, GET_VAR, true, true },
Expand Down Expand Up @@ -747,11 +748,12 @@ ILWrect (0, 400, 965, 0)
for ( int& i: bChannel )
i = false;

// enable OpenSky and OGN by default
// enable OpenSky, OGN, and Synthetic by default
bChannel[DR_CHANNEL_OPEN_SKY_ONLINE - DR_CHANNEL_FIRST] = true;
bChannel[DR_CHANNEL_OPEN_SKY_AC_MASTERDATA - DR_CHANNEL_FIRST] = true;
bChannel[DR_CHANNEL_OPEN_SKY_AC_MASTERFILE - DR_CHANNEL_FIRST] = true;
bChannel[DR_CHANNEL_OPEN_GLIDER_NET - DR_CHANNEL_FIRST] = true;
bChannel[DR_CHANNEL_SYNTHETIC - DR_CHANNEL_FIRST] = true;

// Clear the dataRefs arrays
memset ( adrXP, 0, sizeof(adrXP));
Expand Down
31 changes: 31 additions & 0 deletions Src/LTApt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2699,6 +2699,37 @@ positionTy LTAptFindRwy (const LTAircraft::FlightModel& _mdl,
}


// Find close-by startup position
positionTy LTAptFindStartupLoc (const positionTy& pos,
double maxDist,
double* outDist)
{
// Access to the list of airports is guarded by a lock
std::lock_guard<std::mutex> lock(mtxGMapApt);

// Which airport are we looking at?
Apt* pApt = LTAptFind(pos);
if (!pApt) { // not a position in any airport's bounding box
if (outDist) *outDist = NAN;
return positionTy();
}

// Let's go find!
if (std::isnan(maxDist))
maxDist = dataRefs.GetFdSnapTaxiDist_m() * 3; // same as in SnapToTaxiway()
const StartupLoc* pSuL = pApt->FindStartupLoc(pos, maxDist, outDist);
if (!pSuL)
return positionTy();
else {
positionTy ret (pSuL->lat, pSuL->lon, NAN, NAN, pSuL->heading);
ret.f.bHeadFixed = true;
ret.f.onGrnd = GND_ON;
ret.f.specialPos = SPOS_STARTUP;
return ret;
}
}


// Snaps the passed-in position to the nearest rwy or taxiway if appropriate
bool LTAptSnap (LTFlightData& fd, dequePositionTy::iterator& posIter,
bool bInsertTaxiTurns)
Expand Down
21 changes: 16 additions & 5 deletions Src/LTChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ std::string LTChannel::GetStatusText () const
return buf;
}
// Active, but not a channel for tracking data
if (GetChType() != CHT_TRACKING_DATA) return "Active";
if (GetChType() >= CHT_MASTER_DATA) return "Active";
// An active source of tracking data...for how many aircraft?
snprintf (buf, sizeof(buf), "Active, serving %d aircraft",
GetNumAcServed());
Expand Down Expand Up @@ -304,10 +304,7 @@ std::list<LTACMasterdataChannel*> LTACMasterdataChannel::lstChn;
// Constructor
LTACMasterdataChannel::LTACMasterdataChannel (dataRefsLT ch, const char* chName) :
LTOnlineChannel(ch, CHT_MASTER_DATA, chName)
{
// Register myself as a master data channel
RegisterMasterDataChn(this);
}
{}

/// Add the request to the set if not duplicate
bool LTACMasterdataChannel::InsertRequest (const acStatUpdateTy& r)
Expand Down Expand Up @@ -468,6 +465,19 @@ void LTACMasterdataChannel::RegisterMasterDataChn (LTACMasterdataChannel* pChn)
}
}

// Unregister a mster data channel
void LTACMasterdataChannel::UnregisterMasterDataChn (LTACMasterdataChannel* pChn)
{
try {
std::lock_guard<std::recursive_mutex> lock (mtxMaster);
// just remove the channel
lstChn.remove(pChn);
} catch(const std::system_error& e) {
LOG_MSG(logERR, ERR_LOCK_ERROR, "mtxMaster", e.what());
}
}


// Add request to fetch data
bool LTACMasterdataChannel::RequestMasterData (const LTFlightData::FDKeyTy& keyAc,
const std::string& callSign,
Expand Down Expand Up @@ -858,6 +868,7 @@ bool LTFlightDataEnable()
listFDC.emplace_back(new ADSBHubConnection());
listFDC.emplace_back(new OpenGliderConnection);
listFDC.emplace_back(new FSCConnection);
listFDC.emplace_back(new SyntheticConnection);
// load online master data connections
listFDC.emplace_back(new OpenSkyAcMasterFile);
listFDC.emplace_back(new OpenSkyAcMasterdata);
Expand Down
Loading

0 comments on commit 8f61296

Please sign in to comment.