1 /******************************************************************************
3 * Written by Durk Talsma, started May 5, 2004.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 **************************************************************************/
22 /* This a prototype version of a top-level flight plan manager for Flightgear.
23 * It parses the fgtraffic.txt file and determine for a specific time/date,
24 * where each aircraft listed in this file is at the current time.
26 * I'm currently assuming the following simplifications:
27 * 1) The earth is a perfect sphere
28 * 2) Each aircraft flies a perfect great circle route.
29 * 3) Each aircraft flies at a constant speed (with infinite accelerations and
31 * 4) Each aircraft leaves at exactly the departure time.
32 * 5) Each aircraft arrives at exactly the specified arrival time.
35 * - Check the code for known portability issues
37 *****************************************************************************/
52 #include <simgear/compiler.h>
53 #include <simgear/props/props.hxx>
54 #include <simgear/structure/subsystem_mgr.hxx>
55 #include <simgear/timing/sg_time.hxx>
56 #include <simgear/xml/easyxml.hxx>
58 #include <AIModel/AIFlightPlan.hxx>
59 #include <AIModel/AIManager.hxx>
60 #include <Airports/airport.hxx>
61 #include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
65 #include <Main/globals.hxx>
67 #include "SchedFlight.hxx"
70 /******************************************************************************
71 * FGScheduledFlight stuff
72 *****************************************************************************/
74 FGScheduledFlight::FGScheduledFlight()
86 FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
88 callsign = other.callsign;
89 fltRules = other.fltRules;
90 departurePort = other.departurePort;
93 departureTime = other.departureTime;
94 cruiseAltitude = other.cruiseAltitude;
95 arrivalPort = other.arrivalPort;
96 arrivalTime = other.arrivalTime;
97 repeatPeriod = other.repeatPeriod;
98 initialized = other.initialized;
99 requiredAircraft = other.requiredAircraft;
100 available = other.available;
103 FGScheduledFlight::FGScheduledFlight(const string& cs,
105 const string& depPrt,
106 const string& arrPrt,
108 const string& deptime,
109 const string& arrtime,
115 //departurePort.setId(depPrt);
116 //arrivalPort.setId(arrPrt);
119 //cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
120 //departureTime = processTimeString(deptime);
121 //arrivalTime = processTimeString(arrtime);
122 cruiseAltitude = cruiseAlt;
123 requiredAircraft = reqAC;
125 // Process the repeat period string
126 if (rep.find("WEEK",0) != string::npos)
128 repeatPeriod = 7*24*60*60; // in seconds
130 else if (rep.find("Hr", 0) != string::npos)
132 repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
136 repeatPeriod = 365*24*60*60;
137 SG_LOG( SG_AI, SG_ALERT, "Unknown repeat period in flight plan "
138 "of flight '" << cs << "': " << rep );
141 // What we still need to do is preprocess the departure and
143 departureTime = processTimeString(deptime);
144 arrivalTime = processTimeString(arrtime);
145 //departureTime += rand() % 300; // Make sure departure times are not limited to 5 minute increments.
146 if (departureTime > arrivalTime)
148 departureTime -= repeatPeriod;
155 FGScheduledFlight:: ~FGScheduledFlight()
159 time_t FGScheduledFlight::processTimeString(const string& theTime)
162 int timeOffsetInDays;
168 SGTime* currTimeDate = globals->get_time_params();
170 string timeCopy = theTime;
173 // okay first split theTime string into
174 // weekday, hour, minute, second;
175 // Check if a week day is specified
176 if (timeCopy.find("/",0) != string::npos)
178 weekday = atoi(timeCopy.substr(0,1).c_str());
179 timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
180 timeCopy = timeCopy.substr(2,timeCopy.length());
184 timeOffsetInDays = 0;
186 // TODO: verify status of each token.
187 targetHour = atoi(timeCopy.substr(0,2).c_str());
188 targetMinute = atoi(timeCopy.substr(3,5).c_str());
189 targetSecond = atoi(timeCopy.substr(6,8).c_str());
190 targetTimeDate.tm_year = currTimeDate->getGmt()->tm_year;
191 targetTimeDate.tm_mon = currTimeDate->getGmt()->tm_mon;
192 targetTimeDate.tm_mday = currTimeDate->getGmt()->tm_mday;
193 targetTimeDate.tm_hour = targetHour;
194 targetTimeDate.tm_min = targetMinute;
195 targetTimeDate.tm_sec = targetSecond;
197 time_t processedTime = sgTimeGetGMT(&targetTimeDate);
198 processedTime += timeOffsetInDays*24*60*60;
199 if (processedTime < currTimeDate->get_cur_time())
201 processedTime += repeatPeriod;
203 //tm *temp = currTimeDate->getGmt();
205 //sgTimeFormatTime(&targetTimeDate, buffer);
206 //cout << "Scheduled Time " << buffer << endl;
207 //cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
208 return processedTime;
211 void FGScheduledFlight::update()
213 departureTime += repeatPeriod;
214 arrivalTime += repeatPeriod;
217 void FGScheduledFlight::adjustTime(time_t now)
219 //cerr << "1: Adjusting schedule please wait: " << now
220 // << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
221 // Make sure that the arrival time is in between
222 // the current time and the next repeat period.
223 while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
225 if (arrivalTime < now)
227 departureTime += repeatPeriod;
228 arrivalTime += repeatPeriod;
230 else if (arrivalTime > now+repeatPeriod)
232 departureTime -= repeatPeriod;
233 arrivalTime -= repeatPeriod;
235 // cerr << "2: Adjusting schedule please wait: " << now
236 // << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
241 FGAirport *FGScheduledFlight::getDepartureAirport()
245 initializeAirports();
248 return departurePort;
252 FGAirport * FGScheduledFlight::getArrivalAirport ()
256 initializeAirports();
264 // Upon the first time of requesting airport information
265 // for this scheduled flight, these data need to be
266 // looked up in the main FlightGear database.
267 // Missing or bogus Airport codes are currently ignored,
268 // but we should improve that. The best idea is probably to cancel
269 // this flight entirely by removing it from the schedule, if one
270 // of the airports cannot be found.
271 bool FGScheduledFlight::initializeAirports()
273 //cerr << "Initializing using : " << depId << " " << arrId << endl;
274 departurePort = FGAirport::findByIdent(depId);
275 if(departurePort == NULL)
277 SG_LOG( SG_AI, SG_DEBUG, "Traffic manager could not find departure airport : " << depId);
280 arrivalPort = FGAirport::findByIdent(arrId);
281 if(arrivalPort == NULL)
283 SG_LOG( SG_AI, SG_DEBUG, "Traffic manager could not find arrival airport : " << arrId);
287 //cerr << "Found : " << departurePort->getId() << endl;
288 //cerr << "Found : " << arrivalPort->getId() << endl;
294 bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b)