]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIFlightPlanCreateCruise.cxx
- Added ultra-light traffic is now a separate traffic class that can have its
[flightgear.git] / src / AIModel / AIFlightPlanCreateCruise.cxx
1 /******************************************************************************
2  * AIFlightPlanCreateCruise.cxx
3  * Written by Durk Talsma, started February, 2006.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  **************************************************************************/
21 #include <fstream>
22 #include <iostream>
23 #include "AIFlightPlan.hxx"
24 #include <simgear/math/polar3d.hxx>
25 #include <simgear/math/sg_geodesy.hxx>
26 #include <simgear/route/waypoint.hxx>
27
28 #include <Navaids/awynet.hxx>
29 #include <Airports/runways.hxx>
30
31 #include <Environment/environment_mgr.hxx>
32 #include <Environment/environment.hxx>
33
34 SG_USING_STD(iostream);
35
36 void FGAIFlightPlan::evaluateRoutePart(double deplat,
37                                        double deplon,
38                                        double arrlat,
39                                        double arrlon)
40 {
41   // First do a prescan of all the waypoints that are within a reasonable distance of the
42   // ideal route.
43   intVec nodes;
44   int tmpNode, prevNode;
45
46
47   SGWayPoint first (deplon,
48                     deplat,
49                     100);
50   SGWayPoint sec (arrlon,
51                   arrlat,
52                   100);
53   double course, distance;
54   first.CourseAndDistance(sec, &course, &distance);
55   distance *= SG_METER_TO_NM;
56
57   SGVec3d a = SGVec3d::fromGeoc(SGGeoc::fromDegM(deplon, deplat, 1));
58   SGVec3d b = SGVec3d::fromGeoc(SGGeoc::fromDegM(arrlon, arrlat, 1));
59   SGVec3d _cross = cross(b, a);
60
61   double angle = sgACos(dot(a, b));
62   tmpNode = 0;
63   for (double ang = 0.0; ang < angle; ang += 0.05)
64     {
65       sgdVec3 newPos;
66       sgdMat4 matrix;
67       //cerr << "Angle = " << ang << endl;
68       sgdMakeRotMat4(matrix, ang, _cross.sg());
69       for(int j = 0; j < 3; j++)
70         {
71           newPos[j] =0.0;
72           for (int k = 0; k<3; k++)
73             {
74               newPos[j] += matrix[j][k]*a[k];
75             }
76         }
77       //cerr << "1"<< endl;
78       //SGGeoc geoc = SGGeoc::fromCart(SGVec3d(newPos[0], newPos[1], newPos[2]));
79
80       //double midlat = geoc.getLatitudeDeg();
81       //double midlon = geoc.getLongitudeDeg();
82
83       Point3D temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
84       double midlat = temp.lat() * SG_RADIANS_TO_DEGREES;
85       double midlon = temp.lon() * SG_RADIANS_TO_DEGREES; 
86
87
88       prevNode = tmpNode;
89       tmpNode = globals->get_airwaynet()->findNearestNode(midlat, midlon);
90
91       double nodelat = globals->get_airwaynet()->findNode(tmpNode)->getLatitude  ();
92       double nodelon = globals->get_airwaynet()->findNode(tmpNode)->getLongitude ();
93       SGWayPoint curr(midlat,
94                       midlon,
95                       100);
96       SGWayPoint node(nodelat,
97                       nodelon,
98                       100);
99       curr.CourseAndDistance(node, &course, &distance);
100       if ((distance < 25000) && (tmpNode != prevNode))
101         nodes.push_back(tmpNode);
102     }
103
104     intVecIterator i = nodes.begin();
105     intVecIterator j = nodes.end();
106     while (i != nodes.end())
107     {
108                 j = nodes.end();
109                 while (j != i)
110                 {
111                         j--;
112                         FGAirRoute routePart = globals->get_airwaynet()->findShortestRoute(*i, *j);
113                         if (!(routePart.empty()))
114                         {
115                                 airRoute.add(routePart);
116                                 i = j;
117                                 break;
118                         }
119                 }
120                 i++;
121         }
122 }
123
124
125 /*
126 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
127                                   FGAirport *arr, double latitude,
128                                   double longitude, double speed, double alt)
129 {
130   bool useInitialWayPoint = true;
131   bool useCurrentWayPoint = false;
132   double heading;
133   double lat, lon, az;
134    double lat2, lon2, az2;
135    double azimuth;
136   waypoint *wpt;
137   waypoint *init_waypoint;
138     intVec ids;
139     char buffer[32];
140     SGPath routefile = globals->get_fg_root();
141     init_waypoint = new waypoint;
142     init_waypoint->name      = "Initial waypoint";
143     init_waypoint->latitude  = latitude;
144     init_waypoint->longitude = longitude;;
145     //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
146     init_waypoint->altitude  = alt;
147     init_waypoint->speed     = 450; //speed;
148     init_waypoint->crossat   = -10000;
149     init_waypoint->gear_down = false;
150     init_waypoint->flaps_down= false;
151     init_waypoint->finished  = false;
152     init_waypoint->on_ground = false;
153     waypoints.push_back(init_waypoint);
154     routefile.append("Data/AI/FlightPlans");
155     snprintf(buffer, 32, "%s-%s.txt",
156              dep->getId().c_str(),
157              arr->getId().c_str());
158     routefile.append(buffer);
159     cerr << "trying to read " << routefile.c_str()<< endl;
160     //exit(1);
161     if (routefile.exists())
162       {
163          sg_gzifstream in( routefile.str() );
164         do {
165           in >> route;
166         } while (!(in.eof()));
167       }
168     else {
169     //int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, lon2);
170     //int startId = globals->get_airwaynet()->findNearestNode(dep->getLatitude(), dep->getLongitude());
171     //int endId   = globals->get_airwaynet()->findNearestNode(arr->getLatitude(), arr->getLongitude());
172     //FGAirRoute route;
173     evaluateRoutePart(dep->getLatitude(), dep->getLongitude(),
174                       arr->getLatitude(), arr->getLongitude());
175     //exit(1);
176     }
177     route.first();
178     int node;
179     if (route.empty()) {
180       // if no route could be found, create a direct gps route...
181       cerr << "still no route found from " << dep->getName() << " to << " << arr->getName() <<endl;
182
183       //exit(1);
184     } else {
185       while(route.next(&node))
186         {
187           FGNode *fn = globals->get_airwaynet()->findNode(node);
188           //cerr << "Checking status of each waypoint: " << fn->getIdent();
189
190           SGWayPoint first(init_waypoint->longitude,
191                            init_waypoint->latitude,
192                            alt);
193           SGWayPoint curr (fn->getLongitude(),
194                            fn->getLatitude(),
195                            alt);
196           SGWayPoint arr  (arr->getLongitude(),
197                            arr->getLatitude(),
198                            alt);
199           
200           double crse, crsDiff;
201           double dist;
202           first.CourseAndDistance(arr,   &course, &distance);
203           first.CourseAndDistance(curr, &crse, &dist);
204
205           dist *= SG_METER_TO_NM;
206
207           // We're only interested in the absolute value of crsDiff
208           // wich should fall in the 0-180 deg range.
209           crsDiff = fabs(crse-course);
210           if (crsDiff > 180)
211             crsDiff = 360-crsDiff;
212           // These are the three conditions that we consider including
213           // in our flight plan:
214           // 1) current waypoint is less then 100 miles away OR
215           // 2) curren waypoint is ahead of us, at any distance
216           //cerr << " Distance : " << dist << " : Course diff " << crsDiff 
217           //     << " crs to dest : " << course
218           //     << " crs to wpt  : " << crse;
219           if ((dist > 20.0) && (crsDiff > 90.0))
220             {
221               //useWpt = false;
222               // Once we start including waypoints, we have to continue, even though
223               // one of the following way point would suffice.
224               // so once is the useWpt flag is set to true, we cannot reset it to false.
225               //cerr << " discarding " << endl;
226               //   << ": Course difference = " << crsDiff
227               //  << "Course = " << course
228               // << "crse   = " << crse << endl;
229             }
230           else {
231             //i = ids.end()-1;
232             //cerr << " accepting " << endl;
233
234             //ids.pop_back();
235             wpt = new waypoint;
236             wpt->name      = "Airway"; // fixme: should be the name of the waypoint
237             wpt->latitude  = fn->getLatitude();
238             wpt->longitude = fn->getLongitude();
239             //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
240             wpt->altitude  = alt;
241             wpt->speed     = 450; //speed;
242             wpt->crossat   = -10000;
243             wpt->gear_down = false;
244             wpt->flaps_down= false;
245             wpt->finished  = false;
246             wpt->on_ground = false;
247             waypoints.push_back(wpt);
248           }
249
250           if (!(routefile.exists()))
251             {
252               route.first();
253               fstream outf( routefile.c_str(), fstream::out );
254               while (route.next(&node))
255                 outf << node << endl;
256             }
257         }
258     }
259     arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
260     if (!(globals->get_runways()->search(arr->getId(),
261                                          activeRunway,
262                                          &rwy)))
263   {
264     cout << "Failed to find runway for " << arr->getId() << endl;
265     // Hmm, how do we handle a potential error like this?
266     exit(1);
267   }
268     //string test;
269     //arr->getActiveRunway(string("com"), 1, test);
270     //exit(1);
271
272     //cerr << "Altitude = " << alt << endl;
273     //cerr << "Done" << endl;
274     //if (arr->getId() == "EHAM")
275     //  {
276     //    cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
277     //  }
278     heading = rwy._heading;
279     azimuth = heading + 180.0;
280     while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
281
282
283     // Note: This places us at the location of the active
284     // runway during initial cruise. This needs to be
285     // fixed later.
286     geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
287                         110000,
288                         &lat2, &lon2, &az2 );
289     wpt = new waypoint;
290     wpt->name      = "BOD"; //wpt_node->getStringValue("name", "END");
291     wpt->latitude  = lat2;
292     wpt->longitude = lon2;
293     wpt->altitude  = alt;
294     wpt->speed     = speed;
295     wpt->crossat   = alt;
296     wpt->gear_down = false;
297     wpt->flaps_down= false;
298     wpt->finished  = false;
299     wpt->on_ground = false;
300     waypoints.push_back(wpt);
301 }
302 */
303
304
305 /*******************************************************************
306  * CreateCruise
307  * initialize the Aircraft at the parking location
308  *
309  * Note that this is the original version that does not 
310  * do any dynamic route computation.
311  ******************************************************************/
312 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, 
313                                   FGAirport *arr, double latitude, 
314                                   double longitude, double speed, 
315                                   double alt, const string& fltType)
316 {
317   double wind_speed;
318   double wind_heading;
319   double heading;
320   double lat, lon, az;
321   double lat2, lon2, az2;
322   double azimuth;
323   waypoint *wpt;
324
325   wpt = new waypoint;
326   wpt->name      = "Cruise"; //wpt_node->getStringValue("name", "END");
327   wpt->latitude  = latitude;
328   wpt->longitude = longitude;
329   wpt->altitude  = alt;
330   wpt->speed     = speed; 
331   wpt->crossat   = -10000;
332   wpt->gear_down = false;
333   wpt->flaps_down= false;
334   wpt->finished  = false;
335   wpt->on_ground = false;
336   wpt->routeIndex = 0;
337   waypoints.push_back(wpt); 
338   
339  
340   string rwyClass = getRunwayClassFromTrafficType(fltType);
341   arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
342   if (!(globals->get_runways()->search(arr->getId(), 
343                                        activeRunway, 
344                                        &rwy)))
345     {
346       SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
347              activeRunway << 
348              " at airport     " << arr->getId()<< " of class " << rwyClass << " (5)");
349       exit(1);
350     }
351   heading = rwy._heading;
352   azimuth = heading + 180.0;
353   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
354   
355   
356   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
357                       110000,
358                       &lat2, &lon2, &az2 );
359   wpt = new waypoint;
360   wpt->name      = "BOD";
361   wpt->latitude  = lat2;
362   wpt->longitude = lon2;
363   wpt->altitude  = alt;
364   wpt->speed     = speed; 
365   wpt->crossat   = alt;
366   wpt->gear_down = false;
367   wpt->flaps_down= false;
368   wpt->finished  = false;
369   wpt->on_ground = false;
370   wpt->routeIndex = 0;
371   waypoints.push_back(wpt); 
372 }