]> git.mxchange.org Git - flightgear.git/blob - src/Traffic/SchedFlight.cxx
2672d3d26dc9a2fff8493e1ac6ee7ef7b1bd7b73
[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 <plib/sg.h>
54
55 #include <simgear/compiler.h>
56 #include <simgear/math/polar3d.hxx>
57 #include <simgear/math/sg_geodesy.hxx>
58 #include <simgear/props/props.hxx>
59 #include <simgear/route/waypoint.hxx>
60 #include <simgear/structure/subsystem_mgr.hxx>
61 #include <simgear/timing/sg_time.hxx>
62 #include <simgear/xml/easyxml.hxx>
63
64 #include <AIModel/AIFlightPlan.hxx>
65 #include <AIModel/AIManager.hxx>
66 #include <Airports/simple.hxx>
67 #include <Main/fg_init.hxx>   // That's pretty ugly, but I need fgFindAirportID
68
69
70
71 #include <Main/globals.hxx>
72
73 #include "SchedFlight.hxx"
74
75
76 /******************************************************************************
77  * FGScheduledFlight stuff
78  *****************************************************************************/
79
80 FGScheduledFlight::FGScheduledFlight()
81 {
82 }
83   
84 FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
85 {
86   callsign        = other.callsign;
87   fltRules        = other.fltRules;
88   departurePort   = other.departurePort;
89   depId           = other.depId;
90   arrId           = other.arrId;
91   departureTime   = other.departureTime;
92   cruiseAltitude  = other.cruiseAltitude;
93   arrivalPort     = other.arrivalPort;
94   arrivalTime     = other.arrivalTime;
95   repeatPeriod    = other.repeatPeriod;
96   initialized     = other.initialized;
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 {
108   callsign          = cs;
109   fltRules          = fr;
110   //departurePort.setId(depPrt);
111   //arrivalPort.setId(arrPrt);
112   depId = depPrt;
113   arrId = arrPrt;
114   //cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
115   //departureTime     = processTimeString(deptime);
116   //arrivalTime       = processTimeString(arrtime);
117   cruiseAltitude    = cruiseAlt;
118
119   // Process the repeat period string
120   if (rep.find("WEEK",0) != string::npos)
121     {
122       repeatPeriod = 7*24*60*60; // in seconds
123     }
124   else if (rep.find("Hr", 0) != string::npos)
125     {
126       repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
127     }
128   else
129     {
130       cerr << "Unknown repeat period" << endl;
131       exit(1);
132     }
133
134   // What we still need to do is preprocess the departure and
135   // arrival times. 
136   departureTime = processTimeString(deptime);
137   arrivalTime   = processTimeString(arrtime);
138   if (departureTime > arrivalTime)
139     {
140       departureTime -= repeatPeriod;
141     }
142   initialized = false;
143 }
144
145
146 FGScheduledFlight:: ~FGScheduledFlight()
147 {
148 }
149
150 time_t FGScheduledFlight::processTimeString(const string& theTime)
151 {
152   int weekday;
153   int timeOffsetInDays;
154   int targetDate;
155   int targetHour;
156   int targetMinute;
157   int targetSecond;
158
159   tm targetTimeDate;
160   SGTime* currTimeDate = globals->get_time_params();
161  
162   string timeCopy = theTime;
163
164
165   // okay first split theTime string into
166   // weekday, hour, minute, second;
167   // Check if a week day is specified 
168   if (timeCopy.find("/",0) != string::npos)
169     {
170       weekday          = atoi(timeCopy.substr(0,1).c_str());
171       timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
172       timeCopy = timeCopy.substr(2,timeCopy.length());
173     }
174   else 
175     {
176       timeOffsetInDays = 0;
177     }
178   targetHour   = atoi(timeCopy.substr(0,2).c_str());
179   targetMinute = atoi(timeCopy.substr(3,5).c_str());
180   targetSecond = atoi(timeCopy.substr(6,8).c_str());
181   targetTimeDate.tm_year  = currTimeDate->getGmt()->tm_year;
182   targetTimeDate.tm_mon   = currTimeDate->getGmt()->tm_mon;
183   targetTimeDate.tm_mday  = currTimeDate->getGmt()->tm_mday;
184   targetTimeDate.tm_hour  = targetHour;
185   targetTimeDate.tm_min   = targetMinute;
186   targetTimeDate.tm_sec   = targetSecond;
187
188   time_t processedTime = sgTimeGetGMT(&targetTimeDate);
189   processedTime += timeOffsetInDays*24*60*60;
190   if (processedTime < currTimeDate->get_cur_time())
191     {
192       processedTime += repeatPeriod;
193     }
194   //tm *temp = currTimeDate->getGmt();
195   //char buffer[512];
196   //sgTimeFormatTime(&targetTimeDate, buffer);
197   //cout << "Scheduled Time " << buffer << endl; 
198   //cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
199   return processedTime;
200 }
201
202 void FGScheduledFlight::update()
203 {
204   departureTime += repeatPeriod;
205   arrivalTime  += repeatPeriod;
206 }
207
208 void FGScheduledFlight::adjustTime(time_t now)
209 {
210   //cerr << "1: Adjusting schedule please wait: " << now 
211   //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
212   // Make sure that the arrival time is in between 
213   // the current time and the next repeat period.
214   while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
215     {
216       if (arrivalTime < now)
217         {
218           departureTime += repeatPeriod;
219           arrivalTime   += repeatPeriod;
220         }
221       else if (arrivalTime > now+repeatPeriod)
222         {
223           departureTime -= repeatPeriod;
224           arrivalTime   -= repeatPeriod;
225         }
226       //      cerr << "2: Adjusting schedule please wait: " << now 
227       //   << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
228     }
229 }
230
231
232 FGAirport *FGScheduledFlight::getDepartureAirport()
233 {
234   if (!(initialized))
235     {
236       initializeAirports();
237     }
238   if (initialized)
239     return departurePort;
240   else
241     return 0;
242 }
243 FGAirport * FGScheduledFlight::getArrivalAirport  ()
244 {
245    if (!(initialized))
246     {
247       initializeAirports();
248     }
249    if (initialized)
250      return arrivalPort;
251    else
252      return 0;
253 }
254
255 // Upon the first time of requesting airport information
256 // for this scheduled flight, these data need to be
257 // looked up in the main FlightGear database. 
258 // Missing or bogus Airport codes are currently ignored,
259 // but we should improve that. The best idea is probably to cancel
260 // this flight entirely by removing it from the schedule, if one
261 // of the airports cannot be found. 
262 bool FGScheduledFlight::initializeAirports()
263 {
264   //cerr << "Initializing using : " << depId << " " << arrId << endl;
265   departurePort = globals->get_airports()->search(depId);
266   if(departurePort == NULL)
267     {
268       cerr << "Could not find " << depId << endl; 
269       return false;
270     }
271   arrivalPort = globals->get_airports()->search(arrId);
272   if(arrivalPort == NULL)
273     {
274       cerr << "Could not find " << arrId << endl;
275       return false;
276     }
277
278   //cerr << "Found : " << departurePort->getId() << endl;
279   //cerr << "Found : " << arrivalPort->getId() << endl;
280   initialized = true;
281   return true;
282 }