Clean up dynamics/parking handing code.
Refactor some parking / airport-dynamics APIs, in preparation for caching the ground cache data in the nav-cache.
This commit is contained in:
parent
01be5529ba
commit
b1854459b3
12 changed files with 273 additions and 455 deletions
|
@ -129,7 +129,7 @@ public:
|
|||
|
||||
bool create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
|
||||
bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
|
||||
bool createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
|
||||
bool createPushBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&);
|
||||
bool createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
|
||||
|
||||
void setLeg(int val) { leg = val;}
|
||||
|
@ -189,7 +189,7 @@ private:
|
|||
std::string name;
|
||||
bool isValid;
|
||||
|
||||
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
|
||||
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&);
|
||||
bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
|
||||
bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
|
||||
bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
|
||||
|
|
|
@ -62,7 +62,7 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
|||
int currWpt = wpt_iterator - waypoints.begin();
|
||||
switch (legNr) {
|
||||
case 1:
|
||||
retVal = createPushBack(ac, firstFlight, dep, latitude, longitude,
|
||||
retVal = createPushBack(ac, firstFlight, dep,
|
||||
radius, fltType, aircraftType, airline);
|
||||
// Pregenerate the taxi leg.
|
||||
//if (retVal) {
|
||||
|
@ -206,22 +206,21 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
const string & acType,
|
||||
const string & airline)
|
||||
{
|
||||
double heading, lat, lon;
|
||||
|
||||
// If this function is called during initialization,
|
||||
// make sure we obtain a valid gate ID first
|
||||
// and place the model at the location of the gate.
|
||||
if (firstFlight) {
|
||||
if (!(apt->getDynamics()->getAvailableParking(&lat, &lon,
|
||||
&heading, &gateId,
|
||||
radius, fltType,
|
||||
acType, airline))) {
|
||||
SG_LOG(SG_AI, SG_WARN, "Could not find parking for a " <<
|
||||
acType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << apt->getId());
|
||||
}
|
||||
if (firstFlight)
|
||||
{
|
||||
gateId = apt->getDynamics()->getAvailableParking(radius, fltType,
|
||||
acType, airline);
|
||||
if (gateId < 0) {
|
||||
SG_LOG(SG_AI, SG_WARN, "Could not find parking for a " <<
|
||||
acType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << apt->getId());
|
||||
}
|
||||
}
|
||||
|
||||
string rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||
|
@ -355,11 +354,9 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
|
|||
ac->getPerformance()->vTaxi());
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
double heading, lat, lon;
|
||||
aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
wpt =
|
||||
createOnGround(ac, "ENDtaxi", SGGeod::fromDeg(lon, lat), airportElev,
|
||||
ac->getPerformance()->vTaxi());
|
||||
FGParking* parkPos = aAirport->getDynamics()->getParking(gateId);
|
||||
wpt = createOnGround(ac, "ENDtaxi", parkPos->getGeod(), airportElev,
|
||||
ac->getPerformance()->vTaxi());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
|
||||
|
@ -369,9 +366,7 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
|
|||
const string & acType,
|
||||
const string & airline)
|
||||
{
|
||||
double heading, lat, lon;
|
||||
apt->getDynamics()->getAvailableParking(&lat, &lon, &heading,
|
||||
&gateId, radius, fltType,
|
||||
gateId = apt->getDynamics()->getAvailableParking(radius, fltType,
|
||||
acType, airline);
|
||||
|
||||
SGGeod lastWptPos =
|
||||
|
@ -1012,34 +1007,25 @@ bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
|
|||
{
|
||||
FGAIWaypoint *wpt;
|
||||
double aptElev = apt->getElevation();
|
||||
double lat = 0.0, lat2 = 0.0;
|
||||
double lon = 0.0, lon2 = 0.0;
|
||||
double az2 = 0.0;
|
||||
double heading = 0.0;
|
||||
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vTaxiReduced = vTaxi * (2.0 / 3.0);
|
||||
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
geo_direct_wgs_84(0, lat, lon, heading,
|
||||
2.2 * radius, &lat2, &lon2, &az2);
|
||||
wpt =
|
||||
createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2),
|
||||
aptElev, vTaxiReduced);
|
||||
FGParking* parking = apt->getDynamics()->getParking(gateId);
|
||||
double heading = SGMiscd::normalizePeriodic(0, 360, parking->getHeading() + 180.0);
|
||||
double az; // unused
|
||||
SGGeod pos;
|
||||
|
||||
SGGeodesy::direct(parking->getGeod(), heading, 2.2 * parking->getRadius(),
|
||||
pos, az);
|
||||
|
||||
wpt = createOnGround(ac, "taxiStart", pos, aptElev, vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
geo_direct_wgs_84(0, lat, lon, heading,
|
||||
0.1 * radius, &lat2, &lon2, &az2);
|
||||
|
||||
wpt =
|
||||
createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2),
|
||||
aptElev, vTaxiReduced);
|
||||
SGGeodesy::direct(parking->getGeod(), heading, 0.1 * parking->getRadius(),
|
||||
pos, az);
|
||||
wpt = createOnGround(ac, "taxiStart2", pos, aptElev, vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
wpt =
|
||||
createOnGround(ac, "END-Parking", SGGeod::fromDeg(lon, lat), aptElev,
|
||||
wpt = createOnGround(ac, "END-Parking", parking->getGeod(), aptElev,
|
||||
vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
return true;
|
||||
|
|
|
@ -41,14 +41,11 @@
|
|||
// TODO: Use James Turner's createOnGround functions.
|
||||
bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
||||
bool firstFlight, FGAirport *dep,
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
{
|
||||
double lat, lon, heading;
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vTaxiBackward = vTaxi * (-2.0/3.0);
|
||||
double vTaxiReduced = vTaxi * (2.0/3.0);
|
||||
|
@ -59,132 +56,111 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
|
||||
if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
|
||||
//cerr << "Push Back fallback" << endl;
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
createPushBackFallBack(ac, firstFlight, dep,
|
||||
radius, fltType, aircraftType, airline);
|
||||
return true;
|
||||
}
|
||||
|
||||
// establish the parking position / gate if required
|
||||
if (firstFlight) {
|
||||
gateId = dep->getDynamics()->getAvailableParking(radius, fltType,
|
||||
aircraftType, airline);
|
||||
if (gateId < 0) {
|
||||
SG_LOG(SG_AI, SG_WARN, "Warning: Could not find parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (firstFlight) {
|
||||
dep->getDynamics()->getParking(gateId);
|
||||
}
|
||||
|
||||
if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
|
||||
&heading, &gateId,
|
||||
radius, fltType,
|
||||
aircraftType, airline))) {
|
||||
SG_LOG(SG_AI, SG_WARN, "Warning: Could not find parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
return false;
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", gateId);
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
wpt->setRouteIndex(-1);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
//cerr << "Success : GateId = " << gateId << endl;
|
||||
SG_LOG(SG_AI, SG_WARN, "Warning: Successfully found a parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
} else {
|
||||
//cerr << "Push Back follow-up Flight" << endl;
|
||||
dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
}
|
||||
if (gateId < 0) {
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
radius, fltType, aircraftType, airline);
|
||||
return true;
|
||||
if (gateId < 0) {
|
||||
createPushBackFallBack(ac, firstFlight, dep,
|
||||
radius, fltType, aircraftType, airline);
|
||||
return true;
|
||||
|
||||
}
|
||||
//cerr << "getting parking " << gateId;
|
||||
//cerr << " for a " <<
|
||||
// aircraftType <<
|
||||
// " of flight type " << fltType <<
|
||||
// " of airline " << airline <<
|
||||
// " at airport " << dep->getId() << endl;
|
||||
FGParking *parking = dep->getDynamics()->getParking(gateId);
|
||||
int pushBackNode = parking->getPushBackPoint();
|
||||
}
|
||||
|
||||
FGParking *parking = dep->getDynamics()->getParking(gateId);
|
||||
int pushBackNode = parking->getPushBackPoint();
|
||||
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
|
||||
int node, rte;
|
||||
FGTaxiRoute route;
|
||||
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
|
||||
route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
|
||||
parking->setPushBackRoute(new FGTaxiRoute(route));
|
||||
|
||||
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
|
||||
int node, rte;
|
||||
FGTaxiRoute route;
|
||||
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
|
||||
route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
|
||||
parking->setPushBackRoute(new FGTaxiRoute(route));
|
||||
|
||||
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
int size = pushBackRoute->size();
|
||||
if (size < 2) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Push back route from gate " << gateId << " has only " << size << " nodes.");
|
||||
SG_LOG(SG_AI, SG_ALERT, "Using " << pushBackNode);
|
||||
}
|
||||
pushBackRoute->first();
|
||||
while (pushBackRoute->next(&node, &rte))
|
||||
{
|
||||
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", node);
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
//wpt = new waypoint;
|
||||
SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude());
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
|
||||
wpt->setRouteIndex(rte);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// some special considerations for the last point:
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
waypoints.back()->setSpeed(vTaxi);
|
||||
ac->setTaxiClearanceRequest(true);
|
||||
} else { // In case of a push forward departure...
|
||||
ac->setTaxiClearanceRequest(false);
|
||||
double lat2 = 0.0, lon2 = 0.0, az2 = 0.0;
|
||||
|
||||
//cerr << "Creating final push forward point for gate " << gateId << endl;
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
|
||||
FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
|
||||
FGTaxiSegmentVectorIterator te = tn->getEndRoute();
|
||||
// if the starting node equals the ending node, then there aren't any routes for this parking.
|
||||
// in cases like these we should flag the gate as being inoperative and return false
|
||||
if (ts == te) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
|
||||
parking->setAvailable(false);
|
||||
return false;
|
||||
}
|
||||
tn = (*ts)->getEnd();
|
||||
lastNodeVisited = tn->getIndex();
|
||||
if (tn == NULL) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found");
|
||||
exit(1);
|
||||
}
|
||||
double distance = (*ts)->getLength();
|
||||
//cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl;
|
||||
lat2 = tn->getLatitude();
|
||||
lon2 = tn->getLongitude();
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
((i / 10.0) * distance), &lat2, &lon2, &az2 );
|
||||
char buffer[16];
|
||||
snprintf(buffer, 16, "pushback-%02d", i);
|
||||
SGGeod coord = coord.fromDeg(lon2, lat2);
|
||||
//cerr << i << endl;
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiReduced);
|
||||
|
||||
wpt->setRouteIndex((*ts)->getIndex());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// cerr << "Done " << endl;
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
// cerr << "Done assinging new name" << endl;
|
||||
int size = pushBackRoute->size();
|
||||
if (size < 2) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Push back route from gate " << gateId << " has only " << size << " nodes.");
|
||||
SG_LOG(SG_AI, SG_ALERT, "Using " << pushBackNode);
|
||||
}
|
||||
pushBackRoute->first();
|
||||
while (pushBackRoute->next(&node, &rte))
|
||||
{
|
||||
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", node);
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
//wpt = new waypoint;
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->getGeod(), dep->getElevation(), vTaxiBackward);
|
||||
|
||||
wpt->setRouteIndex(rte);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// some special considerations for the last point:
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
waypoints.back()->setSpeed(vTaxi);
|
||||
ac->setTaxiClearanceRequest(true);
|
||||
} else { // In case of a push forward departure...
|
||||
ac->setTaxiClearanceRequest(false);
|
||||
double az2 = 0.0;
|
||||
|
||||
//cerr << "Creating final push forward point for gate " << gateId << endl;
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
|
||||
FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
|
||||
FGTaxiSegmentVectorIterator te = tn->getEndRoute();
|
||||
// if the starting node equals the ending node, then there aren't any routes for this parking.
|
||||
// in cases like these we should flag the gate as being inoperative and return false
|
||||
if (ts == te) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
|
||||
parking->setAvailable(false);
|
||||
return false;
|
||||
}
|
||||
tn = (*ts)->getEnd();
|
||||
lastNodeVisited = tn->getIndex();
|
||||
if (tn == NULL) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found");
|
||||
exit(1);
|
||||
}
|
||||
double distance = (*ts)->getLength();
|
||||
|
||||
double parkingHeading = parking->getHeading();
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
SGGeod pushForwardPt;
|
||||
SGGeodesy::direct(parking->getGeod(), parkingHeading,
|
||||
((i / 10.0) * distance), pushForwardPt, az2);
|
||||
char buffer[16];
|
||||
snprintf(buffer, 16, "pushback-%02d", i);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), pushForwardPt, dep->getElevation(), vTaxiReduced);
|
||||
|
||||
wpt->setRouteIndex((*ts)->getIndex());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// cerr << "Done " << endl;
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
// cerr << "Done assinging new name" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************
|
||||
|
@ -193,49 +169,29 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
* network yet.
|
||||
******************************************************************/
|
||||
void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
{
|
||||
double heading;
|
||||
double lat;
|
||||
double lon;
|
||||
double lat2 = 0.0;
|
||||
double lon2 = 0.0;
|
||||
double az2 = 0.0;
|
||||
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vTaxiBackward = vTaxi * (-2.0/3.0);
|
||||
double vTaxiReduced = vTaxi * (2.0/3.0);
|
||||
|
||||
|
||||
|
||||
dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
|
||||
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward);
|
||||
double heading = 180.0; // this is a completely arbitrary heading!
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string("park"), dep->geod(), dep->getElevation(), vTaxiBackward);
|
||||
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
10,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
SGGeod coord;
|
||||
SGGeodesy::direct(dep->geod(), heading, 10, coord, az2);
|
||||
wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
|
||||
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
2.2*radius,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
SGGeodesy::direct(dep->geod(), heading, 2.2 * radius, coord, az2);
|
||||
wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
|
|
|
@ -143,8 +143,6 @@ void FGATCManager::init() {
|
|||
if (!(fp->createPushBack(&ai_ac,
|
||||
false,
|
||||
apt,
|
||||
latitude,
|
||||
longitude,
|
||||
aircraftRadius,
|
||||
fltType,
|
||||
aircraftType,
|
||||
|
|
|
@ -589,8 +589,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
|
||||
heading);
|
||||
rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
|
||||
fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
|
||||
getDynamics()->getSID(activeRunway, heading);
|
||||
fp = NULL;
|
||||
rec->getAircraft()->GetFlightPlan()->setSID(fp);
|
||||
if (fp) {
|
||||
SID = fp->getName() + " departure";
|
||||
|
@ -737,11 +736,8 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
SGGeod sender_pos;
|
||||
double sender_alt_ft, sender_alt;
|
||||
if(ground_to_air) {
|
||||
sender_alt_ft = parent->getElevation();
|
||||
sender_alt = sender_alt_ft * SG_FEET_TO_METER;
|
||||
sender_pos= SGGeod::fromDegM( parent->getLongitude(),
|
||||
parent->getLatitude(), sender_alt );
|
||||
}
|
||||
sender_pos = parent->parent()->geod();
|
||||
}
|
||||
else {
|
||||
sender_alt_ft = rec->getAltitude();
|
||||
sender_alt = sender_alt_ft * SG_FEET_TO_METER;
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
|
@ -37,20 +41,17 @@
|
|||
#include <Airports/runways.hxx>
|
||||
#include <ATCDCL/ATCutils.hxx>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "simple.hxx"
|
||||
#include "dynamics.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::sort;
|
||||
using std::random_shuffle;
|
||||
|
||||
#include "simple.hxx"
|
||||
#include "dynamics.hxx"
|
||||
|
||||
FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
|
||||
_ap(ap), rwyPrefs(ap), SIDs(ap),
|
||||
startupController (this),
|
||||
_ap(ap), rwyPrefs(ap),
|
||||
startupController (this),
|
||||
towerController (this),
|
||||
approachController (this),
|
||||
atisSequenceIndex(-1),
|
||||
|
@ -85,159 +86,67 @@ void FGAirportDynamics::init()
|
|||
|
||||
}
|
||||
|
||||
bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
|
||||
double *heading, int *gateId,
|
||||
double rad,
|
||||
const string & flType,
|
||||
int FGAirportDynamics::innerGetAvailableParking(double radius, const string & flType,
|
||||
const string & acType,
|
||||
const string & airline,
|
||||
bool skipEmptyAirlineCode)
|
||||
{
|
||||
FGParkingVecIterator i;
|
||||
for (i = parkings.begin(); i != parkings.end(); i++) {
|
||||
// Taken by another aircraft, or no airline codes
|
||||
if (!i->isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skipEmptyAirlineCode && i->getCodes().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check airline codes match
|
||||
if (!airline.empty() && !i->getCodes().empty()) {
|
||||
if (i->getCodes().find(airline, 0) == string::npos) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Type doesn't match
|
||||
if (i->getType() != flType) {
|
||||
continue;
|
||||
}
|
||||
// too small
|
||||
if (i->getRadius() < radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i->setAvailable(false);
|
||||
return i->getIndex();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FGAirportDynamics::getAvailableParking(double radius, const string & flType,
|
||||
const string & acType,
|
||||
const string & airline)
|
||||
{
|
||||
bool found = false;
|
||||
bool available = false;
|
||||
|
||||
|
||||
FGParkingVecIterator i;
|
||||
if (parkings.begin() == parkings.end()) {
|
||||
//cerr << "Could not find parking spot at " << _ap->getId() << endl;
|
||||
*lat = _ap->getLatitude();
|
||||
*lon = _ap->getLongitude();
|
||||
* gateId = -1;
|
||||
*heading = 0;
|
||||
found = true;
|
||||
} else {
|
||||
// First try finding a parking with a designated airline code
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
|
||||
available = true;
|
||||
// Taken by another aircraft
|
||||
if (!(i->isAvailable())) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
// No airline codes, so skip
|
||||
if (i->getCodes().empty()) {
|
||||
available = false;
|
||||
continue;
|
||||
} else { // Airline code doesn't match
|
||||
//cerr << "Code = " << airline << ": Codes " << i->getCodes();
|
||||
if (i->getCodes().find(airline, 0) == string::npos) {
|
||||
available = false;
|
||||
//cerr << "Unavailable" << endl;
|
||||
continue;
|
||||
} else {
|
||||
//cerr << "Available" << endl;
|
||||
}
|
||||
}
|
||||
// Type doesn't match
|
||||
if (i->getType() != flType) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
// too small
|
||||
if (i->getRadius() < rad) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available) {
|
||||
*lat = i->getLatitude();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading();
|
||||
*gateId = i->getIndex();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// then try again for those without codes.
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
|
||||
available = true;
|
||||
if (!(i->isAvailable())) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
if (!(i->getCodes().empty())) {
|
||||
if ((i->getCodes().find(airline, 0) == string::npos)) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i->getType() != flType) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->getRadius() < rad) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available) {
|
||||
*lat = i->getLatitude();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading();
|
||||
*gateId = i->getIndex();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// And finally once more if that didn't work. Now ignore the airline codes, as a last resort
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
|
||||
available = true;
|
||||
if (!(i->isAvailable())) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
if (i->getType() != flType) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->getRadius() < rad) {
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available) {
|
||||
*lat = i->getLatitude();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading();
|
||||
*gateId = i->getIndex();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (parkings.empty()) {
|
||||
return -1;
|
||||
}
|
||||
if (!found) {
|
||||
//cerr << "Traffic overflow at" << _ap->getId()
|
||||
// << ". flType = " << flType
|
||||
// << ". airline = " << airline
|
||||
// << " Radius = " <<rad
|
||||
// << endl;
|
||||
*lat = _ap->getLatitude();
|
||||
*lon = _ap->getLongitude();
|
||||
*heading = 0;
|
||||
*gateId = -1;
|
||||
//exit(1);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::getParking(int id, double *lat, double *lon,
|
||||
double *heading)
|
||||
{
|
||||
if (id < 0) {
|
||||
*lat = _ap->getLatitude();
|
||||
*lon = _ap->getLongitude();
|
||||
*heading = 0;
|
||||
} else {
|
||||
FGParkingVecIterator i = parkings.begin();
|
||||
for (i = parkings.begin(); i != parkings.end(); i++) {
|
||||
if (id == i->getIndex()) {
|
||||
*lat = i->getLatitude();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading();
|
||||
}
|
||||
}
|
||||
}
|
||||
// most exact seach - airline codes must be present and match
|
||||
int result = innerGetAvailableParking(radius, flType, acType, airline, true);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// more tolerant - gates with empty airline codes are permitted
|
||||
result = innerGetAvailableParking(radius, flType, acType, airline, false);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// fallback - ignore the airline code entirely
|
||||
return innerGetAvailableParking(radius, flType, acType, string(), false);
|
||||
}
|
||||
|
||||
FGParking *FGAirportDynamics::getParking(int id)
|
||||
|
@ -263,6 +172,18 @@ string FGAirportDynamics::getParkingName(int id)
|
|||
return string("overflow");
|
||||
}
|
||||
|
||||
int FGAirportDynamics::findParkingByName(const std::string& name) const
|
||||
{
|
||||
FGParkingVec::const_iterator i = parkings.begin();
|
||||
for (i = parkings.begin(); i != parkings.end(); i++) {
|
||||
if (i->getName() == name) {
|
||||
return i->getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::releaseParking(int id)
|
||||
{
|
||||
if (id >= 0) {
|
||||
|
@ -279,8 +200,6 @@ void FGAirportDynamics::releaseParking(int id)
|
|||
void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref)
|
||||
{
|
||||
rwyPrefs = ref;
|
||||
//cerr << "Exiting due to not implemented yet" << endl;
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
|
||||
|
@ -466,22 +385,12 @@ void FGAirportDynamics::addParking(FGParking & park)
|
|||
parkings.push_back(park);
|
||||
}
|
||||
|
||||
double FGAirportDynamics::getLatitude() const
|
||||
{
|
||||
return _ap->getLatitude();
|
||||
}
|
||||
|
||||
double FGAirportDynamics::getLongitude() const
|
||||
{
|
||||
return _ap->getLongitude();
|
||||
}
|
||||
|
||||
double FGAirportDynamics::getElevation() const
|
||||
{
|
||||
return _ap->getElevation();
|
||||
}
|
||||
|
||||
const string & FGAirportDynamics::getId() const
|
||||
const string FGAirportDynamics::getId() const
|
||||
{
|
||||
return _ap->getId();
|
||||
}
|
||||
|
@ -543,13 +452,6 @@ int FGAirportDynamics::getTowerFrequency(unsigned nr)
|
|||
return towerFreq;
|
||||
}
|
||||
|
||||
|
||||
FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway,
|
||||
double heading)
|
||||
{
|
||||
return SIDs.getBest(activeRunway, heading);
|
||||
}
|
||||
|
||||
const std::string FGAirportDynamics::getAtisSequence()
|
||||
{
|
||||
if (atisSequenceIndex == -1) {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "parking.hxx"
|
||||
#include "groundnetwork.hxx"
|
||||
#include "runwayprefs.hxx"
|
||||
#include "sidstar.hxx"
|
||||
|
||||
// forward decls
|
||||
class FGAirport;
|
||||
|
@ -39,7 +38,6 @@ private:
|
|||
|
||||
FGParkingVec parkings;
|
||||
FGRunwayPreference rwyPrefs;
|
||||
FGSidStar SIDs;
|
||||
FGStartupController startupController;
|
||||
FGGroundNetwork groundNetwork;
|
||||
FGTowerController towerController;
|
||||
|
@ -65,8 +63,9 @@ private:
|
|||
bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading);
|
||||
std::string chooseRwyByHeading(stringVec rwys, double heading);
|
||||
|
||||
double elevation;
|
||||
|
||||
int innerGetAvailableParking(double radius, const std::string & flType,
|
||||
const std::string & acType, const std::string & airline,
|
||||
bool skipEmptyAirlineCode);
|
||||
public:
|
||||
FGAirportDynamics(FGAirport* ap);
|
||||
~FGAirportDynamics();
|
||||
|
@ -91,36 +90,36 @@ public:
|
|||
};
|
||||
|
||||
void init();
|
||||
double getLongitude() const;
|
||||
// Returns degrees
|
||||
double getLatitude() const;
|
||||
// Returns ft
|
||||
|
||||
double getElevation() const;
|
||||
const string& getId() const;
|
||||
const std::string getId() const;
|
||||
|
||||
FGAirport* parent() const
|
||||
{ return _ap; }
|
||||
|
||||
void getActiveRunway(const string& trafficType, int action, string& runway, double heading);
|
||||
|
||||
void addParking(FGParking& park);
|
||||
bool getAvailableParking(double *lat, double *lon,
|
||||
double *heading, int *gate, double rad, const string& fltype,
|
||||
const string& acType, const string& airline);
|
||||
void getParking (int id, double *lat, double* lon, double *heading);
|
||||
|
||||
/**
|
||||
* retrieve an available parking by GateID, or -1 if no suitable
|
||||
* parking location could be found.
|
||||
*/
|
||||
int getAvailableParking(double radius, const std::string& fltype,
|
||||
const std::string& acType, const std::string& airline);
|
||||
|
||||
FGParking *getParking(int i);
|
||||
void releaseParking(int id);
|
||||
string getParkingName(int i);
|
||||
std::string getParkingName(int i);
|
||||
int getNrOfParkings() {
|
||||
return parkings.size();
|
||||
};
|
||||
//FGAirport *getAddress() { return this; };
|
||||
//const string &getName() const { return _name;};
|
||||
// Returns degrees
|
||||
|
||||
// Departure / Arrival procedures
|
||||
FGSidStar * getSIDs() {
|
||||
return &SIDs;
|
||||
};
|
||||
FGAIFlightPlan * getSID(string activeRunway, double heading);
|
||||
|
||||
/**
|
||||
* Find a parking gate index by name. Note names are often not unique
|
||||
* in our data, so will return the first match.
|
||||
*/
|
||||
int findParkingByName(const std::string& name) const;
|
||||
|
||||
// ATC related functions.
|
||||
FGStartupController *getStartupController() {
|
||||
|
|
|
@ -31,7 +31,7 @@ bool sortByLength (FGTaxiSegment *a, FGTaxiSegment *b);
|
|||
|
||||
class FGTaxiNode
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
SGGeod geod;
|
||||
int index;
|
||||
|
||||
|
@ -106,9 +106,9 @@ FGTaxiNode &operator =(const FGTaxiNode &other)
|
|||
|
||||
const SGGeod& getGeod() const { return geod; }
|
||||
|
||||
int getIndex() { return index; };
|
||||
int getHoldPointType() { return holdType; };
|
||||
bool getIsOnRunway() { return isOnRunway; };
|
||||
int getIndex() const { return index; };
|
||||
int getHoldPointType() const { return holdType; };
|
||||
bool getIsOnRunway() const { return isOnRunway; };
|
||||
|
||||
FGTaxiNode *getAddress() { return this;};
|
||||
FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); };
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
|
||||
#include "gnnode.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
class FGTaxiRoute;
|
||||
|
||||
|
||||
|
@ -46,9 +43,9 @@ class FGParking : public FGTaxiNode {
|
|||
private:
|
||||
double heading;
|
||||
double radius;
|
||||
string parkingName;
|
||||
string type;
|
||||
string airlineCodes;
|
||||
std::string parkingName;
|
||||
std::string type;
|
||||
std::string airlineCodes;
|
||||
|
||||
bool available;
|
||||
int pushBackPoint;
|
||||
|
@ -92,34 +89,26 @@ public:
|
|||
return *this;
|
||||
};
|
||||
~FGParking();
|
||||
// FGParking(double lat,
|
||||
// double lon,
|
||||
// double hdg,
|
||||
// double rad,
|
||||
// int idx,
|
||||
// const string& name,
|
||||
// const string& tpe,
|
||||
// const string& codes);
|
||||
|
||||
void setHeading (double hdg) { heading = hdg; };
|
||||
void setRadius (double rad) { radius = rad; };
|
||||
|
||||
void setName (const string& name) { parkingName = name; };
|
||||
void setType (const string& tpe) { type = tpe; };
|
||||
void setCodes (const string& codes){ airlineCodes= codes;};
|
||||
void setName (const std::string& name) { parkingName = name; };
|
||||
void setType (const std::string& tpe) { type = tpe; };
|
||||
void setCodes (const std::string& codes){ airlineCodes= codes;};
|
||||
|
||||
void setPushBackRoute(FGTaxiRoute *val) { pushBackRoute = val; };
|
||||
void setPushBackPoint(int val) { pushBackPoint = val; };
|
||||
|
||||
bool isAvailable () { return available;};
|
||||
bool isAvailable () const { return available;};
|
||||
void setAvailable(bool val) { available = val; };
|
||||
|
||||
double getHeading () { return heading; };
|
||||
double getRadius () { return radius; };
|
||||
double getHeading () const { return heading; };
|
||||
double getRadius () const { return radius; };
|
||||
|
||||
string getType () { return type; };
|
||||
string getCodes () { return airlineCodes;};
|
||||
string getName () { return parkingName; };
|
||||
std::string getType () const { return type; };
|
||||
std::string getCodes () const { return airlineCodes;};
|
||||
std::string getName () const { return parkingName; };
|
||||
|
||||
FGTaxiRoute * getPushBackRoute () { return pushBackRoute; };
|
||||
|
||||
|
@ -129,8 +118,8 @@ public:
|
|||
return radius < other.radius; };
|
||||
};
|
||||
|
||||
typedef vector<FGParking> FGParkingVec;
|
||||
typedef vector<FGParking>::iterator FGParkingVecIterator;
|
||||
typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
|
||||
typedef std::vector<FGParking> FGParkingVec;
|
||||
typedef std::vector<FGParking>::iterator FGParkingVecIterator;
|
||||
typedef std::vector<FGParking>::const_iterator FGParkingVecConstIterator;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <simgear/props/props_io.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Environment/environment.hxx>
|
||||
|
@ -115,7 +116,6 @@ FGAirportDynamics * FGAirport::getDynamics()
|
|||
FGRunwayPreference rwyPrefs(this);
|
||||
XMLLoader::load(&rwyPrefs);
|
||||
_dynamics->setRwyUse(rwyPrefs);
|
||||
XMLLoader::load(_dynamics->getSIDs());
|
||||
|
||||
return _dynamics;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "runwayprefloader.hxx"
|
||||
|
||||
#include "dynamics.hxx"
|
||||
#include "simple.hxx"
|
||||
#include "runwayprefs.hxx"
|
||||
|
||||
using std::string;
|
||||
|
@ -36,9 +37,10 @@ using std::string;
|
|||
XMLLoader::XMLLoader() {}
|
||||
XMLLoader::~XMLLoader() {}
|
||||
|
||||
void XMLLoader::load(FGAirportDynamics* d) {
|
||||
void XMLLoader::load(FGAirportDynamics* d)
|
||||
{
|
||||
FGAirportDynamicsXMLLoader visitor(d);
|
||||
if(loadAirportXMLDataIntoVisitor(d->getId(), "groundnet", visitor)) {
|
||||
if(loadAirportXMLDataIntoVisitor(d->parent()->ident(), "groundnet", visitor)) {
|
||||
d->init();
|
||||
}
|
||||
}
|
||||
|
@ -48,13 +50,6 @@ void XMLLoader::load(FGRunwayPreference* p) {
|
|||
loadAirportXMLDataIntoVisitor(p->getId(), "rwyuse", visitor);
|
||||
}
|
||||
|
||||
void XMLLoader::load(FGSidStar* p) {
|
||||
SGPath path;
|
||||
if (findAirportData(p->getId(), "SID", path)) {
|
||||
p->load(path);
|
||||
}
|
||||
}
|
||||
|
||||
bool XMLLoader::findAirportData(const std::string& aICAO,
|
||||
const std::string& aFileName, SGPath& aPath)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
// simgear
|
||||
#include <simgear/props/props_io.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "globals.hxx"
|
||||
#include "fg_props.hxx"
|
||||
|
@ -150,7 +151,8 @@ bool setPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
|
|||
}
|
||||
|
||||
// Set current_options lon/lat given an airport id and parkig position name
|
||||
static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& parkpos ) {
|
||||
static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& parkpos )
|
||||
{
|
||||
if ( id.empty() )
|
||||
return false;
|
||||
|
||||
|
@ -167,11 +169,9 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
|
|||
return false;
|
||||
}
|
||||
|
||||
int park_index = dcs->getNrOfParkings() - 1;
|
||||
bool succes;
|
||||
int gateID;
|
||||
double radius = fgGetDouble("/sim/dimensions/radius-m");
|
||||
if ((parkpos == string("AVAILABLE")) && (radius > 0)) {
|
||||
double lat, lon, heading;
|
||||
string fltType;
|
||||
string acOperator;
|
||||
SGPath acData;
|
||||
|
@ -203,30 +203,27 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
|
|||
}
|
||||
|
||||
string acType; // Currently not used by findAvailable parking, so safe to leave empty.
|
||||
succes = dcs->getAvailableParking(&lat, &lon, &heading, &park_index, radius, fltType, acType, acOperator);
|
||||
if (succes) {
|
||||
gateID = dcs->getAvailableParking(radius, fltType, acType, acOperator);
|
||||
if (gateID >=0 ) {
|
||||
fgGetString("/sim/presets/parkpos");
|
||||
fgSetString("/sim/presets/parkpos", dcs->getParking(park_index)->getName());
|
||||
fgSetString("/sim/presets/parkpos", dcs->getParking(gateID)->getName());
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to find a suitable parking at airport " << id );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
//cerr << "We shouldn't get here when AVAILABLE" << endl;
|
||||
while (park_index >= 0 && dcs->getParkingName(park_index) != parkpos) park_index--;
|
||||
if (park_index < 0) {
|
||||
gateID = dcs->findParkingByName(parkpos);
|
||||
if (gateID < 0) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to find parking position " << parkpos <<
|
||||
" at airport " << id );
|
||||
"Failed to find a parking at airport " << id << ":" << parkpos);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
FGParking* parking = dcs->getParking(park_index);
|
||||
|
||||
FGParking* parking = dcs->getParking(gateID);
|
||||
parking->setAvailable(false);
|
||||
fgApplyStartOffset(
|
||||
SGGeod::fromDeg(parking->getLongitude(), parking->getLatitude()),
|
||||
parking->getHeading());
|
||||
fgApplyStartOffset(parking->getGeod(), parking->getHeading());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue