]> git.mxchange.org Git - flightgear.git/blob - src/Traffic/SchedFlight.cxx
Port over remaining Point3D usage to the more type and unit safe SG* classes.
[flightgear.git] / src / Traffic / SchedFlight.cxx
1 /******************************************************************************
2  * SchedFlight.cxx
3  * Written by Durk Talsma, started May 5, 2004.
4  *
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.
9  *
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.
14  *
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.
18  *
19  *
20  **************************************************************************/
21  
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. 
25  * 
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
30  *    decelerations) 
31  * 4) Each aircraft leaves at exactly the departure time. 
32  * 5) Each aircraft arrives at exactly the specified arrival time. 
33  *
34  * TODO:
35  * - Check the code for known portability issues
36  * - Find an alternative for the depricated Point3D class
37  *
38  *****************************************************************************/
39
40 #ifdef HAVE_CONFIG_H
41 #  include "config.h"
42 #endif
43
44 #include <stdlib.h>
45 #include <time.h>
46 #include <iostream>
47 #include <fstream>
48
49
50 #include <string>
51 #include <vector>
52
53 #include <simgear/compiler.h>
54 #include <simgear/props/props.hxx>
55 #include <simgear/route/waypoint.hxx>
56 #include <simgear/structure/subsystem_mgr.hxx>
57 #include <simgear/timing/sg_time.hxx>
58 #include <simgear/xml/easyxml.hxx>
59
60 #include <AIModel/AIFlightPlan.hxx>
61 #include <AIModel/AIManager.hxx>
62 #include <Airports/simple.hxx>
63 #include <Main/fg_init.hxx>   // That's pretty ugly, but I need fgFindAirportID
64
65
66
67 #include <Main/globals.hxx>
68
69 #include "SchedFlight.hxx"
70
71
72 /******************************************************************************
73  * FGScheduledFlight stuff
74  *****************************************************************************/
75
76 FGScheduledFlight::FGScheduledFlight()
77 {
78    initialized = false;
79    available = true;
80 }
81   
82 FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
83 {
84   callsign          = other.callsign;
85   fltRules          = other.fltRules;
86   departurePort     = other.departurePort;
87   depId             = other.depId;
88   arrId             = other.arrId;
89   departureTime     = other.departureTime;
90   cruiseAltitude    = other.cruiseAltitude;
91   arrivalPort       = other.arrivalPort;
92   arrivalTime       = other.arrivalTime;
93   repeatPeriod      = other.repeatPeriod;
94   initialized       = other.initialized;
95   requiredAircraft  = other.requiredAircraft;
96   available         = other.available;
97 }
98
99 FGScheduledFlight::FGScheduledFlight(const string& cs,
100                    const string& fr,
101                    const string& depPrt,
102                    const string& arrPrt,
103                    int cruiseAlt,
104                    const string& deptime,
105                    const string& arrtime,
106                    const string& rep,
107                    const string& reqAC)
108 {
109   callsign          = cs;
110   fltRules          = fr;
111   //departurePort.setId(depPrt);
112   //arrivalPort.setId(arrPrt);
113   depId = depPrt;
114   arrId = arrPrt;
115   //cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
116   //departureTime     = processTimeString(deptime);
117   //arrivalTime       = processTimeString(arrtime);
118   cruiseAltitude    = cruiseAlt;
119   requiredAircraft  = reqAC;
120
121   // Process the repeat period string
122   if (rep.find("WEEK",0) != string::npos)
123     {
124       repeatPeriod = 7*24*60*60; // in seconds
125     }
126   else if (rep.find("Hr", 0) != string::npos)
127     {
128       repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
129     }
130   else
131     {
132       repeatPeriod = 365*24*60*60;
133       SG_LOG( SG_GENERAL, SG_ALERT, "Unknown repeat period in flight plan "
134                                     "of flight '" << cs << "': " << rep );
135     }
136
137   // What we still need to do is preprocess the departure and
138   // arrival times. 
139   departureTime = processTimeString(deptime);
140   arrivalTime   = processTimeString(arrtime);
141   //departureTime += rand() % 300; // Make sure departure times are not limited to 5 minute increments.
142   if (departureTime > arrivalTime)
143     {
144       departureTime -= repeatPeriod;
145     }
146   initialized = false;
147   available   = true;
148 }
149
150
151 FGScheduledFlight:: ~FGScheduledFlight()
152 {
153 }
154
155 time_t FGScheduledFlight::processTimeString(const string& theTime)
156 {
157   int weekday;
158   int timeOffsetInDays;
159   int targetHour;
160   int targetMinute;
161   int targetSecond;
162
163   tm targetTimeDate;
164   SGTime* currTimeDate = globals->get_time_params();
165  
166   string timeCopy = theTime;
167
168
169   // okay first split theTime string into
170   // weekday, hour, minute, second;
171   // Check if a week day is specified 
172   if (timeCopy.find("/",0) != string::npos)
173     {
174       weekday          = atoi(timeCopy.substr(0,1).c_str());
175       timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
176       timeCopy = timeCopy.substr(2,timeCopy.length());
177     }
178   else 
179     {
180       timeOffsetInDays = 0;
181     }
182   // TODO: verify status of each token.
183   targetHour   = atoi(timeCopy.substr(0,2).c_str());
184   targetMinute = atoi(timeCopy.substr(3,5).c_str());
185   targetSecond = atoi(timeCopy.substr(6,8).c_str());
186   targetTimeDate.tm_year  = currTimeDate->getGmt()->tm_year;
187   targetTimeDate.tm_mon   = currTimeDate->getGmt()->tm_mon;
188   targetTimeDate.tm_mday  = currTimeDate->getGmt()->tm_mday;
189   targetTimeDate.tm_hour  = targetHour;
190   targetTimeDate.tm_min   = targetMinute;
191   targetTimeDate.tm_sec   = targetSecond;
192
193   time_t processedTime = sgTimeGetGMT(&targetTimeDate);
194   processedTime += timeOffsetInDays*24*60*60;
195   if (processedTime < currTimeDate->get_cur_time())
196     {
197       processedTime += repeatPeriod;
198     }
199   //tm *temp = currTimeDate->getGmt();
200   //char buffer[512];
201   //sgTimeFormatTime(&targetTimeDate, buffer);
202   //cout << "Scheduled Time " << buffer << endl; 
203   //cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
204   return processedTime;
205 }
206
207 void FGScheduledFlight::update()
208 {
209   departureTime += repeatPeriod;
210   arrivalTime  += repeatPeriod;
211 }
212
213 void FGScheduledFlight::adjustTime(time_t now)
214 {
215   //cerr << "1: Adjusting schedule please wait: " << now 
216   //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
217   // Make sure that the arrival time is in between 
218   // the current time and the next repeat period.
219   while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
220     {
221       if (arrivalTime < now)
222         {
223           departureTime += repeatPeriod;
224           arrivalTime   += repeatPeriod;
225         }
226       else if (arrivalTime > now+repeatPeriod)
227         {
228           departureTime -= repeatPeriod;
229           arrivalTime   -= repeatPeriod;
230         }
231       //      cerr << "2: Adjusting schedule please wait: " << now 
232       //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
233     }
234 }
235
236
237 FGAirport *FGScheduledFlight::getDepartureAirport()
238 {
239   if (!(initialized))
240     {
241       initializeAirports();
242     }
243   if (initialized)
244     return departurePort;
245   else
246     return 0;
247 }
248 FGAirport * FGScheduledFlight::getArrivalAirport  ()
249 {
250    if (!(initialized))
251     {
252       initializeAirports();
253     }
254    if (initialized)
255      return arrivalPort;
256    else
257      return 0;
258 }
259
260 // Upon the first time of requesting airport information
261 // for this scheduled flight, these data need to be
262 // looked up in the main FlightGear database. 
263 // Missing or bogus Airport codes are currently ignored,
264 // but we should improve that. The best idea is probably to cancel
265 // this flight entirely by removing it from the schedule, if one
266 // of the airports cannot be found. 
267 bool FGScheduledFlight::initializeAirports()
268 {
269   //cerr << "Initializing using : " << depId << " " << arrId << endl;
270   departurePort = FGAirport::findByIdent(depId);
271   if(departurePort == NULL)
272     {
273       SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find departure airport : " << depId);
274       return false;
275     }
276   arrivalPort = FGAirport::findByIdent(arrId);
277   if(arrivalPort == NULL)
278     {
279       SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airport   : " << arrId);
280       return false;
281     }
282
283   //cerr << "Found : " << departurePort->getId() << endl;
284   //cerr << "Found : " << arrivalPort->getId() << endl;
285   initialized = true;
286   return true;
287 }
288
289
290 bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b) 
291
292   return (*a) < (*b); 
293 };