From db816deb90961b82e085f3d7afc64b4977728f49 Mon Sep 17 00:00:00 2001 From: Durk Talsma Date: Sat, 17 Sep 2011 16:51:00 +0200 Subject: [PATCH] Added a new startup option. By giving the command line option --parkpos=AVAILABLE you can -in principle- let FlightGear decide what the most optimal parking location is. This option does require a few properties to be set that are also needed for future ATC use. Hence, they are listed under /sim/ATC, but could move to a different location if desired. /sim/ATC/radius should be a nummeric estimate of the size of your aircraft. A small aircraft fits into a large parking, but a large aircraft does not fit into a small parking space. Because the AI part of radius is also used for slightly different purposes (prioritizing gate assignmments, the given valuem may deviate slightly from the real aircraft size. See http:/wiki.flightgear.org/Aircraft.radii for an overview of currently used values for the redius property. /sim/ATC/flight-type can be any one of "ga", "cargo", "gate", "mil-fighter", "mil-cargo", or "vtol". See http://wiki.flightgear.org/Interactive_traffic#A_technical_perspective for more information. optionally, the property /sim/ATC/airline can be set set to a three letter icao airline code. By way of illustration, I will commit a number of startup preset files setting these properties shortly. Also did some more finetuning to the traffic mananger routing algorithm can be any one of "ga", "cargo", "gate", "mil-fighter", "mil-cargo", or "vtol". See http://wiki.flightgear.org/Interactive_traffic#A_technical_perspective for more information. optionally, the property /sim/ATC/airline can be set set to a three letter icao airline code. By way of illustration, I will commit a number of startup preset files setting these properties shortly. Also did some more finetuning to the traffic mananger routing algorithm. --- src/ATC/atc_mgr.cxx | 2 +- src/Main/fg_init.cxx | 36 ++++++++++++++++++++++++++++-------- src/Traffic/Schedule.cxx | 28 +++++++++++++++++++++------- src/Traffic/Schedule.hxx | 4 ++-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/ATC/atc_mgr.cxx b/src/ATC/atc_mgr.cxx index 73130fe63..ef17774c2 100644 --- a/src/ATC/atc_mgr.cxx +++ b/src/ATC/atc_mgr.cxx @@ -111,7 +111,7 @@ void FGATCManager::init() { if (park_index < 0) { SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find parking position " << parking << - " at airport " << airport ); + " at airport " << airport << "at " << SG_ORIGIN); } if (parking.empty() || (park_index < 0)) { controller = apt->getDynamics()->getTowerController(); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 25fe5a6f7..7f9bc87c2 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -901,18 +901,38 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par FGAirportDynamics* dcs = apt->getDynamics(); if (!dcs) { SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find parking position " << parkpos << - " at airport " << id ); + "Airport " << id << "does not appear to have parking information available"); return false; } int park_index = dcs->getNrOfParkings() - 1; - while (park_index >= 0 && dcs->getParkingName(park_index) != parkpos) park_index--; - if (park_index < 0) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find parking position " << parkpos << - " at airport " << id ); - return false; + bool succes; + double radius = fgGetDouble("/sim/atc/acradius"); + //cerr << "Using radius " << radius << endl; + //cerr << "Checking parkpos comparison " << (bool) (parkpos == string("AVAILABLE")) << endl; + if ((parkpos == string("AVAILABLE")) && (radius > 0)) { + double lat, lon, heading; + string fltType = fgGetString("/sim/atc/flight-type"); + string airline = fgGetString("/sim/atc/airline" ); + string acType; // Currently not used by findAvailable parking, so safe to leave empty. + succes = dcs->getAvailableParking(&lat, &lon, &heading, &park_index, radius, fltType, acType, airline); + if (succes) { + fgGetString("/sim/presets/parkpos"); + fgSetString("/sim/presets/parkpos", dcs->getParking(park_index)->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) { + SG_LOG( SG_GENERAL, SG_ALERT, + "Failed to find parking position " << parkpos << + " at airport " << id ); + return false; + } } FGParking* parking = dcs->getParking(park_index); parking->setAvailable(false); diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index 2e2ef33d9..a4a18ca17 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -201,7 +201,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) if (!valid) { return false; } - scheduleFlights(); + scheduleFlights(now); if (flights.empty()) { // No flights available for this aircraft valid = false; return false; @@ -369,17 +369,24 @@ void FGAISchedule::setHeading() courseToDest = SGGeodesy::courseDeg((*flights.begin())->getDepartureAirport()->geod(), (*flights.begin())->getArrivalAirport()->geod()); } -void FGAISchedule::scheduleFlights() +void FGAISchedule::scheduleFlights(time_t now) { - string startingPort; if (!flights.empty()) { return; } - // change back to bulk + string startingPort; + string userPort = fgGetString("/sim/presets/airport-id"); SG_LOG(SG_GENERAL, SG_BULK, "Scheduling Flights for : " << modelPath << " " << registration << " " << homePort); FGScheduledFlight *flight = NULL; do { - flight = findAvailableFlight(currentDestination, flightIdentifier); + if (currentDestination.empty()) { + flight = findAvailableFlight(userPort, flightIdentifier, now, (now+6400)); + if (!flight) + flight = findAvailableFlight(currentDestination, flightIdentifier); + } else { + flight = findAvailableFlight(currentDestination, flightIdentifier); + } + if (!flight) { break; } @@ -389,11 +396,12 @@ void FGAISchedule::scheduleFlights() currentDestination = flight->getArrivalAirport()->getId(); + //cerr << "Current destination " << currentDestination << endl; if (!initialized) { string departurePort = flight->getDepartureAirport()->getId(); //cerr << "Scheduled " << registration << " " << score << " for Flight " // << flight-> getCallSign() << " from " << departurePort << " to " << currentDestination << endl; - if (fgGetString("/sim/presets/airport-id") == departurePort) { + if (userPort == departurePort) { hits++; } //runCount++; @@ -452,7 +460,8 @@ bool FGAISchedule::next() } FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDestination, - const string &req) + const string &req, + time_t min, time_t max) { time_t now = time(NULL) + fgGetLong("/sim/time/warp"); @@ -501,6 +510,11 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDesti if ((*i)->getDepartureTime() < (arrival+(20*60))) continue; } + if (min != 0) { + time_t dep = (*i)->getDepartureTime(); + if ((dep < min) || (dep > max)) + continue; + } // So, if we actually get here, we have a winner //cerr << "found flight: " << req << " : " << currentDestination << " : " << diff --git a/src/Traffic/Schedule.hxx b/src/Traffic/Schedule.hxx index 7c7816120..27385ed0d 100644 --- a/src/Traffic/Schedule.hxx +++ b/src/Traffic/Schedule.hxx @@ -62,7 +62,7 @@ class FGAISchedule bool initialized; bool valid; - void scheduleFlights(); + void scheduleFlights(time_t now); /** * Transition this schedule from distant mode to AI mode; @@ -122,7 +122,7 @@ class FGAISchedule void setHeading (); void assign (FGScheduledFlight *ref) { flights.push_back(ref); }; void setFlightType (string val ) { flightType = val; }; - FGScheduledFlight*findAvailableFlight (const string ¤tDestination, const string &req); + FGScheduledFlight*findAvailableFlight (const string ¤tDestination, const string &req, time_t min=0, time_t max=0); // used to sort in decending order of score: I've probably found a better way to // decending order sorting, but still need to test that. bool operator< (const FGAISchedule &other) const;