1
2 #include <fstream>
3
4 #include <simgear/misc/sg_path.hxx>
5 #include <simgear/io/iostreams/sgstream.hxx>
6 #include <simgear/structure/exception.hxx>
7
8 #include <Main/fg_init.hxx>
9 #include <Main/fg_props.hxx>
10
11 #include <Instrumentation/gps.hxx>
12 #include <Autopilot/route_mgr.hxx>
13 #include <Environment/environment_mgr.hxx>
14 #include <Navaids/airways.hxx>
15 #include <Navaids/waypoint.hxx>
16 #include <Navaids/procedure.hxx>
17
18 #include "test_suite/helpers/globals.hxx"
19 #include "test_suite/helpers/NavDataCache.hxx"
20
21 #include "testgps.hxx"
22
23
24 using std::string;
25 using namespace flightgear;
26
27 char *homedir = ::getenv( "HOME" );
28 char *hostname = ::getenv( "HOSTNAME" );
29 bool free_hostname = false;
30
testSetPosition(const SGGeod & aPos)31 void testSetPosition(const SGGeod& aPos)
32 {
33 fgSetDouble("/position/longitude-deg", aPos.getLongitudeDeg());
34 fgSetDouble("/position/latitude-deg", aPos.getLatitudeDeg());
35 fgSetDouble("/position/altitude-ft", aPos.getElevationFt());
36 }
37
printScratch(SGPropertyNode * scratch)38 void printScratch(SGPropertyNode* scratch)
39 {
40 if (!scratch->getBoolValue("valid", false)) {
41 SG_LOG(SG_GENERAL, SG_ALERT, "Scratch is invalid.");
42 return;
43 }
44
45 SG_LOG(SG_GENERAL, SG_ALERT, "Scratch:" <<
46 scratch->getStringValue("ident") << "/" << scratch->getStringValue("name"));
47
48 SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("longitude-deg")
49 << " " << scratch->getDoubleValue("latitude-deg") << " @ " << scratch->getDoubleValue("altitude-ft"));
50
51 SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("true-bearing-deg") <<
52 " (" << scratch->getDoubleValue("mag-bearing-deg") << " magnetic) " << scratch->getDoubleValue("distance-nm"));
53
54 if (scratch->hasChild("result-index")) {
55 SG_LOG(SG_GENERAL, SG_ALERT, "\tresult-index:" << scratch->getIntValue("result-index"));
56 }
57
58 if (scratch->hasChild("route-index")) {
59 SG_LOG(SG_GENERAL, SG_ALERT, "\troute-index:" << scratch->getIntValue("route-index"));
60 }
61 }
62
printRoute(const WayptVec & aRoute)63 void printRoute(const WayptVec& aRoute)
64 {
65 SG_LOG(SG_GENERAL, SG_INFO, "route size=" << aRoute.size());
66 for (unsigned int r=0; r<aRoute.size();++r) {
67 Waypt* w = aRoute[r];
68 SG_LOG(SG_GENERAL, SG_ALERT, "\t" << r << ": " << w->ident() << " "
69 << w->owner()->ident());
70 }
71 }
72
createDummyRoute(FGRouteMgr * rm)73 void createDummyRoute(FGRouteMgr* rm)
74 {
75 SGPropertyNode* rmInput = fgGetNode("/autopilot/route-manager/input", true);
76 rmInput->setStringValue("UW");
77 rmInput->setStringValue("TLA/347/13");
78 rmInput->setStringValue("TLA");
79 rmInput->setStringValue("HAVEN");
80 rmInput->setStringValue("NEW/305/29");
81 rmInput->setStringValue("NEW");
82 rmInput->setStringValue("OTR");
83 }
84
85
setUp()86 void GPSTests::setUp()
87 {
88 fgtest::initTestGlobals("GPS");
89 fgtest::initNavDataCache();
90 }
91
92
tearDown()93 void GPSTests::tearDown()
94 {
95 fgtest::shutdownTestGlobals();
96 }
97
98
testGPS()99 void GPSTests::testGPS()
100 {
101 fgSetDouble("/environment/magnetic-variation-deg", 0.0);
102
103 Airway::load();
104
105 SG_LOG(SG_GENERAL, SG_ALERT, "hello world!");
106
107 const FGAirport* egph = fgFindAirportID("EGPH");
108 SG_LOG(SG_GENERAL, SG_ALERT, "egph: cart location:" << egph->cart());
109
110 FGAirport::AirportFilter af;
111 FGPositionedList l = FGPositioned::findClosestN(egph->geod(), 20, 2000.0, &af);
112 for (unsigned int i=0; i<l.size(); ++i) {
113 SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
114 }
115
116 //l = FGPositioned::findWithinRange(egph->geod(), 500.0, &af);
117 //for (unsigned int i=0; i<l.size(); ++i) {
118 // SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
119 //}
120
121
122 FGRouteMgr* rm = new FGRouteMgr;
123 globals->add_subsystem( "route-manager", rm );
124
125 // FGEnvironmentMgr* envMgr = new FGEnvironmentMgr;
126 // globals->add_subsystem("environment", envMgr);
127 // envMgr->init();
128
129 fgSetBool("/sim/realism/simple-gps", true);
130
131 // _realismSimpleGps
132
133 SGPropertyNode* nd = fgGetNode("/instrumentation/gps", true);
134 GPS* gps = new GPS(nd);
135 globals->add_subsystem("gps", gps);
136
137 const FGAirport* egph = fgFindAirportID("EGPH");
138 testSetPosition(egph->geod());
139
140 // startup the route manager
141 rm->init();
142
143 nd->setBoolValue("serviceable", true);
144 fgSetBool("/systems/electrical/outputs/gps", true);
145
146 gps->init();
147 SGPropertyNode* scratch = nd->getChild("scratch", 0, true);
148 SGPropertyNode* wp = nd->getChild("wp", 0, true);
149 SGPropertyNode* wp1 = wp->getChild("wp", 1, true);
150
151 // update a few times
152 gps->update(0.05);
153 gps->update(0.05);
154 gps->update(0.05);
155
156 scratch->setStringValue("query", "TL");
157 scratch->setStringValue("type", "Vor");
158 scratch->setBoolValue("exact", false);
159 nd->setStringValue("command", "search");
160 printScratch(scratch);
161
162 nd->setStringValue("command", "next");
163 printScratch(scratch);
164
165 nd->setStringValue("command", "next");
166 printScratch(scratch);
167
168 // alphanumeric sort, partial matching
169 nd->setDoubleValue("config/min-runway-length-ft", 5000.0);
170 scratch->setBoolValue("exact", false);
171 scratch->setBoolValue("order-by-distance", false);
172 scratch->setStringValue("query", "KS");
173 scratch->setStringValue("type", "apt");
174
175 nd->setStringValue("command", "search");
176 printScratch(scratch);
177
178 nd->setStringValue("command", "next");
179 printScratch(scratch);
180
181 nd->setStringValue("command", "next");
182 printScratch(scratch);
183
184 // alphanumeric sort, explicit matching
185 scratch->setBoolValue("exact", true);
186 scratch->setBoolValue("order-by-distance", true);
187 scratch->setStringValue("type", "vor");
188 scratch->setStringValue("query", "DCS");
189
190 nd->setStringValue("command", "search");
191 printScratch(scratch);
192
193 nd->setStringValue("command", "next");
194 printScratch(scratch);
195
196 // search on totally missing
197 scratch->setBoolValue("exact", true);
198 scratch->setBoolValue("order-by-distance", true);
199 scratch->setStringValue("query", "FOFOFOFOF");
200 nd->setStringValue("command", "search");
201 printScratch(scratch);
202
203 // nearest
204 scratch->setStringValue("type", "apt");
205 scratch->setIntValue("max-results", 10);
206 nd->setStringValue("command", "nearest");
207 printScratch(scratch);
208
209 nd->setStringValue("command", "next");
210 printScratch(scratch);
211
212 nd->setStringValue("command", "next");
213 printScratch(scratch);
214
215 // direct to
216 nd->setStringValue("command", "direct");
217 SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
218 << wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
219 << " " << wp1->getDoubleValue("latitude-deg"));
220
221 // OBS mode
222 scratch->setStringValue("query", "UW");
223 scratch->setBoolValue("order-by-distance", true);
224 nd->setStringValue("command", "search");
225 printScratch(scratch);
226
227 nd->setStringValue("command", "obs");
228 SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
229 << wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
230 << " " << wp1->getDoubleValue("latitude-deg"));
231
232 // load route waypoints
233 createDummyRoute(rm);
234
235 scratch->setIntValue("route-index", 5);
236 nd->setStringValue("command", "load-route-wpt");
237 printScratch(scratch);
238
239 nd->setStringValue("command", "next");
240 printScratch(scratch);
241
242 nd->setStringValue("command", "next");
243 printScratch(scratch);
244
245 scratch->setIntValue("route-index", 2);
246 nd->setStringValue("command", "load-route-wpt");
247 nd->setStringValue("command", "direct");
248 SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
249 << wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
250 << " " << wp1->getDoubleValue("latitude-deg"));
251
252 // route editing
253 SGGeod pos = egph->geod();
254 scratch->setStringValue("ident", "FOOBAR");
255 scratch->setDoubleValue("longitude-deg", pos.getLongitudeDeg());
256 scratch->setDoubleValue("latitude-deg", pos.getLatitudeDeg());
257 nd->setStringValue("command", "define-user-wpt");
258 printScratch(scratch);
259
260 // airways
261 FGPositioned::TypeFilter vorFilt(FGPositioned::VOR);
262 FGPositionedRef tla = FGPositioned::findClosestWithIdent("TLA", pos, &vorFilt);
263 FGPositionedRef big = FGPositioned::findClosestWithIdent("BIG", pos, &vorFilt);
264 FGPositionedRef pol = FGPositioned::findClosestWithIdent("POL", pos, &vorFilt);
265
266 const FGAirport* eddm = fgFindAirportID("EDDM");
267 FGPositionedRef mun = FGPositioned::findClosestWithIdent("MUN",
268 eddm->geod(), &vorFilt);
269
270 const FGAirport* ksfo = fgFindAirportID("KSFO");
271 FGPositionedRef sfo = FGPositioned::findClosestWithIdent("SFO",
272 ksfo->geod(), &vorFilt);
273
274
275 WayptRef awy1 = new NavaidWaypoint(tla, NULL);
276 WayptRef awy2 = new NavaidWaypoint(big, NULL);
277 WayptRef awy3 = new NavaidWaypoint(pol, NULL);
278 WayptRef awy4 = new NavaidWaypoint(mun, NULL);
279 WayptRef awy5 = new NavaidWaypoint(sfo, NULL);
280
281 WayptRef awy6 = new NavaidWaypoint(
282 (FGPositioned*) fgFindAirportID("KJFK"), NULL);
283
284 SGPath p("/Users/jmt/Desktop/airways.kml");
285 sg_ofstream f;
286 f.open(p, fstream::out | fstream::trunc);
287
288 // pre-amble
289 f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
290 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
291 "<Document>\n";
292
293 WayptVec route;
294 Airway::highLevel()->route(awy1, awy3, route);
295 Route::dumpRouteToLineString("egph-egcc", route, f);
296
297 Airway::lowLevel()->route(awy1, awy2, route);
298 Route::dumpRouteToLineString("egph-big", route, f);
299
300 Airway::lowLevel()->route(awy2, awy4, route);
301 Route::dumpRouteToLineString("big-mun", route, f);
302
303 Airway::highLevel()->route(awy4, awy5, route);
304 Route::dumpRouteToLineString("mun-sfo", route, f);
305
306 Airway::lowLevel()->route(awy5, awy6, route);
307 Route::dumpRouteToLineString("sfo-jfk", route, f);
308
309 // post-amble
310 f << "</Document>\n"
311 "</kml>" << endl;
312 f.close();
313
314 // procedures
315 SGPath op("/Users/jmt/Desktop/procedures.kml");
316 f.open(op, fstream::out | fstream::trunc);
317
318 FGAirport* eham = (FGAirport*) fgFindAirportID("EHAM");
319 FGPositioned::TypeFilter fixFilt(FGPositioned::FIX);
320
321 WayptVec approach;
322 FGPositionedRef redfa = FGPositioned::findClosestWithIdent("REDFA",
323 eham->geod(), &fixFilt);
324 bool ok = eham->buildApproach(new NavaidWaypoint(redfa, NULL),
325 eham->getRunwayByIdent("18R"), approach);
326 if (!ok ) {
327 SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
328 }
329
330
331 FGAirport* egll = (FGAirport*) fgFindAirportID("EGLL");
332 WayptVec approach2;
333 ok = egll->buildApproach(new NavaidWaypoint(big, NULL),
334 egll->getRunwayByIdent("27R"), approach2);
335 if (!ok ) {
336 SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
337 }
338
339 // pre-amble
340 f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
341 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
342 "<Document>\n";
343
344 Route::dumpRouteToLineString("REDFA 18R", approach, f);
345 Route::dumpRouteToLineString("EGLL 27R", approach2, f);
346
347 // post-amble
348 f << "</Document>\n"
349 "</kml>" << endl;
350 f.close();
351 }
352