]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIFlightPlanCreateCruise.cxx
Experimental navinfo() Nasal extension function
[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
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include <fstream>
27 #include <iostream>
28 #include <simgear/route/waypoint.hxx>
29
30 #include <Airports/simple.hxx>
31 #include <Airports/runways.hxx>
32 #include <Airports/dynamics.hxx>
33
34 #include <Environment/environment_mgr.hxx>
35 #include <Environment/environment.hxx>
36
37 #include "AIFlightPlan.hxx"
38 #include "AIAircraft.hxx"
39 #include "performancedata.hxx"
40
41 using std::iostream;
42
43 /*
44 void FGAIFlightPlan::evaluateRoutePart(double deplat,
45                                        double deplon,
46                                        double arrlat,
47                                        double arrlon)
48 {
49   // First do a prescan of all the waypoints that are within a reasonable distance of the
50   // ideal route.
51   intVec nodes;
52   int tmpNode, prevNode;
53
54   SGGeoc dep(SGGeoc::fromDegM(deplon, deplat, 100.0));
55   SGGeoc arr(SGGeoc::fromDegM(arrlon, arrlat, 100.0));
56   
57   SGVec3d a = SGVec3d::fromGeoc(dep);
58   SGVec3d nb = normalize(SGVec3d::fromGeoc(arr));
59   SGVec3d na = normalize(a);
60   
61   SGVec3d _cross = cross(nb, na);
62
63   double angle = acos(dot(na, nb));
64   const double angleStep = 0.05 * SG_DEGREES_TO_RADIANS;
65   tmpNode = 0;
66   for (double ang = 0.0; ang < angle; ang += angleStep)
67   {  
68       SGQuatd q = SGQuatd::fromAngleAxis(ang, _cross);
69       SGGeod geod = SGGeod::fromCart(q.transform(a));
70
71       prevNode = tmpNode;
72       tmpNode = globals->get_airwaynet()->findNearestNode(geod);
73
74       FGNode* node = globals->get_airwaynet()->findNode(tmpNode);
75     
76       if ((tmpNode != prevNode) && (SGGeodesy::distanceM(geod, node->getPosition()) < 25000)) {
77         nodes.push_back(tmpNode);
78       }
79     }
80
81     intVecIterator i = nodes.begin();
82     intVecIterator j = nodes.end();
83     while (i != nodes.end())
84     {
85                 j = nodes.end();
86                 while (j != i)
87                 {
88                         j--;
89                         FGAirRoute routePart = globals->get_airwaynet()->findShortestRoute(*i, *j);
90                         if (!(routePart.empty()))
91                         {
92                                 airRoute.add(routePart);
93                                 i = j;
94                                 break;
95                         }
96                 }
97                 i++;
98         }
99 }
100
101 */
102 /*
103 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
104                                   FGAirport *arr, double latitude,
105                                   double longitude, double speed, double alt)
106 {
107   bool useInitialWayPoint = true;
108   bool useCurrentWayPoint = false;
109   double heading;
110   double lat, lon, az;
111    double lat2, lon2, az2;
112    double azimuth;
113   waypoint *wpt;
114   waypoint *init_waypoint;
115     intVec ids;
116     char buffer[32];
117     SGPath routefile = globals->get_fg_root();
118     init_waypoint = new waypoint;
119     init_waypoint->name      = "Initial waypoint";
120     init_waypoint->latitude  = latitude;
121     init_waypoint->longitude = longitude;;
122     //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
123     init_waypoint->altitude  = alt;
124     init_waypoint->speed     = 450; //speed;
125     init_waypoint->crossat   = -10000;
126     init_waypoint->gear_down = false;
127     init_waypoint->flaps_down= false;
128     init_waypoint->finished  = false;
129     init_waypoint->on_ground = false;
130     waypoints.push_back(init_waypoint);
131     routefile.append("Data/AI/FlightPlans");
132     snprintf(buffer, 32, "%s-%s.txt",
133              dep->getId().c_str(),
134              arr->getId().c_str());
135     routefile.append(buffer);
136     cerr << "trying to read " << routefile.c_str()<< endl;
137     //exit(1);
138     if (routefile.exists())
139       {
140          sg_gzifstream in( routefile.str() );
141         do {
142           in >> route;
143         } while (!(in.eof()));
144       }
145     else {
146     //int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, lon2);
147     //int startId = globals->get_airwaynet()->findNearestNode(dep->getLatitude(), dep->getLongitude());
148     //int endId   = globals->get_airwaynet()->findNearestNode(arr->getLatitude(), arr->getLongitude());
149     //FGAirRoute route;
150     evaluateRoutePart(dep->getLatitude(), dep->getLongitude(),
151                       arr->getLatitude(), arr->getLongitude());
152     //exit(1);
153     }
154     route.first();
155     int node;
156     if (route.empty()) {
157       // if no route could be found, create a direct gps route...
158       cerr << "still no route found from " << dep->getName() << " to << " << arr->getName() <<endl;
159
160       //exit(1);
161     } else {
162       while(route.next(&node))
163         {
164           FGNode *fn = globals->get_airwaynet()->findNode(node);
165           //cerr << "Checking status of each waypoint: " << fn->getIdent();
166
167           SGWayPoint first(init_waypoint->longitude,
168                            init_waypoint->latitude,
169                            alt);
170           SGWayPoint curr (fn->getLongitude(),
171                            fn->getLatitude(),
172                            alt);
173           SGWayPoint arr  (arr->getLongitude(),
174                            arr->getLatitude(),
175                            alt);
176           
177           double crse, crsDiff;
178           double dist;
179           first.CourseAndDistance(arr,   &course, &distance);
180           first.CourseAndDistance(curr, &crse, &dist);
181
182           dist *= SG_METER_TO_NM;
183
184           // We're only interested in the absolute value of crsDiff
185           // wich should fall in the 0-180 deg range.
186           crsDiff = fabs(crse-course);
187           if (crsDiff > 180)
188             crsDiff = 360-crsDiff;
189           // These are the three conditions that we consider including
190           // in our flight plan:
191           // 1) current waypoint is less then 100 miles away OR
192           // 2) curren waypoint is ahead of us, at any distance
193           //cerr << " Distance : " << dist << " : Course diff " << crsDiff 
194           //     << " crs to dest : " << course
195           //     << " crs to wpt  : " << crse;
196           if ((dist > 20.0) && (crsDiff > 90.0))
197             {
198               //useWpt = false;
199               // Once we start including waypoints, we have to continue, even though
200               // one of the following way point would suffice.
201               // so once is the useWpt flag is set to true, we cannot reset it to false.
202               //cerr << " discarding " << endl;
203               //   << ": Course difference = " << crsDiff
204               //  << "Course = " << course
205               // << "crse   = " << crse << endl;
206             }
207           else {
208             //i = ids.end()-1;
209             //cerr << " accepting " << endl;
210
211             //ids.pop_back();
212             wpt = new waypoint;
213             wpt->name      = "Airway"; // fixme: should be the name of the waypoint
214             wpt->latitude  = fn->getLatitude();
215             wpt->longitude = fn->getLongitude();
216             //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
217             wpt->altitude  = alt;
218             wpt->speed     = 450; //speed;
219             wpt->crossat   = -10000;
220             wpt->gear_down = false;
221             wpt->flaps_down= false;
222             wpt->finished  = false;
223             wpt->on_ground = false;
224             waypoints.push_back(wpt);
225           }
226
227           if (!(routefile.exists()))
228             {
229               route.first();
230               fstream outf( routefile.c_str(), fstream::out );
231               while (route.next(&node))
232                 outf << node << endl;
233             }
234         }
235     }
236     arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
237     if (!(globals->get_runways()->search(arr->getId(),
238                                          activeRunway,
239                                          &rwy)))
240   {
241     cout << "Failed to find runway for " << arr->getId() << endl;
242     // Hmm, how do we handle a potential error like this?
243     exit(1);
244   }
245     //string test;
246     //arr->getActiveRunway(string("com"), 1, test);
247     //exit(1);
248
249     //cerr << "Altitude = " << alt << endl;
250     //cerr << "Done" << endl;
251     //if (arr->getId() == "EHAM")
252     //  {
253     //    cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
254     //  }
255     heading = rwy._heading;
256     azimuth = heading + 180.0;
257     while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
258
259
260     // Note: This places us at the location of the active
261     // runway during initial cruise. This needs to be
262     // fixed later.
263     geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
264                         110000,
265                         &lat2, &lon2, &az2 );
266     wpt = new waypoint;
267     wpt->name      = "BOD"; //wpt_node->getStringValue("name", "END");
268     wpt->latitude  = lat2;
269     wpt->longitude = lon2;
270     wpt->altitude  = alt;
271     wpt->speed     = speed;
272     wpt->crossat   = alt;
273     wpt->gear_down = false;
274     wpt->flaps_down= false;
275     wpt->finished  = false;
276     wpt->on_ground = false;
277     waypoints.push_back(wpt);
278 }
279 */
280
281
282 /*******************************************************************
283  * CreateCruise
284  * initialize the Aircraft at the parking location
285  *
286  * Note that this is the original version that does not 
287  * do any dynamic route computation.
288  ******************************************************************/
289 void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
290                                   FGAirport *arr, double latitude, 
291                                   double longitude, double speed, 
292                                   double alt, const string& fltType)
293 {
294   double vCruise = ac->getPerformance()->vCruise();
295   waypoint *wpt;
296   wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, vCruise);
297   waypoints.push_back(wpt); 
298   
299   string rwyClass = getRunwayClassFromTrafficType(fltType);
300   double heading = ac->getTrafficRef()->getCourse();
301   arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
302   rwy = arr->getRunwayByIdent(activeRunway);
303   // begin descent 110km out
304   SGGeod beginDescentPoint     = rwy->pointOnCenterline(0);
305   SGGeod secondaryDescentPoint = rwy->pointOnCenterline(-10000);
306   
307   wpt = createInAir(ac, "BOD", beginDescentPoint,  alt, vCruise);
308   waypoints.push_back(wpt); 
309   wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise);
310   waypoints.push_back(wpt); 
311 }