1 // save.cxx -- class to save and restore a flight.
3 // Written by Curtis Olson, started November 1999.
5 // Copyright (C) 1999 David Megginson - david@megginson.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 - autopilot is working (even with GPS)
30 - use a separate options object so that we can roll back on error
31 - use proper FGFS logging
32 - add view direction, and other stuff
41 #include <simgear/fg_types.hxx>
42 #include <simgear/constants.h>
44 #include <Aircraft/aircraft.hxx>
45 #include <Controls/controls.hxx>
46 #include <Autopilot/autopilot.hxx>
47 #include <Time/fg_time.hxx>
48 #ifndef FG_OLD_WEATHER
49 # include <WeatherCM/FGLocalWeatherDatabase.h>
51 # include <Weather/weather.hxx>
54 #include "options.hxx"
56 #include "fg_init.hxx"
58 FG_USING_NAMESPACE(std);
60 // FIXME: these are not part of the
61 // published interface!!!
62 extern fgAPDataPtr APDataGlobal;
63 extern void fgAPAltitudeSet (double new_altitude);
64 extern void fgAPHeadingSet (double new_heading);
66 #define SAVE(name, value) { output << name << ": " << value << endl; }
69 * Save the current state of the simulator to a stream.
72 fgSaveFlight (ostream &output)
75 const FGInterface * f = current_aircraft.fdm_state;
76 struct tm *t = FGTime::cur_time_params->getGmt();
78 output << "#!fgfs" << endl;
83 SAVE("flight-model", current_options.get_flight_model());
84 SAVE("time", mktime(t));
85 SAVE("hud", current_options.get_hud_status());
86 SAVE("panel", current_options.get_panel_status());
91 SAVE("latitude", (f->get_Latitude() * RAD_TO_DEG));
92 SAVE("longitude", (f->get_Longitude() * RAD_TO_DEG));
93 SAVE("altitude", f->get_Altitude());
98 SAVE("heading", (f->get_Psi() * RAD_TO_DEG));
99 SAVE("pitch", (f->get_Theta() * RAD_TO_DEG));
100 SAVE("roll", (f->get_Phi() * RAD_TO_DEG));
105 SAVE("speed-north", f->get_V_north());
106 SAVE("speed-east", f->get_V_east());
107 SAVE("speed-down", f->get_V_down());
112 SAVE("elevator", controls.get_elevator());
113 SAVE("aileron", controls.get_aileron());
114 SAVE("rudder", controls.get_rudder());
115 // FIXME: save each throttle separately
116 SAVE("throttle", controls.get_throttle(0));
119 // Secondary controls
121 SAVE("elevator-trim", controls.get_elevator_trim());
122 SAVE("flaps", controls.get_flaps());
123 // FIXME: save each brake separately
124 SAVE("brake", controls.get_brake(0));
129 if (current_options.get_airport_id().length() > 0) {
130 SAVE("target-airport", current_options.get_airport_id());
132 SAVE("autopilot-altitude-lock", fgAPAltitudeEnabled());
133 SAVE("autopilot-altitude", fgAPget_TargetAltitude() * METER_TO_FEET);
134 SAVE("autopilot-heading-lock", fgAPHeadingEnabled());
135 SAVE("autopilot-heading", fgAPget_TargetHeading());
136 SAVE("autopilot-gps-lock", fgAPWayPointEnabled());
137 SAVE("autopilot-gps-lat", fgAPget_TargetLatitude());
138 SAVE("autopilot-gps-lon", fgAPget_TargetLongitude());
143 #ifndef FG_OLD_WEATHER
144 SAVE("visibility", WeatherDatabase->getWeatherVisibility());
146 SAVE("visibility", current_weather.get_visibility());
154 * Restore the current state of the simulator from a stream.
157 fgLoadFlight (istream &input)
159 FGInterface * f = current_aircraft.fdm_state;
164 double elevator = controls.get_elevator();
165 double aileron = controls.get_aileron();
166 double rudder = controls.get_rudder();
167 double throttle = controls.get_throttle(0);
168 double elevator_trim = controls.get_elevator_trim();
169 double flaps = controls.get_flaps();
170 double brake = controls.get_brake(FGControls::ALL_WHEELS);
172 bool ap_heading_lock = false;
173 double ap_heading = 0;
174 bool ap_altitude_lock = false;
175 double ap_altitude = 0;
176 bool ap_gps_lock = false;
177 double ap_gps_lat = 0;
178 double ap_gps_lon = 0;
180 string airport_id = current_options.get_airport_id();
181 current_options.set_airport_id("");
182 current_options.set_time_offset(0);
183 current_options.set_time_offset_type(fgOPTIONS::FG_TIME_GMT_OFFSET);
185 if (!input.good() || input.eof()) {
186 cout << "Stream is no good!\n";
191 if (text != "#!fgfs") {
192 printf("Bad save file format!\n");
197 while (input.good() && !input.eof()) {
204 if (text == "flight-model:") {
206 cout << "flight model is " << i << endl;
207 current_options.set_flight_model(i);
210 else if (text == "time:") {
212 cout << "saved time is " << i << endl;
213 current_options.set_time_offset(i);
214 current_options.set_time_offset_type(fgOPTIONS::FG_TIME_GMT_ABSOLUTE);
215 FGTime::cur_time_params->init(*cur_fdm_state);
216 FGTime::cur_time_params->update(*cur_fdm_state);
219 else if (text == "hud:") {
221 cout << "hud status is " << i << endl;
222 current_options.set_hud_status(i);
225 else if (text == "panel:") {
227 cout << "panel status is " << i << endl;
228 if (current_options.get_panel_status() != i) {
229 current_options.toggle_panel();
237 else if (text == "latitude:") {
239 cout << "latitude is " << n << endl;
240 current_options.set_lat(n);
241 } else if (text == "longitude:") {
243 cout << "longitude is " << n << endl;
244 current_options.set_lon(n);
245 } else if (text == "altitude:") {
247 cout << "altitude is " << n << endl;
248 current_options.set_altitude(n * FEET_TO_METER);
255 else if (text == "heading:") {
257 cout << "heading is " << n << endl;
258 current_options.set_heading(n);
259 } else if (text == "pitch:") {
261 cout << "pitch is " << n << endl;
262 current_options.set_pitch(n);
263 } else if (text == "roll:") {
265 cout << "roll is " << n << endl;
266 current_options.set_roll(n);
273 else if (text == "speed-north:") {
275 cout << "speed north is " << n << endl;
276 current_options.set_uBody(n);
277 } else if (text == "speed-east:") {
279 cout << "speed east is " << n << endl;
280 current_options.set_vBody(n);
281 } else if (text == "speed-down:") {
283 cout << "speed down is " << n << endl;
284 current_options.set_wBody(n);
291 else if (text == "elevator:") {
293 cout << "elevator is " << elevator << endl;
296 else if (text == "aileron:") {
298 cout << "aileron is " << aileron << endl;
301 else if (text == "rudder:") {
303 cout << "rudder is " << rudder << endl;
306 // FIXME: assumes single engine
307 else if (text == "throttle:") {
309 cout << "throttle is " << throttle << endl;
313 // Secondary controls
315 else if (text == "elevator-trim:") {
316 input >> elevator_trim;
317 cout << "elevator trim is " << elevator_trim << endl;
320 else if (text == "flaps:") {
322 cout << "flaps are " << flaps << endl;
325 else if (text == "brake:") {
327 cout << "brake is " << brake << endl;
334 else if (text == "target-airport:") {
336 cout << "target airport is " << airport_id << endl;
339 else if (text == "autopilot-altitude-lock:") {
340 input >> ap_altitude_lock;
341 cout << "autopilot altitude lock is " << ap_altitude_lock << endl;
344 else if (text == "autopilot-altitude:") {
345 input >> ap_altitude;
346 cout << "autopilot altitude is " << ap_altitude << endl;
349 else if (text == "autopilot-heading-lock:") {
350 input >> ap_heading_lock;
351 cout << "autopilot heading lock is " << ap_heading_lock << endl;
354 else if (text == "autopilot-heading:") {
356 cout << "autopilot heading is " << ap_heading << endl;
359 else if (text == "autopilot-gps-lock:") {
360 input >> ap_gps_lock;
361 cout << "autopilot GPS lock is " << ap_gps_lock << endl;
364 else if (text == "autopilot-gps-lat:") {
368 else if (text == "autopilot-gps-lon:") {
376 else if (text == "visibility:") {
378 cout << "visibility is " << n << endl;
380 #ifndef FG_OLD_WEATHER
381 WeatherDatabase->setWeatherVisibility(n);
383 current_weather.set_visibility(n);
388 // Don't die if we don't recognize something
392 cerr << "Skipping unknown field: " << text << endl;
397 fgReInitSubsystems();
399 // Set airport and controls after the
401 current_options.set_airport_id(airport_id);
403 // The controls have to be set after
405 controls.set_elevator(elevator);
406 controls.set_aileron(aileron);
407 controls.set_rudder(rudder);
408 controls.set_throttle(FGControls::ALL_ENGINES, throttle);
409 controls.set_elevator_trim(elevator_trim);
410 controls.set_flaps(flaps);
411 controls.set_brake(FGControls::ALL_WHEELS, brake);
413 // Ditto for the autopilot.
414 // FIXME: shouldn't have to use
416 APDataGlobal->heading_hold = ap_heading_lock;
417 APDataGlobal->altitude_hold = ap_altitude_lock;
418 fgAPHeadingSet(ap_heading);
419 fgAPAltitudeSet(ap_altitude);
420 // GPS overrides heading
421 APDataGlobal->waypoint_hold = ap_gps_lock;
422 APDataGlobal->TargetLatitude = ap_gps_lat;
423 APDataGlobal->TargetLongitude = ap_gps_lon;