FlightGear next
heading_indicator_fg.cxx
Go to the documentation of this file.
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/math/SGMath.hxx>
18
19#include <Main/fg_props.hxx>
20#include <Main/util.hxx>
21
23
24using std::string;
25
27 :
28 _last_heading_deg(0)
29{
30 readConfig(node, "heading-indicator-fg");
31}
32
36
40
41void
43{
44 string branch = nodePath();
45
46 _heading_in_node = fgGetNode("/orientation/heading-deg", true);
47
48 SGPropertyNode *node = fgGetNode(branch, true );
49 if( NULL == (_offset_node = node->getChild("offset-deg", 0, false)) ) {
50 _offset_node = node->getChild("offset-deg", 0, true);
51 _offset_node->setDoubleValue( -fgGetDouble("/environment/magnetic-variation-deg") );
52 }
53 _error_node = node->getChild("heading-bug-error-deg", 0, true);
54 _nav1_error_node = node->getChild("nav1-course-error-deg", 0, true);
55 _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
56 _off_node = node->getChild("off-flag", 0, true);
57 _spin_node = node->getChild("spin", 0, true);
58
60
61 reinit();
62}
63
64void
66{
67 _last_heading_deg = (_heading_in_node->getDoubleValue() +
68 _offset_node->getDoubleValue());
69 _gyro.reinit();
70}
71
72void
74{
75 // Get the spin from the gyro
76 _gyro.set_power_norm(isServiceableAndPowered());
77 _gyro.update(dt);
78 double spin = _gyro.get_spin_norm();
79 _spin_node->setDoubleValue( spin );
80
81 if ( isServiceableAndPowered() && spin >= 0.25) {
82 _off_node->setBoolValue(false);
83 } else {
84 _off_node->setBoolValue(true);
85 return;
86 }
87
88 // No time-based precession for a flux gate compass
89 // We just use offset to get the magvar
90 double offset = _offset_node->getDoubleValue();
91
92 // TODO: movement-induced error
93
94 // Next, calculate the indicated heading,
95 // introducing errors.
96 double factor = 100 * (spin * spin * spin * spin * spin * spin);
97 double heading = _heading_in_node->getDoubleValue();
98
99 // Now, we have to get the current
100 // heading and the last heading into
101 // the same range.
102 if ((heading - _last_heading_deg) > 180)
103 _last_heading_deg += 360;
104 if ((heading - _last_heading_deg) < -180)
105 _last_heading_deg -= 360;
106
107 heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
108 _last_heading_deg = heading;
109
110 heading += offset;
111
112 if (heading < 0)
113 heading += 360;
114 if (heading > 360)
115 heading -= 360;
116
117 _heading_out_node->setDoubleValue(heading);
118
119 // calculate the difference between the indicated heading
120 // and the selected heading for use with an autopilot
121 SGPropertyNode *bnode
122 = fgGetNode( "/autopilot/settings/heading-bug-deg", false );
123 double diff = 0;
124 if ( bnode ){
125 diff = bnode->getDoubleValue() - heading;
126 if ( diff < -180.0 ) { diff += 360.0; }
127 if ( diff > 180.0 ) { diff -= 360.0; }
128 _error_node->setDoubleValue( diff );
129 }
130 // calculate the difference between the indicated heading
131 // and the selected nav1 radial for use with an autopilot
132 SGPropertyNode *nnode
133 = fgGetNode( "/instrumentation/nav/radials/selected-deg", true );
134 double ndiff = 0;
135 if ( nnode ){
136 ndiff = nnode->getDoubleValue() - heading;
137 if ( ndiff < -180.0 ) { ndiff += 360.0; }
138 if ( ndiff > 180.0 ) { ndiff -= 360.0; }
139 _nav1_error_node->setDoubleValue( ndiff );
140 }
141
142
143}
144
145
146// Register the subsystem.
147#if 0
148SGSubsystemMgr::InstancedRegistrant<HeadingIndicatorFG> registrantHeadingIndicatorFG(
149 SGSubsystemMgr::FDM,
150 {{"instrumentation", SGSubsystemMgr::Dependency::HARD}});
151#endif
152
153// end of heading_indicator_fg.cxx
void initServicePowerProperties(SGPropertyNode *node)
void readConfig(SGPropertyNode *config, std::string defaultName)
std::string nodePath() const
bool isServiceableAndPowered() const
void update(double dt) override
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
Definition proptest.cpp:30
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27
double fgGetLowPass(double current, double target, double timeratio)
Move a value towards a target.
Definition util.cxx:46