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>
29 #include <Autopilot/newauto.hxx>
30 #include <Aircraft/aircraft.hxx>
31 #include <Time/tmp.hxx>
32 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
33 #ifndef FG_OLD_WEATHER
34 # include <WeatherCM/FGLocalWeatherDatabase.h>
36 # include <Weather/weather.hxx>
38 #include <Objects/matlib.hxx>
41 #include "fg_props.hxx"
43 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
44 SG_USING_STD(istream);
45 SG_USING_STD(ostream);
48 static double getWindNorth ();
49 static double getWindEast ();
50 static double getWindDown ();
52 // Allow the view to be set from two axes (i.e. a joystick hat)
53 // This needs to be in FGViewer itself, somehow.
54 static double axisLong = 0.0;
55 static double axisLat = 0.0;
57 static bool winding_ccw = false; // FIXME: temporary
59 static bool fdm_data_logging = false; // FIXME: temporary
66 _set_view_from_axes ()
68 // Take no action when hat is centered
69 if ( ( axisLong < 0.01 ) &&
70 ( axisLong > -0.01 ) &&
78 /* Do all the quick and easy cases */
79 if (axisLong < 0) { // Longitudinal axis forward
80 if (axisLat == axisLong)
82 else if (axisLat == - axisLong)
84 else if (axisLat == 0)
86 } else if (axisLong > 0) { // Longitudinal axis backward
87 if (axisLat == - axisLong)
89 else if (axisLat == axisLong)
91 else if (axisLat == 0)
93 } else if (axisLong == 0) { // Longitudinal axis neutral
98 else return; /* And assertion failure maybe? */
101 /* Do all the difficult cases */
103 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
104 if ( viewDir < -1 ) viewDir += 360;
106 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
107 // << axisLong << " gave angle=" << viewDir );
109 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
110 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
114 ////////////////////////////////////////////////////////////////////////
115 // Default property bindings (not yet handled by any module).
116 ////////////////////////////////////////////////////////////////////////
120 * Get the pause state of the sim.
125 return globals->get_freeze();
130 * Set the pause state of the sim.
133 setFreeze (bool freeze)
135 globals->set_freeze(freeze);
139 * Return the current aircraft directory (UIUC) as a string.
149 * Set the current aircraft directory (UIUC).
152 setAircraftDir (string dir)
154 if (getAircraftDir() != dir) {
156 // needReinit(); FIXME!!
162 * Get the current view offset in degrees.
167 return (globals->get_current_view()
168 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
173 setViewOffset (double offset)
175 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
181 return (globals->get_current_view()
182 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
186 setGoalViewOffset (double offset)
188 while ( offset < 0 ) {
191 while ( offset > 360.0 ) {
194 // Snap to center if we are close
195 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
199 globals->get_current_view()
200 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
205 * Return the current Zulu time.
212 struct tm * t = globals->get_time_params()->getGmt();
213 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
214 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
215 t->tm_hour, t->tm_min, t->tm_sec);
222 * Set the current Zulu time.
225 setDateString (string date_string)
227 SGTime * st = globals->get_time_params();
228 struct tm * current_time = st->getGmt();
231 // Scan for basic ISO format
232 // YYYY-MM-DDTHH:MM:SS
233 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
234 &(new_time.tm_year), &(new_time.tm_mon),
235 &(new_time.tm_mday), &(new_time.tm_hour),
236 &(new_time.tm_min), &(new_time.tm_sec));
238 // Be pretty picky about this, so
239 // that strange things don't happen
240 // if the save file has been edited
243 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
244 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
248 // OK, it looks like we got six
249 // values, one way or another.
250 new_time.tm_year -= 1900;
251 new_time.tm_mon -= 1;
253 // Now, tell flight gear to use
254 // the new time. This was far
255 // too difficult, by the way.
257 mktime(&new_time) - mktime(current_time) + globals->get_warp();
258 double lon = current_aircraft.fdm_state->get_Longitude();
259 double lat = current_aircraft.fdm_state->get_Latitude();
260 globals->set_warp(warp);
261 st->update(lon, lat, warp);
262 fgUpdateSkyAndLightingParams();
266 * Return the GMT as a string.
273 struct tm * t = globals->get_time_params()->getGmt();
274 sprintf(buf, " %.2d:%.2d:%.2d",
275 t->tm_hour, t->tm_min, t->tm_sec);
282 * Get the texture rendering state.
287 return (material_lib.get_step() == 0);
292 * Set the texture rendering state.
295 setTextures (bool textures)
298 material_lib.set_step(0);
300 material_lib.set_step(1);
305 * Return the magnetic variation
310 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
315 * Return the magnetic dip
320 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
325 * Return the current heading in degrees.
330 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
335 * Return the current engine0 rpm
340 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
341 return current_aircraft.fdm_state->get_engine(0)->get_RPM();
349 * Return the current engine0 EGT.
354 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
355 return current_aircraft.fdm_state->get_engine(0)->get_EGT();
362 * Return the current engine0 CHT.
367 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
368 return current_aircraft.fdm_state->get_engine(0)->get_CHT();
375 * Return the current engine0 Manifold Pressure.
380 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
381 return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
389 * Return the current engine0 fuel flow
394 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
395 return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
402 * Return the fuel level in tank 1
407 return current_aircraft.fdm_state->get_Tank1Fuel();
411 setTank1Fuel ( double gals )
413 current_aircraft.fdm_state->set_Tank1Fuel( gals );
417 * Return the fuel level in tank 2
422 return current_aircraft.fdm_state->get_Tank2Fuel();
426 setTank2Fuel ( double gals )
428 current_aircraft.fdm_state->set_Tank2Fuel( gals );
433 * Get the autopilot altitude lock (true=on).
438 return (current_autopilot->get_AltitudeEnabled() &&
439 current_autopilot->get_AltitudeMode()
440 == FGAutopilot::FG_ALTITUDE_LOCK);
445 * Set the autopilot altitude lock (true=on).
448 setAPAltitudeLock (bool lock)
450 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
451 current_autopilot->set_AltitudeEnabled(lock);
456 * Get the autopilot target altitude in feet.
461 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
466 * Set the autopilot target altitude in feet.
469 setAPAltitude (double altitude)
471 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
475 * Get the autopilot altitude lock (true=on).
480 return (current_autopilot->get_AltitudeEnabled() &&
481 (current_autopilot->get_AltitudeMode()
482 == FGAutopilot::FG_ALTITUDE_GS1));
487 * Set the autopilot altitude lock (true=on).
490 setAPGSLock (bool lock)
492 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
493 current_autopilot->set_AltitudeEnabled(lock);
498 * Get the autopilot terrain lock (true=on).
503 return (current_autopilot->get_AltitudeEnabled() &&
504 (current_autopilot->get_AltitudeMode()
505 == FGAutopilot::FG_ALTITUDE_TERRAIN));
510 * Set the autopilot terrain lock (true=on).
513 setAPTerrainLock (bool lock)
515 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
516 current_autopilot->set_AltitudeEnabled(lock);
521 * Get the autopilot target altitude in feet.
526 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
531 * Set the autopilot target altitude in feet.
534 setAPClimb (double rate)
536 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
541 * Get the autopilot heading lock (true=on).
547 (current_autopilot->get_HeadingEnabled() &&
548 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
553 * Set the autopilot heading lock (true=on).
556 setAPHeadingLock (bool lock)
559 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
560 current_autopilot->set_HeadingEnabled(true);
562 current_autopilot->set_HeadingEnabled(false);
568 * Get the autopilot heading bug in degrees.
573 return current_autopilot->get_DGTargetHeading();
578 * Set the autopilot heading bug in degrees.
581 setAPHeadingBug (double heading)
583 current_autopilot->set_DGTargetHeading( heading );
588 * Get the autopilot wing leveler lock (true=on).
594 (current_autopilot->get_HeadingEnabled() &&
595 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
600 * Set the autopilot wing leveler lock (true=on).
603 setAPWingLeveler (bool lock)
606 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
607 current_autopilot->set_HeadingEnabled(true);
609 current_autopilot->set_HeadingEnabled(false);
614 * Return true if the autopilot is locked to NAV1.
620 (current_autopilot->get_HeadingEnabled() &&
621 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
626 * Set the autopilot NAV1 lock.
629 setAPNAV1Lock (bool lock)
632 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
633 current_autopilot->set_HeadingEnabled(true);
634 } else if (current_autopilot->get_HeadingMode() ==
635 FGAutopilot::FG_HEADING_NAV1) {
636 current_autopilot->set_HeadingEnabled(false);
641 * Get the autopilot autothrottle lock.
644 getAPAutoThrottleLock ()
646 return current_autopilot->get_AutoThrottleEnabled();
651 * Set the autothrottle lock.
654 setAPAutoThrottleLock (bool lock)
656 current_autopilot->set_AutoThrottleEnabled(lock);
662 getAPRudderControl ()
664 if (getAPHeadingLock())
665 return current_autopilot->get_TargetHeading();
667 return controls.get_rudder();
672 setAPRudderControl (double value)
674 if (getAPHeadingLock()) {
675 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
676 value -= current_autopilot->get_TargetHeading();
677 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
679 controls.set_rudder(value);
685 getAPElevatorControl ()
687 if (getAPAltitudeLock())
688 return current_autopilot->get_TargetAltitude();
690 return controls.get_elevator();
695 setAPElevatorControl (double value)
697 if (getAPAltitudeLock()) {
698 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
699 value -= current_autopilot->get_TargetAltitude();
700 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
702 controls.set_elevator(value);
708 getAPThrottleControl ()
710 if (getAPAutoThrottleLock())
711 return 0.0; // always resets
713 return controls.get_throttle(0);
718 setAPThrottleControl (double value)
720 if (getAPAutoThrottleLock())
721 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
723 controls.set_throttle(0, value);
728 * Get the current visibility (meters).
733 #ifndef FG_OLD_WEATHER
734 return WeatherDatabase->getWeatherVisibility();
736 return current_weather.get_visibility();
742 * Set the current visibility (meters).
745 setVisibility (double visibility)
747 #ifndef FG_OLD_WEATHER
748 WeatherDatabase->setWeatherVisibility(visibility);
750 current_weather.set_visibility(visibility);
755 * Get the current wind north velocity (feet/second).
760 return current_aircraft.fdm_state->get_V_north_airmass();
765 * Set the current wind north velocity (feet/second).
768 setWindNorth (double speed)
770 current_aircraft.fdm_state
771 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
776 * Get the current wind east velocity (feet/second).
781 return current_aircraft.fdm_state->get_V_east_airmass();
786 * Set the current wind east velocity (feet/second).
789 setWindEast (double speed)
791 cout << "Set wind-east to " << speed << endl;
792 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
799 * Get the current wind down velocity (feet/second).
804 return current_aircraft.fdm_state->get_V_down_airmass();
809 * Set the current wind down velocity (feet/second).
812 setWindDown (double speed)
814 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
822 return globals->get_current_view()->get_fov();
828 globals->get_current_view()->set_fov( fov );
834 return globals->get_warp();
840 globals->set_warp(warp);
846 return globals->get_warp_delta();
850 setWarpDelta (long delta)
852 globals->set_warp_delta(delta);
856 setViewAxisLong (double axis)
862 setViewAxisLat (double axis)
874 setWindingCCW (bool state)
878 glFrontFace ( GL_CCW );
880 glFrontFace ( GL_CW );
886 #if defined(FX) && !defined(WIN32)
887 return global_fullscreen;
894 setFullScreen (bool state)
896 #if defined(FX) && !defined(WIN32)
897 global_fullscreen = state;
898 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
899 XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
907 return fdm_data_logging;
911 setFDMDataLogging (bool state)
913 // kludge; no getter or setter available
914 if (state != fdm_data_logging) {
915 fgToggleFDMdataLogging();
916 fdm_data_logging = state;
922 ////////////////////////////////////////////////////////////////////////
923 // Tie the properties.
924 ////////////////////////////////////////////////////////////////////////
930 fgTie("/sim/freeze", getFreeze, setFreeze);
931 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
932 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset);
933 fgSetArchivable("/sim/view/offset-deg");
934 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset);
935 fgSetArchivable("/sim/view/goal-offset-deg");
936 fgTie("/sim/time/gmt", getDateString, setDateString);
937 fgSetArchivable("/sim/time/gmt");
938 fgTie("/sim/time/gmt-string", getGMTString);
939 fgTie("/sim/rendering/textures", getTextures, setTextures);
942 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
945 fgTie("/engines/engine[0]/rpm", getRPM);
946 fgTie("/engines/engine[0]/egt-degf", getEGT);
947 fgTie("/engines/engine[0]/cht-degf", getCHT);
948 fgTie("/engines/engine[0]/mp-osi", getMP);
949 fgTie("/engines/engine[0]/fuel-flow-gph", getFuelFlow);
952 fgTie("/consumables/fuel/tank[0]/level-gal_us",
953 getTank1Fuel, setTank1Fuel, false);
954 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
955 fgTie("/consumables/fuel/tank[1]/level-gal_us",
956 getTank2Fuel, setTank2Fuel, false);
957 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
960 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
961 fgSetArchivable("/autopilot/locks/altitude");
962 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
963 fgSetArchivable("/autopilot/settings/altitude-ft");
964 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
965 fgSetArchivable("/autopilot/locks/glide-slope");
966 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
967 fgSetArchivable("/autopilot/locks/terrain");
968 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
969 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
970 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
971 fgSetArchivable("/autopilot/locks/heading");
972 fgTie("/autopilot/settings/heading-bug-deg",
973 getAPHeadingBug, setAPHeadingBug, false);
974 fgSetArchivable("/autopilot/settings/heading-bug-deg");
975 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
976 fgSetArchivable("/autopilot/locks/wing-leveler");
977 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
978 fgSetArchivable("/autopilot/locks/nav[0]");
979 fgTie("/autopilot/locks/auto-throttle",
980 getAPAutoThrottleLock, setAPAutoThrottleLock);
981 fgSetArchivable("/autopilot/locks/auto-throttle");
982 fgTie("/autopilot/control-overrides/rudder",
983 getAPRudderControl, setAPRudderControl);
984 fgSetArchivable("/autopilot/control-overrides/rudder");
985 fgTie("/autopilot/control-overrides/elevator",
986 getAPElevatorControl, setAPElevatorControl);
987 fgSetArchivable("/autopilot/control-overrides/elevator");
988 fgTie("/autopilot/control-overrides/throttle",
989 getAPThrottleControl, setAPThrottleControl);
990 fgSetArchivable("/autopilot/control-overrides/throttle");
993 fgTie("/environment/visibility-m", getVisibility, setVisibility);
994 fgSetArchivable("/environment/visibility-m");
995 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
996 fgSetArchivable("/environment/wind-north-fps");
997 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
998 fgSetArchivable("/environment/wind-east-fps");
999 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1000 fgSetArchivable("/environment/wind-down-fps");
1002 fgTie("/environment/magnetic-variation-deg", getMagVar);
1003 fgTie("/environment/magnetic-dip-deg", getMagDip);
1006 fgTie("/sim/field-of-view", getFOV, setFOV);
1007 fgSetArchivable("/sim/field-of-view");
1008 fgTie("/sim/time/warp", getWarp, setWarp, false);
1009 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1010 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1011 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1013 // Misc. Temporary junk.
1014 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW);
1015 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1016 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1024 _set_view_from_axes();
1029 ////////////////////////////////////////////////////////////////////////
1030 // Save and restore.
1031 ////////////////////////////////////////////////////////////////////////
1035 * Save the current state of the simulator to a stream.
1038 fgSaveFlight (ostream &output)
1040 return writeProperties(output, globals->get_props());
1045 * Restore the current state of the simulator from a stream.
1048 fgLoadFlight (istream &input)
1050 SGPropertyNode props;
1051 if (readProperties(input, &props)) {
1052 copyProperties(&props, globals->get_props());
1053 // When loading a flight, make it the
1054 // new initial state.
1055 globals->saveInitialState();
1057 SG_LOG(SG_INPUT, SG_ALERT, "Error restoring flight; aborted");
1064 // end of fg_props.cxx