Support for creating default SID/approach.
Durk reminded me of this - when we're missing procedures data (the common case), synthesise a plausible (but possibly dangerously unrealistic) departure and approach. Will work fine for airports in gentle terrain, and likely kill you at challenging airports. You have been warned.
This commit is contained in:
parent
25138930e3
commit
78d97fa468
7 changed files with 142 additions and 16 deletions
|
@ -262,9 +262,13 @@ private:
|
|||
mutable PositionedIDVec mTaxiways;
|
||||
PositionedIDVec mPavements;
|
||||
|
||||
std::vector<flightgear::SID*> mSIDs;
|
||||
std::vector<flightgear::STAR*> mSTARs;
|
||||
std::vector<flightgear::Approach*> mApproaches;
|
||||
typedef SGSharedPtr<flightgear::SID> SIDRef;
|
||||
typedef SGSharedPtr<flightgear::STAR> STARRef;
|
||||
typedef SGSharedPtr<flightgear::Approach> ApproachRef;
|
||||
|
||||
std::vector<SIDRef> mSIDs;
|
||||
std::vector<STARRef> mSTARs;
|
||||
std::vector<ApproachRef> mApproaches;
|
||||
};
|
||||
|
||||
// find basic airport location info from airport database
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
@ -913,6 +914,41 @@ const char* FGRouteMgr::getSID() const
|
|||
return "";
|
||||
}
|
||||
|
||||
flightgear::SID* createDefaultSID(FGRunway* aRunway)
|
||||
{
|
||||
if (!aRunway) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double runwayElevFt = aRunway->end().getElevationFt();
|
||||
WayptVec wpts;
|
||||
std::ostringstream ss;
|
||||
ss << aRunway->ident() << "-3";
|
||||
|
||||
SGGeod p = aRunway->pointOnCenterline(aRunway->lengthM() + (3.0 * SG_NM_TO_METER));
|
||||
p.setElevationFt(runwayElevFt + 2000.0);
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
ss.str("");
|
||||
ss << aRunway->ident() << "-6";
|
||||
p = aRunway->pointOnCenterline(aRunway->lengthM() + (6.0 * SG_NM_TO_METER));
|
||||
p.setElevationFt(runwayElevFt + 4000.0);
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
ss.str("");
|
||||
ss << aRunway->ident() << "-9";
|
||||
p = aRunway->pointOnCenterline(aRunway->lengthM() + (9.0 * SG_NM_TO_METER));
|
||||
p.setElevationFt(runwayElevFt + 6000.0);
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
BOOST_FOREACH(Waypt* w, wpts) {
|
||||
w->setFlag(WPT_DEPARTURE);
|
||||
w->setFlag(WPT_GENERATED);
|
||||
}
|
||||
|
||||
return SID::createTempSID("DEFAULT", aRunway, wpts);
|
||||
}
|
||||
|
||||
void FGRouteMgr::setSID(const char* aIdent)
|
||||
{
|
||||
FGAirport* apt = _plan->departureAirport();
|
||||
|
@ -921,6 +957,11 @@ void FGRouteMgr::setSID(const char* aIdent)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(aIdent, "DEFAULT")) {
|
||||
_plan->setSID(createDefaultSID(_plan->departureRunway()));
|
||||
return;
|
||||
}
|
||||
|
||||
string ident(aIdent);
|
||||
size_t hyphenPos = ident.find('-');
|
||||
if (hyphenPos != string::npos) {
|
||||
|
@ -990,9 +1031,56 @@ const char* FGRouteMgr::getApproach() const
|
|||
return "";
|
||||
}
|
||||
|
||||
flightgear::Approach* createDefaultApproach(FGRunway* aRunway)
|
||||
{
|
||||
if (!aRunway) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double thresholdElevFt = aRunway->threshold().getElevationFt();
|
||||
const double approachHeightFt = 2000.0;
|
||||
double glideslopeDistanceM = (approachHeightFt * SG_FEET_TO_METER) /
|
||||
tan(3.0 * SG_DEGREES_TO_RADIANS);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << aRunway->ident() << "-12";
|
||||
WayptVec wpts;
|
||||
SGGeod p = aRunway->pointOnCenterline(-12.0 * SG_NM_TO_METER);
|
||||
p.setElevationFt(thresholdElevFt + 4000);
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
|
||||
p = aRunway->pointOnCenterline(-8.0 * SG_NM_TO_METER);
|
||||
p.setElevationFt(thresholdElevFt + approachHeightFt);
|
||||
ss.str("");
|
||||
ss << aRunway->ident() << "-8";
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
p = aRunway->pointOnCenterline(-glideslopeDistanceM);
|
||||
p.setElevationFt(thresholdElevFt + approachHeightFt);
|
||||
|
||||
ss.str("");
|
||||
ss << aRunway->ident() << "-GS";
|
||||
wpts.push_back(new BasicWaypt(p, ss.str(), NULL));
|
||||
|
||||
wpts.push_back(new RunwayWaypt(aRunway, NULL));
|
||||
|
||||
BOOST_FOREACH(Waypt* w, wpts) {
|
||||
w->setFlag(WPT_APPROACH);
|
||||
w->setFlag(WPT_GENERATED);
|
||||
}
|
||||
|
||||
return Approach::createTempApproach("DEFAULT", aRunway, wpts);
|
||||
}
|
||||
|
||||
void FGRouteMgr::setApproach(const char* aIdent)
|
||||
{
|
||||
FGAirport* apt = _plan->destinationAirport();
|
||||
if (!strcmp(aIdent, "DEFAULT")) {
|
||||
_plan->setApproach(createDefaultApproach(_plan->destinationRunway()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!apt || (aIdent == NULL)) {
|
||||
_plan->setApproach(NULL);
|
||||
} else {
|
||||
|
|
|
@ -247,9 +247,9 @@ private:
|
|||
|
||||
FGAirportRef _departure, _destination;
|
||||
FGRunway* _departureRunway, *_destinationRunway;
|
||||
SID* _sid;
|
||||
STAR* _star;
|
||||
Approach* _approach;
|
||||
SGSharedPtr<SID> _sid;
|
||||
SGSharedPtr<STAR> _star;
|
||||
SGSharedPtr<Approach> _approach;
|
||||
std::string _sidTransition, _starTransition;
|
||||
|
||||
double _totalDistance;
|
||||
|
|
|
@ -36,7 +36,7 @@ struct SearchContext;
|
|||
class AdjacentWaypoint;
|
||||
class InAirwayFilter;
|
||||
|
||||
class Airway : public RouteBase
|
||||
class Airway
|
||||
{
|
||||
public:
|
||||
virtual std::string ident() const
|
||||
|
|
|
@ -49,6 +49,14 @@ Approach::Approach(const string& aIdent, ProcedureType ty) :
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
Approach* Approach::createTempApproach(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath)
|
||||
{
|
||||
Approach* app = new Approach(aIdent, PROCEDURE_APPROACH_RNAV);
|
||||
app->setRunway(aRunway);
|
||||
app->setPrimaryAndMissed(aPath, WayptVec());
|
||||
return app;
|
||||
}
|
||||
|
||||
void Approach::setRunway(FGRunwayRef aRwy)
|
||||
{
|
||||
|
@ -329,6 +337,19 @@ bool SID::route(FGRunwayRef aWay, Transition* trans, WayptVec& aPath)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
SID* SID::createTempSID(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath)
|
||||
{
|
||||
// flip waypoints since SID stores them reversed
|
||||
WayptVec path;
|
||||
std::back_insert_iterator<WayptVec> bi(path);
|
||||
std::reverse_copy(aPath.begin(), aPath.end(), bi);
|
||||
|
||||
SID* sid = new SID(aIdent, aRunway->airport());
|
||||
sid->setCommon(path);
|
||||
sid->addRunway(aRunway);
|
||||
return sid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -72,6 +72,8 @@ protected:
|
|||
class Transition : public Procedure
|
||||
{
|
||||
public:
|
||||
virtual ~Transition() { ; }
|
||||
|
||||
bool route(WayptVec& aPath);
|
||||
|
||||
Procedure* parent() const
|
||||
|
@ -106,6 +108,8 @@ private:
|
|||
WayptVec _primary;
|
||||
};
|
||||
|
||||
typedef SGSharedPtr<Transition> TransitionRef;
|
||||
|
||||
/**
|
||||
* Describe an approach procedure, including the missed approach
|
||||
* segment
|
||||
|
@ -113,6 +117,8 @@ private:
|
|||
class Approach : public Procedure
|
||||
{
|
||||
public:
|
||||
virtual ~Approach() { ; }
|
||||
|
||||
FGRunwayRef runway()
|
||||
{ return _runway; }
|
||||
|
||||
|
@ -143,6 +149,8 @@ public:
|
|||
|
||||
virtual ProcedureType type() const
|
||||
{ return _type; }
|
||||
|
||||
static Approach* createTempApproach(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath);
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
|
@ -155,7 +163,7 @@ private:
|
|||
FGRunwayRef _runway;
|
||||
ProcedureType _type;
|
||||
|
||||
typedef std::map<WayptRef, Transition*> WptTransitionMap;
|
||||
typedef std::map<WayptRef, TransitionRef> WptTransitionMap;
|
||||
WptTransitionMap _transitions;
|
||||
|
||||
WayptVec _primary; // unify these?
|
||||
|
@ -207,26 +215,26 @@ protected:
|
|||
|
||||
ArrivalDeparture(const std::string& aIdent, FGAirport* apt);
|
||||
|
||||
|
||||
void addRunway(FGRunwayRef aRwy);
|
||||
|
||||
typedef std::map<FGRunwayRef, Transition*> RunwayTransitionMap;
|
||||
typedef std::map<FGRunwayRef, TransitionRef> RunwayTransitionMap;
|
||||
RunwayTransitionMap _runways;
|
||||
|
||||
virtual WayptFlag flagType() const = 0;
|
||||
|
||||
void setCommon(const WayptVec& aWps);
|
||||
|
||||
private:
|
||||
friend class NavdataVisitor;
|
||||
|
||||
void addTransition(Transition* aTrans);
|
||||
|
||||
void setCommon(const WayptVec& aWps);
|
||||
|
||||
void addRunwayTransition(FGRunwayRef aRwy, Transition* aTrans);
|
||||
|
||||
FGAirport* _airport;
|
||||
WayptVec _common;
|
||||
|
||||
typedef std::map<WayptRef, Transition*> WptTransitionMap;
|
||||
typedef std::map<WayptRef, TransitionRef> WptTransitionMap;
|
||||
WptTransitionMap _enrouteTransitions;
|
||||
|
||||
|
||||
|
@ -234,12 +242,15 @@ private:
|
|||
|
||||
class SID : public ArrivalDeparture
|
||||
{
|
||||
public:
|
||||
public:
|
||||
virtual ~SID() { ; }
|
||||
|
||||
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
|
||||
|
||||
virtual ProcedureType type() const
|
||||
{ return PROCEDURE_SID; }
|
||||
|
||||
static SID* createTempSID(const std::string& aIdent, FGRunway* aRunway, const WayptVec& aPath);
|
||||
protected:
|
||||
virtual WayptFlag flagType() const
|
||||
{ return WPT_DEPARTURE; }
|
||||
|
@ -252,7 +263,9 @@ private:
|
|||
|
||||
class STAR : public ArrivalDeparture
|
||||
{
|
||||
public:
|
||||
public:
|
||||
virtual ~STAR() { ; }
|
||||
|
||||
virtual bool route(FGRunwayRef aWay, Transition* aTrans, WayptVec& aPath);
|
||||
|
||||
virtual ProcedureType type() const
|
||||
|
|
|
@ -219,7 +219,7 @@ private:
|
|||
|
||||
typedef std::vector<WayptRef> WayptVec;
|
||||
|
||||
class RouteBase
|
||||
class RouteBase : public SGReferenced
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue