23 _name(node->getStringValue(
"name",
"magnetic-compass")),
24 _num(node->getIntValue(
"number", 0))
26 SGPropertyNode_ptr n = node->getNode(
"deviation",
false );
28 SGPropertyNode_ptr deviation_table_node = n->getNode(
"table",
false );
29 if( NULL != deviation_table_node ) {
30 _deviation_table =
new SGInterpTable( deviation_table_node );
32 std::string deviation_node_name = n->getStringValue();
33 if( !deviation_node_name.empty() )
34 _deviation_node =
fgGetNode( deviation_node_name,
true );
38 _cfg_viscosity = node->getDoubleValue(
"fluid-viscosity", 8.2);
49 branch =
"/instrumentation/" + _name;
51 SGPropertyNode *node =
fgGetNode(branch, _num,
true );
52 _serviceable_node = node->getChild(
"serviceable", 0,
true);
53 _pitch_offset_node = node->getChild(
"pitch-offset-deg", 0,
true);
54 _roll_node =
fgGetNode(
"/orientation/roll-deg",
true);
55 _pitch_node =
fgGetNode(
"/orientation/pitch-deg",
true);
56 _heading_node =
fgGetNode(
"/orientation/heading-magnetic-deg",
true);
57 _beta_node =
fgGetNode(
"/orientation/side-slip-deg",
true);
58 _dip_node =
fgGetNode(
"/environment/magnetic-dip-deg",
true);
59 _x_accel_node =
fgGetNode(
"/accelerations/pilot/x-accel-fps_sec",
true);
60 _y_accel_node =
fgGetNode(
"/accelerations/pilot/y-accel-fps_sec",
true);
61 _z_accel_node =
fgGetNode(
"/accelerations/pilot/z-accel-fps_sec",
true);
62 _out_node = node->getChild(
"indicated-heading-deg", 0,
true);
63 _roll_out_node = node->getChild(
"roll-deg", 0,
true);
64 _pitch_out_node = node->getChild(
"pitch-deg", 0,
true);
65 _fluid_viscosity = node->getChild(
"fluid-viscosity", 0,
true);
88 if (!_serviceable_node->getBoolValue())
98 double fluid_damping = 5.0/8.0 * _fluid_viscosity->getDoubleValue() * 10;
109 if (fabs(_beta_node->getDoubleValue()) > 12.0) {
135 double phi = _roll_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
138 double theta = _pitch_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS
139 + _pitch_offset_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
142 double psi = _heading_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
145 double mu = _dip_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
160 double x_accel_g = _x_accel_node->getDoubleValue() / 32;
161 double y_accel_g = _y_accel_node->getDoubleValue() / 32;
164 theta -= 0.07 * x_accel_g;
165 phi -= 0.07 * y_accel_g;
168 double d = -_z_accel_node->getDoubleValue();
169 if (d < 1.0) d = 1.0;
170 double x_factor_norm = _x_accel_node->getDoubleValue() / d * 10.0;
171 double y_factor_norm = _y_accel_node->getDoubleValue() / d * 10.0;
173 double roll = phi * SGD_RADIANS_TO_DEGREES * abs(y_factor_norm);
175 _roll_out_node->setDoubleValue(roll);
178 double pitch = -theta * SGD_RADIANS_TO_DEGREES * abs(x_factor_norm);
180 _pitch_out_node->setDoubleValue(pitch);
189 double sin_phi = sin(phi);
190 double sin_theta = sin(theta);
191 double sin_mu = sin(mu);
192 double cos_theta = cos(theta);
193 double cos_psi = cos(psi);
194 double cos_mu = cos(mu);
196 double a = cos(phi) * sin(psi) * cos_mu
197 - sin_phi * cos_theta * sin_mu
198 - sin_phi* sin_theta * cos_mu * cos_psi;
200 double b = cos_theta * cos_psi * cos(mu)
201 - sin_theta * sin_mu;
205 double target_deg = atan2(a, b) * SGD_RADIANS_TO_DEGREES;
207 if( _deviation_node ) {
208 target_deg -= _deviation_node->getDoubleValue();
209 }
else if( _deviation_table ) {
210 target_deg -= _deviation_table->interpolate( SGMiscd::normalizePeriodic( 0.0, 360.0, target_deg ) );
213 double old_deg = _out_node->getDoubleValue();
215 while ((target_deg - old_deg) > 180.0)
217 while ((target_deg - old_deg) < -180.0)
226 double error = target_deg - old_deg;
227 _rate_degps =
fgGetLowPass(_rate_degps, error, delta_time_sec / 5.0);
228 double indicated_deg = old_deg + _rate_degps * delta_time_sec;
229 SG_NORMALIZE_RANGE(indicated_deg, 0.0, 360.0);
232 _out_node->setDoubleValue(indicated_deg);