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