]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_props.cxx
2a92e5982ba5c28e98201b935683870179fb6fdc
[flightgear.git] / src / Main / fg_props.cxx
1 // fg_props.cxx -- support for FlightGear properties.
2 //
3 // Written by David Megginson, started 2000.
4 //
5 // Copyright (C) 2000, 2001 David Megginson - david@megginson.com
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <simgear/compiler.h>
25 #endif
26
27 #include STL_IOSTREAM
28
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>
35 #else
36 #  include <Weather/weather.hxx>
37 #endif
38
39 #include "fgfs.hxx"
40 #include "fg_props.hxx"
41
42 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
43 SG_USING_STD(istream);
44 SG_USING_STD(ostream);
45 #endif
46
47 #define DEFAULT_AP_HEADING_LOCK FGAutopilot::FG_DG_HEADING_LOCK
48
49 static double getWindNorth ();
50 static double getWindEast ();
51 static double getWindDown ();
52
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;
57
58 /**
59  * Utility function.
60  */
61 static inline void
62 _set_view_from_axes ()
63 {
64                                 // Take no action when hat is centered
65   if ( ( axisLong <  0.01 ) &&
66        ( axisLong > -0.01 ) &&
67        ( axisLat  <  0.01 ) &&
68        ( axisLat  > -0.01 )
69      )
70     return;
71
72   double viewDir = 999;
73
74   /* Do all the quick and easy cases */
75   if (axisLong < 0) {           // Longitudinal axis forward
76     if (axisLat == axisLong)
77       viewDir = 45;
78     else if (axisLat == - axisLong)
79       viewDir = 315;
80     else if (axisLat == 0)
81       viewDir = 0;
82   } else if (axisLong > 0) {    // Longitudinal axis backward
83     if (axisLat == - axisLong)
84       viewDir = 135;
85     else if (axisLat == axisLong)
86       viewDir = 225;
87     else if (axisLat == 0)
88       viewDir = 180;
89   } else if (axisLong = 0) {    // Longitudinal axis neutral
90     if (axisLat < 0)
91       viewDir = 90;
92     else if (axisLat > 0)
93       viewDir = 270;
94     else return; /* And assertion failure maybe? */
95   }
96
97   /* Do all the difficult cases */
98   if ( viewDir > 900 )
99     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
100   if ( viewDir < -1 ) viewDir += 360;
101
102 //  SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << "   and Long="
103 //      << axisLong << "  gave angle=" << viewDir );
104
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);
107 }
108
109 \f
110 ////////////////////////////////////////////////////////////////////////
111 // Default property bindings (not yet handled by any module).
112 ////////////////////////////////////////////////////////////////////////
113
114 /**
115  * Return the current aircraft directory (UIUC) as a string.
116  */
117 static string 
118 getAircraftDir ()
119 {
120   return aircraft_dir;
121 }
122
123
124 /**
125  * Set the current aircraft directory (UIUC).
126  */
127 static void
128 setAircraftDir (string dir)
129 {
130   if (getAircraftDir() != dir) {
131     aircraft_dir = dir;
132 //     needReinit(); FIXME!!
133   }
134 }
135
136
137 /**
138  * Get the current view offset in degrees.
139  */
140 static double
141 getViewOffset ()
142 {
143   return (globals->get_current_view()
144           ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
145 }
146
147
148 static void
149 setViewOffset (double offset)
150 {
151   globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
152 }
153
154 static double
155 getGoalViewOffset ()
156 {
157   return (globals->get_current_view()
158           ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
159 }
160
161 static void
162 setGoalViewOffset (double offset)
163 {
164   globals->get_current_view()
165     ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
166 }
167
168
169 /**
170  * Return the current Zulu time.
171  */
172 static string 
173 getDateString ()
174 {
175   string out;
176   char buf[64];
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);
181   out = buf;
182   return out;
183 }
184
185
186 /**
187  * Set the current Zulu time.
188  */
189 static void
190 setDateString (string date_string)
191 {
192   SGTime * st = globals->get_time_params();
193   struct tm * current_time = st->getGmt();
194   struct tm new_time;
195
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));
202
203                                 // Be pretty picky about this, so
204                                 // that strange things don't happen
205                                 // if the save file has been edited
206                                 // by hand.
207   if (ret != 6) {
208     SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
209            << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
210     return;
211   }
212
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;
217
218                                 // Now, tell flight gear to use
219                                 // the new time.  This was far
220                                 // too difficult, by the way.
221   long int warp =
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();
228 }
229
230 /**
231  * Return the GMT as a string.
232  */
233 static string 
234 getGMTString ()
235 {
236   string out;
237   char buf[16];
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);
241   out = buf;
242   return out;
243 }
244
245 /**
246  * Return the magnetic variation
247  */
248 static double
249 getMagVar ()
250 {
251   return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
252 }
253
254
255 /**
256  * Return the magnetic dip
257  */
258 static double
259 getMagDip ()
260 {
261   return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
262 }
263
264
265 /**
266  * Return the current heading in degrees.
267  */
268 static double
269 getHeadingMag ()
270 {
271   return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
272 }
273
274
275 /**
276  * Return the current engine0 rpm
277  */
278 static double
279 getRPM ()
280 {
281   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
282       return current_aircraft.fdm_state->get_engine(0)->get_RPM();
283   } else {
284       return 0.0;
285   }
286 }
287
288
289 /**
290  * Return the current engine0 EGT.
291  */
292 static double
293 getEGT ()
294 {
295   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
296       return current_aircraft.fdm_state->get_engine(0)->get_EGT();
297   } else {
298       return 0.0;
299   }
300 }
301
302 /**
303  * Return the current engine0 CHT.
304  */
305 static double
306 getCHT ()
307 {
308   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
309       return current_aircraft.fdm_state->get_engine(0)->get_CHT();
310   } else {
311       return 0.0;
312   }
313 }
314
315 /**
316  * Return the current engine0 Manifold Pressure.
317  */
318 static double
319 getMP ()
320 {
321   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
322       return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
323   } else {
324       return 0.0;
325   }
326 }
327
328
329 /**
330  * Return the current engine0 fuel flow
331  */
332 static double
333 getFuelFlow ()
334 {
335   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
336       return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
337   } else {
338       return 0.0;
339   }
340 }
341
342 /**
343  * Return the fuel level in tank 1
344  */
345 static double
346 getTank1Fuel ()
347 {
348   return current_aircraft.fdm_state->get_Tank1Fuel();
349 }
350
351 static void
352 setTank1Fuel ( double gals )
353 {
354   current_aircraft.fdm_state->set_Tank1Fuel( gals );
355 }
356
357 /**
358  * Return the fuel level in tank 2
359  */
360 static double
361 getTank2Fuel ()
362 {
363   return current_aircraft.fdm_state->get_Tank2Fuel();
364 }
365
366 static void
367 setTank2Fuel ( double gals )
368 {
369   current_aircraft.fdm_state->set_Tank2Fuel( gals );
370 }
371
372
373 /**
374  * Get the autopilot altitude lock (true=on).
375  */
376 static bool
377 getAPAltitudeLock ()
378 {
379     return current_autopilot->get_AltitudeEnabled();
380 }
381
382
383 /**
384  * Set the autopilot altitude lock (true=on).
385  */
386 static void
387 setAPAltitudeLock (bool lock)
388 {
389   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
390   current_autopilot->set_AltitudeEnabled(lock);
391 }
392
393 /**
394  * Get the autopilot target altitude in feet.
395  */
396 static double
397 getAPAltitude ()
398 {
399   return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
400 }
401
402
403 /**
404  * Set the autopilot target altitude in feet.
405  */
406 static void
407 setAPAltitude (double altitude)
408 {
409     current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
410 }
411
412 /**
413  * Get the autopilot altitude lock (true=on).
414  */
415 static bool
416 getAPGSLock ()
417 {
418     return current_autopilot->get_AltitudeEnabled();
419 }
420
421
422 /**
423  * Set the autopilot altitude lock (true=on).
424  */
425 static void
426 setAPGSLock (bool lock)
427 {
428   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
429   current_autopilot->set_AltitudeEnabled(lock);
430 }
431
432
433 /**
434  * Get the autopilot target altitude in feet.
435  */
436 static double
437 getAPClimb ()
438 {
439   return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
440 }
441
442
443 /**
444  * Set the autopilot target altitude in feet.
445  */
446 static void
447 setAPClimb (double rate)
448 {
449     current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
450 }
451
452
453 /**
454  * Get the autopilot heading lock (true=on).
455  */
456 static bool
457 getAPHeadingLock ()
458 {
459     return
460       (current_autopilot->get_HeadingEnabled() &&
461        current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
462 }
463
464
465 /**
466  * Set the autopilot heading lock (true=on).
467  */
468 static void
469 setAPHeadingLock (bool lock)
470 {
471     if (lock) {
472         current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
473         current_autopilot->set_HeadingEnabled(true);
474     } else {
475         current_autopilot->set_HeadingEnabled(false);
476     }
477 }
478
479
480 /**
481  * Get the autopilot heading bug in degrees.
482  */
483 static double
484 getAPHeadingBug ()
485 {
486   return current_autopilot->get_DGTargetHeading();
487 }
488
489
490 /**
491  * Set the autopilot heading bug in degrees.
492  */
493 static void
494 setAPHeadingBug (double heading)
495 {
496   current_autopilot->set_DGTargetHeading( heading );
497 }
498
499
500 /**
501  * Get the autopilot wing leveler lock (true=on).
502  */
503 static bool
504 getAPWingLeveler ()
505 {
506     return
507       (current_autopilot->get_HeadingEnabled() &&
508        current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
509 }
510
511
512 /**
513  * Set the autopilot wing leveler lock (true=on).
514  */
515 static void
516 setAPWingLeveler (bool lock)
517 {
518     if (lock) {
519         current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
520         current_autopilot->set_HeadingEnabled(true);
521     } else {
522         current_autopilot->set_HeadingEnabled(false);
523     }
524 }
525
526 /**
527  * Return true if the autopilot is locked to NAV1.
528  */
529 static bool
530 getAPNAV1Lock ()
531 {
532   return
533     (current_autopilot->get_HeadingEnabled() &&
534      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
535 }
536
537
538 /**
539  * Set the autopilot NAV1 lock.
540  */
541 static void
542 setAPNAV1Lock (bool lock)
543 {
544   if (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);
550   }
551 }
552
553 /**
554  * Get the autopilot autothrottle lock.
555  */
556 static bool
557 getAPAutoThrottleLock ()
558 {
559   return current_autopilot->get_AutoThrottleEnabled();
560 }
561
562
563 /**
564  * Set the autothrottle lock.
565  */
566 static void
567 setAPAutoThrottleLock (bool lock)
568 {
569   current_autopilot->set_AutoThrottleEnabled(lock);
570 }
571
572
573 // kludge
574 static double
575 getAPRudderControl ()
576 {
577     if (getAPHeadingLock())
578         return current_autopilot->get_TargetHeading();
579     else
580         return controls.get_rudder();
581 }
582
583 // kludge
584 static void
585 setAPRudderControl (double value)
586 {
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);
591     } else {
592         controls.set_rudder(value);
593     }
594 }
595
596 // kludge
597 static double
598 getAPElevatorControl ()
599 {
600   if (getAPAltitudeLock())
601       return current_autopilot->get_TargetAltitude();
602   else
603     return controls.get_elevator();
604 }
605
606 // kludge
607 static void
608 setAPElevatorControl (double value)
609 {
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);
614     } else {
615         controls.set_elevator(value);
616     }
617 }
618
619 // kludge
620 static double
621 getAPThrottleControl ()
622 {
623   if (getAPAutoThrottleLock())
624     return 0.0;                 // always resets
625   else
626     return controls.get_throttle(0);
627 }
628
629 // kludge
630 static void
631 setAPThrottleControl (double value)
632 {
633   if (getAPAutoThrottleLock())
634     current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
635   else
636     controls.set_throttle(0, value);
637 }
638
639
640 /**
641  * Get the current visibility (meters).
642  */
643 static double
644 getVisibility ()
645 {
646 #ifndef FG_OLD_WEATHER
647   return WeatherDatabase->getWeatherVisibility();
648 #else
649   return current_weather.get_visibility();
650 #endif
651 }
652
653
654 /**
655  * Set the current visibility (meters).
656  */
657 static void
658 setVisibility (double visibility)
659 {
660 #ifndef FG_OLD_WEATHER
661   WeatherDatabase->setWeatherVisibility(visibility);
662 #else
663   current_weather.set_visibility(visibility);
664 #endif
665 }
666
667 /**
668  * Get the current wind north velocity (feet/second).
669  */
670 static double
671 getWindNorth ()
672 {
673   return current_aircraft.fdm_state->get_V_north_airmass();
674 }
675
676
677 /**
678  * Set the current wind north velocity (feet/second).
679  */
680 static void
681 setWindNorth (double speed)
682 {
683   current_aircraft.fdm_state
684     ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
685 }
686
687
688 /**
689  * Get the current wind east velocity (feet/second).
690  */
691 static double
692 getWindEast ()
693 {
694   return current_aircraft.fdm_state->get_V_east_airmass();
695 }
696
697
698 /**
699  * Set the current wind east velocity (feet/second).
700  */
701 static void
702 setWindEast (double speed)
703 {
704   cout << "Set wind-east to " << speed << endl;
705   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
706                                                            speed,
707                                                            getWindDown());
708 }
709
710
711 /**
712  * Get the current wind down velocity (feet/second).
713  */
714 static double
715 getWindDown ()
716 {
717   return current_aircraft.fdm_state->get_V_down_airmass();
718 }
719
720
721 /**
722  * Set the current wind down velocity (feet/second).
723  */
724 static void
725 setWindDown (double speed)
726 {
727   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
728                                                            getWindEast(),
729                                                            speed);
730 }
731
732 static double
733 getFOV ()
734 {
735   return globals->get_current_view()->get_fov();
736 }
737
738 static void
739 setFOV (double fov)
740 {
741   globals->get_current_view()->set_fov( fov );
742 }
743
744
745 static void
746 setViewAxisLong (double axis)
747 {
748   axisLong = axis;
749 }
750
751 static void
752 setViewAxisLat (double axis)
753 {
754   axisLat = axis;
755 }
756
757
758 void
759 fgInitProps ()
760 {
761                                 // Simulation
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);
767
768                                 // Orientation
769   fgTie("/orientation/heading-magnetic", getHeadingMag);
770
771                                 // Engine
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);
777
778   //consumables
779   fgTie("/consumables/fuel/tank1/level", getTank1Fuel, setTank1Fuel, false);
780   fgTie("/consumables/fuel/tank2/level", getTank2Fuel, setTank2Fuel, false);
781
782                                 // Autopilot
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,
789         false);
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);
800
801                                 // Environment
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);
808
809                                 // View
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);
813 }
814
815
816 void
817 fgUpdateProps ()
818 {
819   _set_view_from_axes();
820 }
821
822
823 \f
824 ////////////////////////////////////////////////////////////////////////
825 // Save and restore.
826 ////////////////////////////////////////////////////////////////////////
827
828
829 /**
830  * Save the current state of the simulator to a stream.
831  */
832 bool
833 fgSaveFlight (ostream &output)
834 {
835   return writeProperties(output, globals->get_props());
836 }
837
838
839 /**
840  * Restore the current state of the simulator from a stream.
841  */
842 bool
843 fgLoadFlight (istream &input)
844 {
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();
851   } else {
852     SG_LOG(SG_INPUT, SG_ALERT, "Error restoring flight; aborted");
853     return false;
854   }
855
856   return true;
857 }
858
859 // end of fg_props.cxx
860