]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIFlightPlanCreatePushBack.cxx
Merge branch 'next' into durk-atc
[flightgear.git] / src / AIModel / AIFlightPlanCreatePushBack.cxx
1 /******************************************************************************
2  * AIFlightPlanCreatePushBack.cxx
3  * Written by Durk Talsma, started August 1, 2007.
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 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #include <simgear/math/sg_geodesy.hxx>
26
27 #include <Airports/simple.hxx>
28 #include <Airports/runways.hxx>
29 #include <Airports/dynamics.hxx>
30
31 #include <Environment/environment_mgr.hxx>
32 #include <Environment/environment.hxx>
33
34 #include "AIFlightPlan.hxx"
35 #include "AIAircraft.hxx"
36 #include "performancedata.hxx"
37
38
39 // TODO: Use James Turner's createOnGround functions.
40 void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
41                                     bool firstFlight, FGAirport *dep, 
42                                     double latitude,
43                                     double longitude,
44                                     double radius,
45                                     const string& fltType,
46                                     const string& aircraftType,
47                                     const string& airline)
48 {
49     double lat, lon, heading;
50     double vTaxi = ac->getPerformance()->vTaxi();
51     double vTaxiBackward = vTaxi * (-2.0/3.0);
52     double vTaxiReduced  = vTaxi * (2.0/3.0);
53     FGTaxiRoute *pushBackRoute;
54     // Active runway can be conditionally set by ATC, so at the start of a new flight, this
55     // must be reset.
56     activeRunway.clear();
57
58     if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
59         //cerr << "Push Back fallback" << endl;
60         createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
61                                radius, fltType, aircraftType, airline);
62     } else {
63         if (firstFlight) {
64              
65              if (!(dep->getDynamics()->getAvailableParking(&lat, &lon, 
66                                                            &heading, &gateId, 
67                                                            radius, fltType, 
68                                                            aircraftType, airline))) {
69                     SG_LOG(SG_INPUT, SG_WARN, "Warning: Could not find parking for a " << 
70                                               aircraftType <<
71                                               " of flight type " << fltType << 
72                                               " of airline     " << airline <<
73                                               " at airport     " << dep->getId());
74                     char buffer[10];
75                     snprintf (buffer, 10, "%d", gateId);
76                     //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
77                     waypoint *wpt;
78                     wpt = new waypoint;
79                     wpt->name      = string(buffer); // fixme: should be the name of the taxiway
80                     wpt->latitude  = lat;
81                     wpt->longitude = lon;
82                     // Elevation is currently disregarded when on_ground is true
83                     // because the AIModel obtains a periodic ground elevation estimate.
84                    wpt->altitude  = dep->getElevation();
85                    wpt->speed = vTaxiBackward;
86                    wpt->crossat   = -10000;
87                    wpt->gear_down = true;
88                    wpt->flaps_down= true;
89                    wpt->finished  = false;
90                    wpt->on_ground = true;
91                    wpt->routeIndex = -1;
92                    waypoints.push_back(wpt);
93             }
94            //cerr << "Success : GateId = " << gateId << endl;
95            SG_LOG(SG_INPUT, SG_WARN, "Warning: Succesfully found a parking for a " << 
96                                               aircraftType <<
97                                               " of flight type " << fltType << 
98                                               " of airline     " << airline <<
99                                               " at airport     " << dep->getId());
100         } else {
101             //cerr << "Push Back follow-up Flight" << endl;
102             dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
103         }
104         if (gateId < 0) {
105              createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
106                                     radius, fltType, aircraftType, airline);
107              return;
108
109         }
110         //cerr << "getting parking " << gateId;
111         //cerr << " for a " << 
112         //                                      aircraftType <<
113         //                                      " of flight type " << fltType << 
114         //                                      " of airline     " << airline <<
115         //                                      " at airport     " << dep->getId() << endl;
116         FGParking *parking = dep->getDynamics()->getParking(gateId);
117         int pushBackNode = parking->getPushBackPoint();
118
119
120         pushBackRoute = parking->getPushBackRoute();
121         if ((pushBackNode > 0) && (pushBackRoute == 0)) {
122             int node, rte;
123             FGTaxiRoute route;
124             //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
125             route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
126             parking->setPushBackRoute(new FGTaxiRoute(route));
127             
128
129             pushBackRoute = parking->getPushBackRoute();
130             int size = pushBackRoute->size();
131             if (size < 2) {
132                 SG_LOG(SG_GENERAL, SG_WARN, "Push back route from gate " << gateId << " has only " << size << " nodes.");
133                 SG_LOG(SG_GENERAL, SG_WARN, "Using  " << pushBackNode);
134             }
135             pushBackRoute->first();
136             waypoint *wpt;
137             while(pushBackRoute->next(&node, &rte))
138               {
139                 //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
140                 char buffer[10];
141                 snprintf (buffer, 10, "%d", node);
142                 FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
143                 //ids.pop_back();  
144                 wpt = new waypoint;
145                 wpt->name      = string(buffer); // fixme: should be the name of the taxiway
146                 wpt->latitude  = tn->getLatitude();
147                 wpt->longitude = tn->getLongitude();
148                 // Elevation is currently disregarded when on_ground is true
149                 // because the AIModel obtains a periodic ground elevation estimate.
150                 wpt->altitude  = dep->getElevation();
151                 wpt->speed = vTaxiBackward;
152                 wpt->crossat   = -10000;
153                 wpt->gear_down = true;
154                 wpt->flaps_down= true;
155                 wpt->finished  = false;
156                 wpt->on_ground = true;
157                 wpt->routeIndex = rte;
158                 waypoints.push_back(wpt);
159               }
160               // some special considerations for the last point:
161               wpt->name = string("PushBackPoint");
162               wpt->speed = vTaxi;
163               //for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) {
164               //    cerr << "Waypoint Name: " << (*i)->name << endl;
165               //}
166         } else {
167            //cerr << "Creating direct forward departure route fragment" << endl;
168            double lat2 = 0.0, lon2 = 0.0, az2 = 0.0;
169            waypoint *wpt;
170            geo_direct_wgs_84 ( 0, lat, lon, heading, 
171                                2, &lat2, &lon2, &az2 );
172            wpt = new waypoint;
173            wpt->name      = "park2";
174            wpt->latitude  = lat2;
175            wpt->longitude = lon2;
176            wpt->altitude  = dep->getElevation();
177            wpt->speed     = vTaxiReduced; 
178            wpt->crossat   = -10000;
179            wpt->gear_down = true;
180            wpt->flaps_down= true;
181            wpt->finished  = false;
182            wpt->on_ground = true;
183            wpt->routeIndex = 0;
184            waypoints.push_back(wpt); 
185
186            geo_direct_wgs_84 ( 0, lat, lon, heading, 
187                                4, &lat2, &lon2, &az2 );
188            wpt = new waypoint;
189            wpt->name      = "name";
190            wpt->latitude  = lat2;
191            wpt->longitude = lon2;
192            wpt->altitude  = dep->getElevation();
193            wpt->speed     = vTaxiReduced; 
194            wpt->crossat   = -10000;
195            wpt->gear_down = true;
196            wpt->flaps_down= true;
197            wpt->finished  = false;
198            wpt->on_ground = true;
199            wpt->routeIndex = 0;
200            waypoints.push_back(wpt);
201
202            //cerr << "Creating final push forward point for gate " << gateId << endl;
203            FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
204            FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
205            FGTaxiSegmentVectorIterator te = tn->getEndRoute();
206            if (ts == te) {
207                SG_LOG(SG_GENERAL, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
208                //exit(1);
209            }
210            tn = (*ts)->getEnd();
211            lastNodeVisited = tn->getIndex();
212            if (tn == NULL) {
213                SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
214                exit(1);
215            }
216            wpt = new waypoint;
217            wpt->name      = "PushBackPoint";
218            wpt->latitude  = tn->getLatitude();
219            wpt->longitude = tn->getLongitude();
220            wpt->altitude  = dep->getElevation();
221            wpt->speed     = vTaxiReduced; 
222            wpt->crossat   = -10000;
223            wpt->gear_down = true;
224            wpt->flaps_down= true;
225            wpt->finished  = false;
226            wpt->on_ground = true;
227            wpt->routeIndex = (*ts)->getIndex();
228            waypoints.push_back(wpt);
229
230
231         }
232
233     }
234 }
235 /*******************************************************************
236  * createPushBackFallBack
237  * This is the backup function for airports that don't have a 
238  * network yet. 
239  ******************************************************************/
240 void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
241                                     double latitude,
242                                     double longitude,
243                                     double radius,
244                                     const string& fltType,
245                                     const string& aircraftType,
246                                     const string& airline)
247 {
248   double heading;
249   double lat;
250   double lon;
251   double lat2 = 0.0;
252   double lon2 = 0.0;
253   double az2 = 0.0;
254
255   double vTaxi = ac->getPerformance()->vTaxi();
256   double vTaxiBackward = vTaxi * (-2.0/3.0);
257   double vTaxiReduced  = vTaxi * (2.0/3.0);
258
259
260
261   dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
262
263   heading += 180.0;
264   if (heading > 360)
265     heading -= 360;
266   waypoint *wpt = new waypoint;
267   wpt->name      = "park";
268   wpt->latitude  = lat;
269   wpt->longitude = lon;
270   wpt->altitude  = dep->getElevation();
271   wpt->speed     = vTaxiBackward; 
272   wpt->crossat   = -10000;
273   wpt->gear_down = true;
274   wpt->flaps_down= true;
275   wpt->finished  = false;
276   wpt->on_ground = true;
277
278   waypoints.push_back(wpt); 
279
280   geo_direct_wgs_84 ( 0, lat, lon, heading, 
281                       10, 
282                       &lat2, &lon2, &az2 );
283   wpt = new waypoint;
284   wpt->name      = "park2";
285   wpt->latitude  = lat2;
286   wpt->longitude = lon2;
287   wpt->altitude  = dep->getElevation();
288   wpt->speed     = vTaxiBackward; 
289   wpt->crossat   = -10000;
290   wpt->gear_down = true;
291   wpt->flaps_down= true;
292   wpt->finished  = false;
293   wpt->on_ground = true;
294   wpt->routeIndex = 0;
295   waypoints.push_back(wpt); 
296   geo_direct_wgs_84 ( 0, lat, lon, heading, 
297                       2.2*radius,           
298                       &lat2, &lon2, &az2 );
299   wpt = new waypoint;
300   wpt->name      = "taxiStart";
301   wpt->latitude  = lat2;
302   wpt->longitude = lon2;
303   wpt->altitude  = dep->getElevation();
304   wpt->speed     = vTaxiReduced; 
305   wpt->crossat   = -10000;
306   wpt->gear_down = true;
307   wpt->flaps_down= true;
308   wpt->finished  = false;
309   wpt->on_ground = true;
310   wpt->routeIndex = 0;
311   waypoints.push_back(wpt);
312 }