]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/heading_indicator_fg.cxx
NavDisplay enhancements for Syd.
[flightgear.git] / src / Instrumentation / heading_indicator_fg.cxx
1 // heading_indicator_fg.cxx - a flux_gate compass.
2 // Based on the vacuum driven Heading Indicator Written by David Megginson, started 2002.
3 //
4 // Written by Vivian Meazza, started 2005.
5 //
6 // This file is in the Public Domain and comes with no warranty.
7
8 #ifdef HAVE_CONFIG_H
9 #  include "config.h"
10 #endif
11
12 #include <simgear/compiler.h>
13 #include <iostream>
14 #include <string>
15 #include <sstream>
16
17 #include <simgear/magvar/magvar.hxx>
18 #include <simgear/math/SGMath.hxx>
19
20 #include <Main/fg_props.hxx>
21 #include <Main/util.hxx>
22
23 #include "heading_indicator_fg.hxx"
24
25 using std::string;
26
27 HeadingIndicatorFG::HeadingIndicatorFG ( SGPropertyNode *node )
28     :
29     name("heading-indicator-fg"),        
30     num(0)
31 {
32     int i;
33     for ( i = 0; i < node->nChildren(); ++i ) {
34         SGPropertyNode *child = node->getChild(i);
35         string cname = child->getName();
36         string cval = child->getStringValue();
37         if ( cname == "name" ) {
38             name = cval;
39         } else if ( cname == "number" ) {
40             num = child->getIntValue();
41         } else {
42             SG_LOG( SG_INSTR, SG_WARN, "Error in flux-gate heading-indicator config logic" );
43             if ( name.length() ) {
44                 SG_LOG( SG_INSTR, SG_WARN, "Section = " << name );
45             }
46         }
47     }
48 }
49
50 HeadingIndicatorFG::HeadingIndicatorFG ()
51 {
52 }
53
54 HeadingIndicatorFG::~HeadingIndicatorFG ()
55 {
56 }
57
58 void
59 HeadingIndicatorFG::init ()
60 {
61     string branch;
62     branch = "/instrumentation/" + name;
63     
64         _heading_in_node = fgGetNode("/orientation/heading-deg", true);
65
66     SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
67     if( NULL == (_offset_node = node->getChild("offset-deg", 0, false)) ) {
68       _offset_node = node->getChild("offset-deg", 0, true);
69       _offset_node->setDoubleValue( -globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES );
70     }
71     _serviceable_node = node->getChild("serviceable", 0, true);
72         _error_node = node->getChild("heading-bug-error-deg", 0, true);
73         _nav1_error_node = node->getChild("nav1-course-error-deg", 0, true);
74     _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
75     _off_node         = node->getChild("off-flag", 0, true);
76
77     _last_heading_deg = (_heading_in_node->getDoubleValue() +
78                          _offset_node->getDoubleValue());
79         _electrical_node = fgGetNode("/systems/electrical/outputs/DG", true);
80 }
81
82 void
83 HeadingIndicatorFG::bind ()
84 {
85     std::ostringstream temp;
86     string branch;
87     temp << num;
88     branch = "/instrumentation/" + name + "[" + temp.str() + "]";
89
90     fgTie((branch + "/serviceable").c_str(),
91           &_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
92     fgTie((branch + "/spin").c_str(),
93           &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
94         
95 }
96
97 void
98 HeadingIndicatorFG::unbind ()
99 {
100     std::ostringstream temp;
101     string branch;
102     temp << num;
103     branch = "/instrumentation/" + name + "[" + temp.str() + "]";
104
105     fgUntie((branch + "/serviceable").c_str());
106     fgUntie((branch + "/spin").c_str());
107 }
108
109 void
110 HeadingIndicatorFG::update (double dt)
111 {
112                                 // Get the spin from the gyro
113          _gyro.set_power_norm(_electrical_node->getDoubleValue());
114         _gyro.update(dt);
115     double spin = _gyro.get_spin_norm();
116
117     if ( _electrical_node->getDoubleValue() > 0 && spin >= 0.25) {
118         _off_node->setBoolValue(false);
119     } else {
120         _off_node->setBoolValue(true);
121         return;
122     }
123
124                                 // No time-based precession     for a flux gate compass
125                                     // We just use offset to get the magvar
126         double offset = _offset_node->getDoubleValue();
127            
128                                 // TODO: movement-induced error
129
130                                 // Next, calculate the indicated heading,
131                                 // introducing errors.
132     double factor = 100 * (spin * spin * spin * spin * spin * spin);
133     double heading = _heading_in_node->getDoubleValue();
134
135                                 // Now, we have to get the current
136                                 // heading and the last heading into
137                                 // the same range.
138     if ((heading - _last_heading_deg) > 180)
139         _last_heading_deg += 360;
140     if ((heading - _last_heading_deg) < -180)
141         _last_heading_deg -= 360;
142
143     heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
144     _last_heading_deg = heading;
145
146         heading += offset;
147
148     if (heading < 0)
149         heading += 360;
150     if (heading > 360)
151         heading -= 360;
152
153     _heading_out_node->setDoubleValue(heading);
154
155                                      // calculate the difference between the indicated heading
156                                      // and the selected heading for use with an autopilot
157         static SGPropertyNode *bnode
158         = fgGetNode( "/autopilot/settings/heading-bug-deg", false );
159         double diff = 0;
160         if ( bnode ){
161                 diff = bnode->getDoubleValue() - heading;
162                 if ( diff < -180.0 ) { diff += 360.0; }
163                 if ( diff > 180.0 ) { diff -= 360.0; }
164                 _error_node->setDoubleValue( diff );
165         }   
166                                      // calculate the difference between the indicated heading
167                                      // and the selected nav1 radial for use with an autopilot
168         SGPropertyNode *nnode
169         = fgGetNode( "/instrumentation/nav/radials/selected-deg", true );
170         double ndiff = 0;
171         if ( nnode ){
172                 ndiff = nnode->getDoubleValue() - heading;
173                 if ( ndiff < -180.0 ) { ndiff += 360.0; }
174                 if ( ndiff > 180.0 ) { ndiff -= 360.0; }
175                 _nav1_error_node->setDoubleValue( ndiff );
176         }   
177
178
179 }
180
181 // end of heading_indicator_fg.cxx