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>
40 #include "fg_props.hxx"
42 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
43 SG_USING_STD(istream);
44 SG_USING_STD(ostream);
47 #define DEFAULT_AP_HEADING_LOCK FGAutopilot::FG_DG_HEADING_LOCK
49 static double getWindNorth ();
50 static double getWindEast ();
51 static double getWindDown ();
53 // Allow the view to be set from two axes (i.e. a joystick hat)
54 // This needs to be in FGViewer itself, somehow.
55 static double axisLong = 0.0;
56 static double axisLat = 0.0;
62 _set_view_from_axes ()
64 // Take no action when hat is centered
65 if ( ( axisLong < 0.01 ) &&
66 ( axisLong > -0.01 ) &&
74 /* Do all the quick and easy cases */
75 if (axisLong < 0) { // Longitudinal axis forward
76 if (axisLat == axisLong)
78 else if (axisLat == - axisLong)
80 else if (axisLat == 0)
82 } else if (axisLong > 0) { // Longitudinal axis backward
83 if (axisLat == - axisLong)
85 else if (axisLat == axisLong)
87 else if (axisLat == 0)
89 } else if (axisLong = 0) { // Longitudinal axis neutral
94 else return; /* And assertion failure maybe? */
97 /* Do all the difficult cases */
99 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
100 if ( viewDir < -1 ) viewDir += 360;
102 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
103 // << axisLong << " gave angle=" << viewDir );
105 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
106 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
110 ////////////////////////////////////////////////////////////////////////
111 // Default property bindings (not yet handled by any module).
112 ////////////////////////////////////////////////////////////////////////
115 * Return the current aircraft directory (UIUC) as a string.
125 * Set the current aircraft directory (UIUC).
128 setAircraftDir (string dir)
130 if (getAircraftDir() != dir) {
132 // needReinit(); FIXME!!
138 * Get the current view offset in degrees.
143 return (globals->get_current_view()
144 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
149 setViewOffset (double offset)
151 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
157 return (globals->get_current_view()
158 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
162 setGoalViewOffset (double offset)
164 globals->get_current_view()
165 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
170 * Return the current Zulu time.
177 struct tm * t = globals->get_time_params()->getGmt();
178 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
179 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
180 t->tm_hour, t->tm_min, t->tm_sec);
187 * Set the current Zulu time.
190 setDateString (string date_string)
192 SGTime * st = globals->get_time_params();
193 struct tm * current_time = st->getGmt();
196 // Scan for basic ISO format
197 // YYYY-MM-DDTHH:MM:SS
198 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
199 &(new_time.tm_year), &(new_time.tm_mon),
200 &(new_time.tm_mday), &(new_time.tm_hour),
201 &(new_time.tm_min), &(new_time.tm_sec));
203 // Be pretty picky about this, so
204 // that strange things don't happen
205 // if the save file has been edited
208 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
209 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
213 // OK, it looks like we got six
214 // values, one way or another.
215 new_time.tm_year -= 1900;
216 new_time.tm_mon -= 1;
218 // Now, tell flight gear to use
219 // the new time. This was far
220 // too difficult, by the way.
222 mktime(&new_time) - mktime(current_time) + globals->get_warp();
223 double lon = current_aircraft.fdm_state->get_Longitude();
224 double lat = current_aircraft.fdm_state->get_Latitude();
225 globals->set_warp(warp);
226 st->update(lon, lat, warp);
227 fgUpdateSkyAndLightingParams();
231 * Return the GMT as a string.
238 struct tm * t = globals->get_time_params()->getGmt();
239 sprintf(buf, " %.2d:%.2d:%.2d",
240 t->tm_hour, t->tm_min, t->tm_sec);
246 * Return the magnetic variation
251 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
256 * Return the magnetic dip
261 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
266 * Return the current heading in degrees.
271 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
276 * Return the current engine0 rpm
281 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
282 return current_aircraft.fdm_state->get_engine(0)->get_RPM();
290 * Return the current engine0 EGT.
295 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
296 return current_aircraft.fdm_state->get_engine(0)->get_EGT();
303 * Return the current engine0 CHT.
308 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
309 return current_aircraft.fdm_state->get_engine(0)->get_CHT();
316 * Return the current engine0 Manifold Pressure.
321 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
322 return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
330 * Return the current engine0 fuel flow
335 if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
336 return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
343 * Return the fuel level in tank 1
348 return current_aircraft.fdm_state->get_Tank1Fuel();
352 setTank1Fuel ( double gals )
354 current_aircraft.fdm_state->set_Tank1Fuel( gals );
358 * Return the fuel level in tank 2
363 return current_aircraft.fdm_state->get_Tank2Fuel();
367 setTank2Fuel ( double gals )
369 current_aircraft.fdm_state->set_Tank2Fuel( gals );
374 * Get the autopilot altitude lock (true=on).
379 return current_autopilot->get_AltitudeEnabled();
384 * Set the autopilot altitude lock (true=on).
387 setAPAltitudeLock (bool lock)
389 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
390 current_autopilot->set_AltitudeEnabled(lock);
394 * Get the autopilot target altitude in feet.
399 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
404 * Set the autopilot target altitude in feet.
407 setAPAltitude (double altitude)
409 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
413 * Get the autopilot altitude lock (true=on).
418 return current_autopilot->get_AltitudeEnabled();
423 * Set the autopilot altitude lock (true=on).
426 setAPGSLock (bool lock)
428 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
429 current_autopilot->set_AltitudeEnabled(lock);
434 * Get the autopilot target altitude in feet.
439 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
444 * Set the autopilot target altitude in feet.
447 setAPClimb (double rate)
449 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
454 * Get the autopilot heading lock (true=on).
460 (current_autopilot->get_HeadingEnabled() &&
461 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
466 * Set the autopilot heading lock (true=on).
469 setAPHeadingLock (bool lock)
472 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
473 current_autopilot->set_HeadingEnabled(true);
475 current_autopilot->set_HeadingEnabled(false);
481 * Get the autopilot heading bug in degrees.
486 return current_autopilot->get_DGTargetHeading();
491 * Set the autopilot heading bug in degrees.
494 setAPHeadingBug (double heading)
496 current_autopilot->set_DGTargetHeading( heading );
501 * Get the autopilot wing leveler lock (true=on).
507 (current_autopilot->get_HeadingEnabled() &&
508 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
513 * Set the autopilot wing leveler lock (true=on).
516 setAPWingLeveler (bool lock)
519 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
520 current_autopilot->set_HeadingEnabled(true);
522 current_autopilot->set_HeadingEnabled(false);
527 * Return true if the autopilot is locked to NAV1.
533 (current_autopilot->get_HeadingEnabled() &&
534 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
539 * Set the autopilot NAV1 lock.
542 setAPNAV1Lock (bool lock)
545 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
546 current_autopilot->set_HeadingEnabled(true);
547 } else if (current_autopilot->get_HeadingMode() ==
548 FGAutopilot::FG_HEADING_NAV1) {
549 current_autopilot->set_HeadingEnabled(false);
554 * Get the autopilot autothrottle lock.
557 getAPAutoThrottleLock ()
559 return current_autopilot->get_AutoThrottleEnabled();
564 * Set the autothrottle lock.
567 setAPAutoThrottleLock (bool lock)
569 current_autopilot->set_AutoThrottleEnabled(lock);
575 getAPRudderControl ()
577 if (getAPHeadingLock())
578 return current_autopilot->get_TargetHeading();
580 return controls.get_rudder();
585 setAPRudderControl (double value)
587 if (getAPHeadingLock()) {
588 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
589 value -= current_autopilot->get_TargetHeading();
590 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
592 controls.set_rudder(value);
598 getAPElevatorControl ()
600 if (getAPAltitudeLock())
601 return current_autopilot->get_TargetAltitude();
603 return controls.get_elevator();
608 setAPElevatorControl (double value)
610 if (getAPAltitudeLock()) {
611 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
612 value -= current_autopilot->get_TargetAltitude();
613 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
615 controls.set_elevator(value);
621 getAPThrottleControl ()
623 if (getAPAutoThrottleLock())
624 return 0.0; // always resets
626 return controls.get_throttle(0);
631 setAPThrottleControl (double value)
633 if (getAPAutoThrottleLock())
634 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
636 controls.set_throttle(0, value);
641 * Get the current visibility (meters).
646 #ifndef FG_OLD_WEATHER
647 return WeatherDatabase->getWeatherVisibility();
649 return current_weather.get_visibility();
655 * Set the current visibility (meters).
658 setVisibility (double visibility)
660 #ifndef FG_OLD_WEATHER
661 WeatherDatabase->setWeatherVisibility(visibility);
663 current_weather.set_visibility(visibility);
668 * Get the current wind north velocity (feet/second).
673 return current_aircraft.fdm_state->get_V_north_airmass();
678 * Set the current wind north velocity (feet/second).
681 setWindNorth (double speed)
683 current_aircraft.fdm_state
684 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
689 * Get the current wind east velocity (feet/second).
694 return current_aircraft.fdm_state->get_V_east_airmass();
699 * Set the current wind east velocity (feet/second).
702 setWindEast (double speed)
704 cout << "Set wind-east to " << speed << endl;
705 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
712 * Get the current wind down velocity (feet/second).
717 return current_aircraft.fdm_state->get_V_down_airmass();
722 * Set the current wind down velocity (feet/second).
725 setWindDown (double speed)
727 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
735 return globals->get_current_view()->get_fov();
741 globals->get_current_view()->set_fov( fov );
746 setViewAxisLong (double axis)
752 setViewAxisLat (double axis)
762 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
763 fgTie("/sim/view/offset", getViewOffset, setViewOffset);
764 fgTie("/sim/view/goal-offset", getGoalViewOffset, setGoalViewOffset);
765 fgTie("/sim/time/gmt", getDateString, setDateString);
766 fgTie("/sim/time/gmt-string", getGMTString);
769 fgTie("/orientation/heading-magnetic", getHeadingMag);
772 fgTie("/engines/engine0/rpm", getRPM);
773 fgTie("/engines/engine0/egt", getEGT);
774 fgTie("/engines/engine0/cht", getCHT);
775 fgTie("/engines/engine0/mp", getMP);
776 fgTie("/engines/engine0/fuel-flow", getFuelFlow);
779 fgTie("/consumables/fuel/tank1/level", getTank1Fuel, setTank1Fuel, false);
780 fgTie("/consumables/fuel/tank2/level", getTank2Fuel, setTank2Fuel, false);
783 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
784 fgTie("/autopilot/settings/altitude", getAPAltitude, setAPAltitude);
785 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
786 fgTie("/autopilot/settings/climb-rate", getAPClimb, setAPClimb, false);
787 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
788 fgTie("/autopilot/settings/heading-bug", getAPHeadingBug, setAPHeadingBug,
790 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
791 fgTie("/autopilot/locks/nav1", getAPNAV1Lock, setAPNAV1Lock);
792 fgTie("/autopilot/locks/auto-throttle",
793 getAPAutoThrottleLock, setAPAutoThrottleLock);
794 fgTie("/autopilot/control-overrides/rudder",
795 getAPRudderControl, setAPRudderControl);
796 fgTie("/autopilot/control-overrides/elevator",
797 getAPElevatorControl, setAPElevatorControl);
798 fgTie("/autopilot/control-overrides/throttle",
799 getAPThrottleControl, setAPThrottleControl);
802 fgTie("/environment/visibility", getVisibility, setVisibility);
803 fgTie("/environment/wind-north", getWindNorth, setWindNorth);
804 fgTie("/environment/wind-east", getWindEast, setWindEast);
805 fgTie("/environment/wind-down", getWindDown, setWindDown);
806 fgTie("/environment/magnetic-variation", getMagVar);
807 fgTie("/environment/magnetic-dip", getMagDip);
810 fgTie("/sim/field-of-view", getFOV, setFOV);
811 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
812 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
819 _set_view_from_axes();
824 ////////////////////////////////////////////////////////////////////////
826 ////////////////////////////////////////////////////////////////////////
830 * Save the current state of the simulator to a stream.
833 fgSaveFlight (ostream &output)
835 return writeProperties(output, globals->get_props());
840 * Restore the current state of the simulator from a stream.
843 fgLoadFlight (istream &input)
845 SGPropertyNode props;
846 if (readProperties(input, &props)) {
847 copyProperties(&props, globals->get_props());
848 // When loading a flight, make it the
849 // new initial state.
850 globals->saveInitialState();
852 SG_LOG(SG_INPUT, SG_ALERT, "Error restoring flight; aborted");
859 // end of fg_props.cxx