1
0
Fork 0

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:
James Turner 2012-11-12 22:30:28 +01:00
parent 25138930e3
commit 78d97fa468
7 changed files with 142 additions and 16 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -36,7 +36,7 @@ struct SearchContext;
class AdjacentWaypoint;
class InAirwayFilter;
class Airway : public RouteBase
class Airway
{
public:
virtual std::string ident() const

View file

@ -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;
}
////////////////////////////////////////////////////////////////////////////

View file

@ -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

View file

@ -219,7 +219,7 @@ private:
typedef std::vector<WayptRef> WayptVec;
class RouteBase
class RouteBase : public SGReferenced
{
public:
/**