1 // fg_props.cxx -- support for FlightGear properties.
3 // Written by David Megginson, started 2000.
5 // Copyright (C) 2000, 2001 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.
24 # include <simgear/compiler.h>
27 #include <simgear/misc/exception.hxx>
31 #include <Autopilot/newauto.hxx>
32 #include <Aircraft/aircraft.hxx>
33 #include <Time/tmp.hxx>
34 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
35 #ifndef FG_OLD_WEATHER
36 # include <WeatherCM/FGLocalWeatherDatabase.h>
38 # include <Weather/weather.hxx>
40 #include <Objects/matlib.hxx>
45 #include "fg_props.hxx"
47 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
48 SG_USING_STD(istream);
49 SG_USING_STD(ostream);
52 static double getWindNorth ();
53 static double getWindEast ();
54 static double getWindDown ();
56 // Allow the view to be set from two axes (i.e. a joystick hat)
57 // This needs to be in FGViewer itself, somehow.
58 static double axisLong = 0.0;
59 static double axisLat = 0.0;
61 static bool winding_ccw = false; // FIXME: temporary
63 static bool fdm_data_logging = false; // FIXME: temporary
70 _set_view_from_axes ()
72 // Take no action when hat is centered
73 if ( ( axisLong < 0.01 ) &&
74 ( axisLong > -0.01 ) &&
82 /* Do all the quick and easy cases */
83 if (axisLong < 0) { // Longitudinal axis forward
84 if (axisLat == axisLong)
86 else if (axisLat == - axisLong)
88 else if (axisLat == 0)
90 } else if (axisLong > 0) { // Longitudinal axis backward
91 if (axisLat == - axisLong)
93 else if (axisLat == axisLong)
95 else if (axisLat == 0)
97 } else if (axisLong == 0) { // Longitudinal axis neutral
100 else if (axisLat > 0)
102 else return; /* And assertion failure maybe? */
105 /* Do all the difficult cases */
107 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
108 if ( viewDir < -1 ) viewDir += 360;
110 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
111 // << axisLong << " gave angle=" << viewDir );
113 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
114 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
118 ////////////////////////////////////////////////////////////////////////
119 // Default property bindings (not yet handled by any module).
120 ////////////////////////////////////////////////////////////////////////
124 * Get the pause state of the sim.
129 return globals->get_freeze();
134 * Set the pause state of the sim.
137 setFreeze (bool freeze)
139 globals->set_freeze(freeze);
143 * Return the current aircraft directory (UIUC) as a string.
153 * Set the current aircraft directory (UIUC).
156 setAircraftDir (string dir)
158 if (getAircraftDir() != dir) {
160 // needReinit(); FIXME!!
166 * Get the current view offset in degrees.
171 return (globals->get_current_view()
172 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
177 setViewOffset (double offset)
179 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
185 return (globals->get_current_view()
186 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
190 setGoalViewOffset (double offset)
192 while ( offset < 0 ) {
195 while ( offset > 360.0 ) {
198 // Snap to center if we are close
199 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
203 globals->get_current_view()
204 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
209 * Return the current Zulu time.
216 struct tm * t = globals->get_time_params()->getGmt();
217 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
218 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
219 t->tm_hour, t->tm_min, t->tm_sec);
226 * Set the current Zulu time.
229 setDateString (string date_string)
231 SGTime * st = globals->get_time_params();
232 struct tm * current_time = st->getGmt();
235 // Scan for basic ISO format
236 // YYYY-MM-DDTHH:MM:SS
237 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
238 &(new_time.tm_year), &(new_time.tm_mon),
239 &(new_time.tm_mday), &(new_time.tm_hour),
240 &(new_time.tm_min), &(new_time.tm_sec));
242 // Be pretty picky about this, so
243 // that strange things don't happen
244 // if the save file has been edited
247 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
248 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
252 // OK, it looks like we got six
253 // values, one way or another.
254 new_time.tm_year -= 1900;
255 new_time.tm_mon -= 1;
257 // Now, tell flight gear to use
258 // the new time. This was far
259 // too difficult, by the way.
261 mktime(&new_time) - mktime(current_time) + globals->get_warp();
262 double lon = current_aircraft.fdm_state->get_Longitude();
263 double lat = current_aircraft.fdm_state->get_Latitude();
264 globals->set_warp(warp);
265 st->update(lon, lat, warp);
266 fgUpdateSkyAndLightingParams();
270 * Return the GMT as a string.
277 struct tm * t = globals->get_time_params()->getGmt();
278 sprintf(buf, " %.2d:%.2d:%.2d",
279 t->tm_hour, t->tm_min, t->tm_sec);
286 * Get the texture rendering state.
291 return (material_lib.get_step() == 0);
296 * Set the texture rendering state.
299 setTextures (bool textures)
302 material_lib.set_step(0);
304 material_lib.set_step(1);
309 * Return the magnetic variation
314 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
319 * Return the magnetic dip
324 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
329 * Return the current heading in degrees.
334 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
339 * Return the current engine0 rpm
344 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
345 return current_aircraft.fdm_state->get_engine(0)->get_RPM();
353 * Return the current engine0 EGT.
358 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
359 return current_aircraft.fdm_state->get_engine(0)->get_EGT();
366 * Return the current engine0 CHT.
371 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
372 return current_aircraft.fdm_state->get_engine(0)->get_CHT();
379 * Return the current engine0 Manifold Pressure.
384 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
385 return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
393 * Return the current engine0 fuel flow
398 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
399 return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
406 * Return the fuel level in tank 1
411 return current_aircraft.fdm_state->get_Tank1Fuel();
415 setTank1Fuel ( double gals )
417 current_aircraft.fdm_state->set_Tank1Fuel( gals );
421 * Return the fuel level in tank 2
426 return current_aircraft.fdm_state->get_Tank2Fuel();
430 setTank2Fuel ( double gals )
432 current_aircraft.fdm_state->set_Tank2Fuel( gals );
437 * Get the autopilot altitude lock (true=on).
442 return (current_autopilot->get_AltitudeEnabled() &&
443 current_autopilot->get_AltitudeMode()
444 == FGAutopilot::FG_ALTITUDE_LOCK);
449 * Set the autopilot altitude lock (true=on).
452 setAPAltitudeLock (bool lock)
454 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
455 current_autopilot->set_AltitudeEnabled(lock);
460 * Get the autopilot target altitude in feet.
465 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
470 * Set the autopilot target altitude in feet.
473 setAPAltitude (double altitude)
475 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
479 * Get the autopilot altitude lock (true=on).
484 return (current_autopilot->get_AltitudeEnabled() &&
485 (current_autopilot->get_AltitudeMode()
486 == FGAutopilot::FG_ALTITUDE_GS1));
491 * Set the autopilot altitude lock (true=on).
494 setAPGSLock (bool lock)
496 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
497 current_autopilot->set_AltitudeEnabled(lock);
502 * Get the autopilot terrain lock (true=on).
507 return (current_autopilot->get_AltitudeEnabled() &&
508 (current_autopilot->get_AltitudeMode()
509 == FGAutopilot::FG_ALTITUDE_TERRAIN));
514 * Set the autopilot terrain lock (true=on).
517 setAPTerrainLock (bool lock)
519 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
520 current_autopilot->set_AltitudeEnabled(lock);
525 * Get the autopilot target altitude in feet.
530 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
535 * Set the autopilot target altitude in feet.
538 setAPClimb (double rate)
540 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
545 * Get the autopilot heading lock (true=on).
551 (current_autopilot->get_HeadingEnabled() &&
552 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
557 * Set the autopilot heading lock (true=on).
560 setAPHeadingLock (bool lock)
563 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
564 current_autopilot->set_HeadingEnabled(true);
566 current_autopilot->set_HeadingEnabled(false);
572 * Get the autopilot heading bug in degrees.
577 return current_autopilot->get_DGTargetHeading();
582 * Set the autopilot heading bug in degrees.
585 setAPHeadingBug (double heading)
587 current_autopilot->set_DGTargetHeading( heading );
592 * Get the autopilot wing leveler lock (true=on).
598 (current_autopilot->get_HeadingEnabled() &&
599 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
604 * Set the autopilot wing leveler lock (true=on).
607 setAPWingLeveler (bool lock)
610 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
611 current_autopilot->set_HeadingEnabled(true);
613 current_autopilot->set_HeadingEnabled(false);
618 * Return true if the autopilot is locked to NAV1.
624 (current_autopilot->get_HeadingEnabled() &&
625 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
630 * Set the autopilot NAV1 lock.
633 setAPNAV1Lock (bool lock)
636 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
637 current_autopilot->set_HeadingEnabled(true);
638 } else if (current_autopilot->get_HeadingMode() ==
639 FGAutopilot::FG_HEADING_NAV1) {
640 current_autopilot->set_HeadingEnabled(false);
645 * Get the autopilot autothrottle lock.
648 getAPAutoThrottleLock ()
650 return current_autopilot->get_AutoThrottleEnabled();
655 * Set the autothrottle lock.
658 setAPAutoThrottleLock (bool lock)
660 current_autopilot->set_AutoThrottleEnabled(lock);
666 getAPRudderControl ()
668 if (getAPHeadingLock())
669 return current_autopilot->get_TargetHeading();
671 return controls.get_rudder();
676 setAPRudderControl (double value)
678 if (getAPHeadingLock()) {
679 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
680 value -= current_autopilot->get_TargetHeading();
681 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
683 controls.set_rudder(value);
689 getAPElevatorControl ()
691 if (getAPAltitudeLock())
692 return current_autopilot->get_TargetAltitude();
694 return controls.get_elevator();
699 setAPElevatorControl (double value)
701 if (getAPAltitudeLock()) {
702 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
703 value -= current_autopilot->get_TargetAltitude();
704 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
706 controls.set_elevator(value);
712 getAPThrottleControl ()
714 if (getAPAutoThrottleLock())
715 return 0.0; // always resets
717 return controls.get_throttle(0);
722 setAPThrottleControl (double value)
724 if (getAPAutoThrottleLock())
725 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
727 controls.set_throttle(0, value);
732 * Get the current visibility (meters).
737 #ifndef FG_OLD_WEATHER
738 return WeatherDatabase->getWeatherVisibility();
740 return current_weather.get_visibility();
746 * Set the current visibility (meters).
749 setVisibility (double visibility)
751 #ifndef FG_OLD_WEATHER
752 WeatherDatabase->setWeatherVisibility(visibility);
754 current_weather.set_visibility(visibility);
759 * Get the current wind north velocity (feet/second).
764 return current_aircraft.fdm_state->get_V_north_airmass();
769 * Set the current wind north velocity (feet/second).
772 setWindNorth (double speed)
774 current_aircraft.fdm_state
775 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
780 * Get the current wind east velocity (feet/second).
785 return current_aircraft.fdm_state->get_V_east_airmass();
790 * Set the current wind east velocity (feet/second).
793 setWindEast (double speed)
795 cout << "Set wind-east to " << speed << endl;
796 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
803 * Get the current wind down velocity (feet/second).
808 return current_aircraft.fdm_state->get_V_down_airmass();
813 * Set the current wind down velocity (feet/second).
816 setWindDown (double speed)
818 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
826 return globals->get_current_view()->get_fov();
832 globals->get_current_view()->set_fov( fov );
838 return globals->get_warp();
844 globals->set_warp(warp);
850 return globals->get_warp_delta();
854 setWarpDelta (long delta)
856 globals->set_warp_delta(delta);
860 setViewAxisLong (double axis)
866 setViewAxisLat (double axis)
878 setWindingCCW (bool state)
882 glFrontFace ( GL_CCW );
884 glFrontFace ( GL_CW );
890 #if defined(FX) && !defined(WIN32)
891 return global_fullscreen;
898 setFullScreen (bool state)
900 #if defined(FX) && !defined(WIN32)
901 global_fullscreen = state;
902 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
903 XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
911 return fdm_data_logging;
915 setFDMDataLogging (bool state)
917 // kludge; no getter or setter available
918 if (state != fdm_data_logging) {
919 fgToggleFDMdataLogging();
920 fdm_data_logging = state;
926 ////////////////////////////////////////////////////////////////////////
927 // Tie the properties.
928 ////////////////////////////////////////////////////////////////////////
934 fgTie("/sim/freeze", getFreeze, setFreeze);
935 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
936 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset);
937 fgSetArchivable("/sim/view/offset-deg");
938 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset);
939 fgSetArchivable("/sim/view/goal-offset-deg");
940 fgTie("/sim/time/gmt", getDateString, setDateString);
941 fgSetArchivable("/sim/time/gmt");
942 fgTie("/sim/time/gmt-string", getGMTString);
943 fgTie("/sim/rendering/textures", getTextures, setTextures);
946 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
949 fgTie("/engines/engine[0]/rpm", getRPM);
950 fgTie("/engines/engine[0]/egt-degf", getEGT);
951 fgTie("/engines/engine[0]/cht-degf", getCHT);
952 fgTie("/engines/engine[0]/mp-osi", getMP);
953 fgTie("/engines/engine[0]/fuel-flow-gph", getFuelFlow);
956 fgTie("/consumables/fuel/tank[0]/level-gal_us",
957 getTank1Fuel, setTank1Fuel, false);
958 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
959 fgTie("/consumables/fuel/tank[1]/level-gal_us",
960 getTank2Fuel, setTank2Fuel, false);
961 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
964 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
965 fgSetArchivable("/autopilot/locks/altitude");
966 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
967 fgSetArchivable("/autopilot/settings/altitude-ft");
968 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
969 fgSetArchivable("/autopilot/locks/glide-slope");
970 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
971 fgSetArchivable("/autopilot/locks/terrain");
972 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
973 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
974 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
975 fgSetArchivable("/autopilot/locks/heading");
976 fgTie("/autopilot/settings/heading-bug-deg",
977 getAPHeadingBug, setAPHeadingBug, false);
978 fgSetArchivable("/autopilot/settings/heading-bug-deg");
979 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
980 fgSetArchivable("/autopilot/locks/wing-leveler");
981 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
982 fgSetArchivable("/autopilot/locks/nav[0]");
983 fgTie("/autopilot/locks/auto-throttle",
984 getAPAutoThrottleLock, setAPAutoThrottleLock);
985 fgSetArchivable("/autopilot/locks/auto-throttle");
986 fgTie("/autopilot/control-overrides/rudder",
987 getAPRudderControl, setAPRudderControl);
988 fgSetArchivable("/autopilot/control-overrides/rudder");
989 fgTie("/autopilot/control-overrides/elevator",
990 getAPElevatorControl, setAPElevatorControl);
991 fgSetArchivable("/autopilot/control-overrides/elevator");
992 fgTie("/autopilot/control-overrides/throttle",
993 getAPThrottleControl, setAPThrottleControl);
994 fgSetArchivable("/autopilot/control-overrides/throttle");
997 fgTie("/environment/visibility-m", getVisibility, setVisibility);
998 fgSetArchivable("/environment/visibility-m");
999 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1000 fgSetArchivable("/environment/wind-north-fps");
1001 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1002 fgSetArchivable("/environment/wind-east-fps");
1003 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1004 fgSetArchivable("/environment/wind-down-fps");
1006 fgTie("/environment/magnetic-variation-deg", getMagVar);
1007 fgTie("/environment/magnetic-dip-deg", getMagDip);
1010 fgTie("/sim/field-of-view", getFOV, setFOV);
1011 fgSetArchivable("/sim/field-of-view");
1012 fgTie("/sim/time/warp", getWarp, setWarp, false);
1013 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1014 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1015 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1017 // Misc. Temporary junk.
1018 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW);
1019 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1020 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1028 _set_view_from_axes();
1033 ////////////////////////////////////////////////////////////////////////
1034 // Save and restore.
1035 ////////////////////////////////////////////////////////////////////////
1039 * Save the current state of the simulator to a stream.
1042 fgSaveFlight (ostream &output)
1045 writeProperties(output, globals->get_props());
1046 } catch (const sg_io_exception &e) {
1047 string message = "Error saving flight: ";
1048 message += e.getMessage();
1049 message += "\n at ";
1050 message += e.getLocation().asString();
1051 SG_LOG(SG_INPUT, SG_ALERT, message);
1052 mkDialog(message.c_str());
1060 * Restore the current state of the simulator from a stream.
1063 fgLoadFlight (istream &input)
1065 SGPropertyNode props;
1067 readProperties(input, &props);
1068 } catch (const sg_io_exception &e) {
1069 string message = "Error reading saved flight: ";
1070 message += e.getMessage();
1071 message += "\n at ";
1072 message += e.getLocation().asString();
1073 SG_LOG(SG_INPUT, SG_ALERT, message);
1074 mkDialog(message.c_str());
1077 copyProperties(&props, globals->get_props());
1078 // When loading a flight, make it the
1079 // new initial state.
1080 globals->saveInitialState();
1084 // end of fg_props.cxx