using std::cerr;
+FGAIFlightPlan::FGAIFlightPlan()
+{
+ sid = 0;
+}
FGAIFlightPlan::FGAIFlightPlan(const string& filename)
{
int i;
+ sid = 0;
start_time = 0;
leg = 10;
gateId = 0;
const string& acType,
const string& airline)
{
+ sid = 0;
repeat = false;
leg = 10;
gateId=0;
string time;
} waypoint;
-
+ FGAIFlightPlan();
FGAIFlightPlan(const string& filename);
FGAIFlightPlan(FGAIAircraft *,
const std::string& p,
void setRunway(string rwy) { activeRunway = rwy; };
string getRunwayClassFromTrafficType(string fltType);
+ void addWaypoint(waypoint* wpt) { waypoints.push_back(wpt); };
+
+ void setName(string n) { name = n; };
+ string getName() { return name; };
+
+ void setSID(FGAIFlightPlan* fp) { sid = fp;};
+ FGAIFlightPlan* getSID() { return sid; };
+
private:
FGRunway* rwy;
+ FGAIFlightPlan *sid;
typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::const_iterator wpt_vector_iterator;
string activeRunway;
FGAirRoute airRoute;
FGTaxiRoute *taxiRoute;
+ string name;
void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
waypoint* cloneWithPos(FGAIAircraft *, waypoint* aWpt, const std::string& aName, const SGGeod& aPos);
+ waypoint* clone(waypoint* aWpt);
//void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
void evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon);
+ public:
+ wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
+ wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };
- bool loadSID(const string& filename);
- string expandICAODirs(const string in);
};
#endif // _FG_AIFLIGHTPLAN_HXX
return wpt;
}
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::clone(waypoint* aWpt)
+{
+ waypoint* wpt = new waypoint;
+ wpt->name = aWpt->name;
+ wpt->longitude = aWpt->longitude;
+ wpt->latitude = aWpt->latitude;
+
+ wpt->altitude = aWpt->altitude;
+ wpt->speed = aWpt->speed;
+ wpt->crossat = aWpt->crossat;
+ wpt->gear_down = aWpt->gear_down;
+ wpt->flaps_down= aWpt->flaps_down;
+ wpt->finished = aWpt->finished;
+ wpt->on_ground = aWpt->on_ground;
+ wpt->routeIndex = 0;
+
+ return wpt;
+}
+
+
void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway)
{
SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
rwy = apt->getRunwayByIdent(activeRunway);
}
- if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == true) {
- string_list sc = globals->get_fg_scenery();
- char buffer[64];
- // NOTE: Currently for testing only. A slightly more elaborate naming convention
- // needs to be dropped here.
- snprintf(buffer, 64, "%s.SID-%s-01.xml", apt->getId().c_str(), activeRunway.c_str() );
- string airportDir = expandICAODirs(apt->getId());
- for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
- SGPath aptpath( *i );
- aptpath.append( "Airports" );
- aptpath.append ( airportDir );
- aptpath.append( string(buffer) );
- if (aptpath.exists()) {
- planLoaded = loadSID(aptpath.str());
- //cerr << "Reading " << aptpath.str() << endl;
- }
- }
- }
- if (!planLoaded) {
+ if (sid) {
+ for (wpt_vector_iterator i = sid->getFirstWayPoint();
+ i != sid->getLastWayPoint();
+ i++) {
+ waypoints.push_back(clone(*(i)));
+ //cerr << " Cloning waypoint " << endl;
+ }
+ } else {
SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
wpt = createInAir(ac, "10000ft climb", climb1, speed, 10000);
wpt->gear_down = true;
}
}
-bool FGAIFlightPlan::loadSID(const string& filename)
-{
- SGPropertyNode root;
- try {
- readProperties(filename, &root);
- } catch (const sg_exception &e) {
- SG_LOG(SG_GENERAL, SG_ALERT,
- "Error reading AI flight plan: " << filename);
- // cout << path.str() << endl;
- return false;
- }
-
- SGPropertyNode * node = root.getNode("flightplan");
- for (int i = 0; i < node->nChildren(); i++) {
- //cout << "Reading waypoint " << i << endl;
- waypoint* wpt = new waypoint;
- SGPropertyNode * wpt_node = node->getChild(i);
- wpt->name = wpt_node->getStringValue("name", "END");
- wpt->latitude = wpt_node->getDoubleValue("lat", 0);
- wpt->longitude = wpt_node->getDoubleValue("lon", 0);
- wpt->altitude = wpt_node->getDoubleValue("alt", 0);
- wpt->speed = wpt_node->getDoubleValue("ktas", 0);
- wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
- wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
- wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
- wpt->on_ground = wpt_node->getBoolValue("on-ground", false);
- wpt->time_sec = wpt_node->getDoubleValue("time-sec", 0);
- wpt->time = wpt_node->getStringValue("time", "");
-
- if (wpt->name == "END") wpt->finished = true;
- else wpt->finished = false;
-
- waypoints.push_back( wpt );
- }
-
- //wpt_iterator = waypoints.begin();
- //cout << waypoints.size() << " waypoints read." << endl;
- return true;
-}
-
-// NOTE: This is just copied from Airports/readXML.
-string FGAIFlightPlan::expandICAODirs(const string in){
- //cerr << "Expanding " << in << endl;
- if (in.size() == 4) {
- char buffer[11];
- snprintf(buffer, 11, "%c/%c/%c", in[0], in[1], in[2]);
- //cerr << "result: " << buffer << endl;
- return string(buffer);
- } else {
- return in;
- }
- //exit(1);
-}
/*******************************************************************
string activeRunway;
string fltType;
string rwyClass;
+ string SID;
+ FGAIFlightPlan *fp;
switch (msgId) {
case MSG_ANNOUNCE_ENGINE_START:
text = sender + ". Ready to Start up";
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
+ fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getSID(activeRunway, heading);
+ rec->getAircraft()->GetFlightPlan()->setSID(fp);
+ if (fp) {
+ SID = fp->getName() + " departure";
+ } else {
+ SID = "fly runway heading ";
+ }
//snprintf(buffer, 7, "%3.2f", heading);
text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " + activeRunway
- + ", AAA departure, squawk BBBB. " +
+ + ", " + SID + ", squawk BBBB. " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + sender + " control.";
break;
case MSG_DENY_ENGINE_START:
text = receiver + ". Standby";
break;
case MSG_ACKNOWLEDGE_ENGINE_START:
+ fp = rec->getAircraft()->GetFlightPlan()->getSID();
+ if (fp) {
+ SID = rec->getAircraft()->GetFlightPlan()->getSID()->getName() + " departure";
+ } else {
+ SID = "fly runway heading ";
+ }
taxiFreqStr = formatATCFrequency3_2(taxiFreq);
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " +
- activeRunway + ", AAA departure, squawk BBBB. " +
+ activeRunway + ", " + SID + ", squawk BBBB. " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + sender;
break;
default:
groundnetwork.cxx groundnetwork.hxx \
dynamics.cxx dynamics.hxx \
dynamicloader.cxx dynamicloader.hxx \
+ sidstar.cxx sidstar.hxx \
runwayprefloader.cxx runwayprefloader.hxx \
xmlloader.cxx xmlloader.hxx \
runwaybase.cxx runwaybase.hxx
#include "dynamics.hxx"
FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
- _ap(ap), rwyPrefs(ap) {
+ _ap(ap), rwyPrefs(ap), SIDs(ap) {
lastUpdate = 0;
// For testing only. This needs to be refined when we move ATIS functionality over.
// Note that the ground network should also be copied
FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
- rwyPrefs(other.rwyPrefs)
+ rwyPrefs(other.rwyPrefs),
+ SIDs(other.SIDs)
{
for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
parkings.push_back(*(ip));
groundFreq = freqGround[leg-2];
}
return groundFreq;
+}
+
+FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, double heading)
+{
+ return SIDs.getBest(activeRunway, heading);
}
\ No newline at end of file
#include "parking.hxx"
#include "groundnetwork.hxx"
#include "runwayprefs.hxx"
+#include "sidstar.hxx"
//typedef vector<float> DoubleVec;
//typedef vector<float>::iterator DoubleVecIterator;
FGParkingVec parkings;
FGRunwayPreference rwyPrefs;
+ FGSidStar SIDs;
FGStartupController startupController;
FGGroundNetwork groundNetwork;
FGTowerController towerController;
//const string &getName() const { return _name;};
// Returns degrees
+ // Departure / Arrival procedures
+ FGSidStar * getSIDs() { return &SIDs; };
+ FGAIFlightPlan * getSID(string activeRunway, double heading);
+
// ATC related functions.
FGStartupController *getStartupController() { return &startupController; };
--- /dev/null
+// sidstar.cxx - Code to manage departure / arrival procedures
+// Written by Durk Talsma, started March 2009.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id$
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+
+
+
+#include <Airports/simple.hxx>
+
+
+#include "sidstar.hxx"
+
+using std::cerr;
+using std::endl;
+
+FGSidStar::FGSidStar(FGAirport *ap) {
+ id = ap->getId();
+ initialized = false;
+}
+
+
+FGSidStar::FGSidStar(const FGSidStar &other) {
+ cerr << "TODO" << endl;
+ exit(1);
+}
+
+void FGSidStar::load(SGPath filename) {
+ SGPropertyNode root;
+ string runway;
+ string name;
+ try {
+ readProperties(filename.str(), &root);
+ } catch (const sg_exception &e) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Error reading AI flight plan: " << filename.str());
+ // cout << path.str() << endl;
+ return;
+ }
+
+ SGPropertyNode * node = root.getNode("SIDS");
+ FGAIFlightPlan *fp;
+ for (int i = 0; i < node->nChildren(); i++) {
+ fp = new FGAIFlightPlan;
+ SGPropertyNode * fpl_node = node->getChild(i);
+ name = fpl_node->getStringValue("name", "END");
+ runway = fpl_node->getStringValue("runway", "27");
+ //cerr << "Runway = " << runway << endl;
+ fp->setName(name);
+ SGPropertyNode * wpts_node = fpl_node->getNode("wpts");
+ for (int j = 0; j < wpts_node->nChildren(); j++) {
+ FGAIFlightPlan::waypoint* wpt = new FGAIFlightPlan::waypoint;
+ SGPropertyNode * wpt_node = wpts_node->getChild(j);
+ //cerr << "Reading waypoint " << j << wpt_node->getStringValue("name", "END") << endl;
+ wpt->name = wpt_node->getStringValue("name", "END");
+ wpt->latitude = wpt_node->getDoubleValue("lat", 0);
+ wpt->longitude = wpt_node->getDoubleValue("lon", 0);
+ wpt->altitude = wpt_node->getDoubleValue("alt", 0);
+ wpt->speed = wpt_node->getDoubleValue("ktas", 0);
+ wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
+ wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
+ wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
+ wpt->on_ground = wpt_node->getBoolValue("on-ground", false);
+ wpt->time_sec = wpt_node->getDoubleValue("time-sec", 0);
+ wpt->time = wpt_node->getStringValue("time", "");
+
+ if (wpt->name == "END") wpt->finished = true;
+ else wpt->finished = false;
+
+ //
+ fp->addWaypoint( wpt );
+ }
+ data[runway].push_back(fp);
+ //cerr << "Runway = " << runway << endl;
+ }
+
+
+ //wpt_iterator = waypoints.begin();
+ //cout << waypoints.size() << " waypoints read." << endl;
+}
+
+
+FGAIFlightPlan *FGSidStar::getBest(string activeRunway, double heading)
+{
+ //cerr << "Getting best procedure for " << activeRunway << endl;
+ for (FlightPlanVecIterator i = data[activeRunway].begin(); i != data[activeRunway].end(); i++) {
+ //cerr << (*i)->getName() << endl;
+ }
+ int size = data[activeRunway].size();
+ //cerr << "size is " << size << endl;
+ if (size) {
+ return data[activeRunway][(rand() % size)];
+ } else {
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+// sidstar.hxx - a class to store and maintain data for SID and STAR
+// procedures.
+// Written by Durk Talsma, started March 2009.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id$
+
+
+#ifndef _SIDSTAR_HXX_
+#define _SIDSTAR_HXX_
+
+#include <string>
+
+#include <simgear/misc/sg_path.hxx>
+
+#include <simgear/xml/easyxml.hxx>
+
+#include <ATC/trafficcontrol.hxx>
+#include <AIModel/AIFlightPlan.hxx>
+#include "parking.hxx"
+#include "groundnetwork.hxx"
+#include "runwayprefs.hxx"
+
+
+using std::string;
+
+class FGAirport;
+
+typedef vector<FGAIFlightPlan*> FlightPlanVec;
+typedef vector<FGAIFlightPlan*>::iterator FlightPlanVecIterator;
+
+typedef std::map < std::string, FlightPlanVec > FlightPlanVecMap;
+
+
+class FGSidStar
+{
+ private:
+ string id;
+ bool initialized;
+ FlightPlanVecMap data;
+
+ public:
+ FGSidStar(FGAirport *ap);
+ FGSidStar(const FGSidStar &other);
+
+ string getId() { return id; };
+ void load(SGPath path);
+ FGAIFlightPlan *getBest(string activeRunway, double heading);
+};
+
+
+
+#endif
\ No newline at end of file
FGRunwayPreference rwyPrefs(this);
XMLLoader::load(&rwyPrefs);
_dynamics->setRwyUse(rwyPrefs);
+
+ //FGSidStar SIDs(this);
+ XMLLoader::load(_dynamics->getSIDs());
}
return _dynamics;
}
}
}
+void XMLLoader::load(FGSidStar* p) {
+ //FGRunwayPreferenceXMLLoader visitor(p);
+ if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == true) {
+ string_list sc = globals->get_fg_scenery();
+ char buffer[32];
+ snprintf(buffer, 32, "%s.SID.xml", p->getId().c_str() );
+ string airportDir = expandICAODirs(p->getId());
+ for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
+ SGPath sidpath( *i );
+ sidpath.append( "Airports" );
+ sidpath.append ( airportDir );
+ sidpath.append( string(buffer) );
+ if (sidpath.exists()) {
+ try {
+ //readXML(rwypath.str(), visitor);
+ //cerr << "Reading SID procedure : " << sidpath.str() << endl;
+ p->load(sidpath);
+ }
+ catch (const sg_exception &e) {
+ }
+ return;
+ }
+ }
+ }
+}
class FGAirportDynamics;
class FGRunwayPreference;
+class FGSidStar;
~XMLLoader();
static string expandICAODirs(const string in);
static void load(FGRunwayPreference* p);
- static void load(FGAirportDynamics* d);
+ static void load(FGAirportDynamics* d);
+ static void load(FGSidStar* s);
};