FlightGear next
heading_indicator.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: heading_indicator.cxx
3 * SPDX-FileComment: a vacuum-powered heading indicator.
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * SPDX-FileContributor: Written by David Megginson, started 2002.
6 */
7
8#include "config.h"
9
10#include "heading_indicator.hxx"
11
12#include <simgear/compiler.h>
13#include <simgear/sg_inlines.h>
14#include <simgear/math/SGMath.hxx>
15#include <iostream>
16#include <string>
17#include <sstream>
18
19#include <Main/fg_props.hxx>
20#include <Main/util.hxx>
21
22HeadingIndicator::HeadingIndicator ( SGPropertyNode *node )
23 :
24 _name(node->getStringValue("name", "heading-indicator")),
25 _num(node->getIntValue("number", 0)),
26 _suction(node->getStringValue("suction", "/systems/vacuum/suction-inhg"))
27{
28}
29
33
34void
36{
37 std::string branch;
38 branch = "/instrumentation/" + _name;
39
40 SGPropertyNode *node = fgGetNode(branch, _num, true );
41 if( NULL == (_offset_node = node->getChild("offset-deg", 0, false)) ) {
42 _offset_node = node->getChild("offset-deg", 0, true);
43 _offset_node->setDoubleValue( -fgGetDouble("/environment/magnetic-variation-deg") );
44 }
45 _heading_in_node = fgGetNode("/orientation/heading-deg", true);
46 _suction_node = fgGetNode(_suction, true);
47 _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
48 _heading_bug_error_node = node->getChild("heading-bug-error-deg", 0, true);
49 _heading_bug_node = node->getChild("heading-bug-deg", 0, true);
50
51 reinit();
52}
53
54void
56{
57 _last_heading_deg = (_heading_in_node->getDoubleValue() +
58 _offset_node->getDoubleValue());
59 _gyro.reinit();
60}
61
62void
64{
65 std::ostringstream temp;
66 std::string branch;
67 temp << _num;
68 branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
69
70 fgTie((branch + "/serviceable").c_str(),
72 fgTie((branch + "/spin").c_str(),
74}
75
76void
78{
79 std::ostringstream temp;
80 std::string branch;
81 temp << _num;
82 branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
83
84 fgUntie((branch + "/serviceable").c_str());
85 fgUntie((branch + "/spin").c_str());
86}
87
88void
90{
91 // Get the spin from the gyro
92 _gyro.set_power_norm(_suction_node->getDoubleValue()/5.0);
93 _gyro.update(dt);
94 double spin = _gyro.get_spin_norm();
95
96 // Next, calculate time-based precession
97 double offset = _offset_node->getDoubleValue();
98 offset -= dt * (0.25 / 60.0); // 360deg/day
99 SG_NORMALIZE_RANGE(offset, -360.0, 360.0);
100
101 // TODO: movement-induced error
102
103 // Next, calculate the indicated heading,
104 // introducing errors.
105 double factor = 100 * (spin * spin * spin * spin * spin * spin);
106 double heading = _heading_in_node->getDoubleValue();
107
108 // Now, we have to get the current
109 // heading and the last heading into
110 // the same range.
111 while ((heading - _last_heading_deg) > 180)
112 _last_heading_deg += 360;
113 while ((heading - _last_heading_deg) < -180)
114 _last_heading_deg -= 360;
115
116 heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
117 _last_heading_deg = heading;
118
119 heading += offset;
120 SG_NORMALIZE_RANGE(heading, 0.0, 360.0);
121
122 _heading_out_node->setDoubleValue(heading);
123
124 // Calculate heading bug error normalized to +/- 180.0
125 double heading_bug = _heading_bug_node->getDoubleValue();
126 double diff = heading_bug - heading;
127
128 SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
129 _heading_bug_error_node->setDoubleValue( diff );
130}
131
132
133// Register the subsystem.
134#if 0
135SGSubsystemMgr::InstancedRegistrant<HeadingIndicator> registrantHeadingIndicator(
136 SGSubsystemMgr::FDM,
137 {{"instrumentation", SGSubsystemMgr::Dependency::HARD}});
138#endif
139
140// end of heading_indicator.cxx
virtual void set_spin_norm(double spin_norm)
Set the gyro's current spin.
Definition gyro.cxx:65
virtual bool is_serviceable() const
Test if the gyro is serviceable.
Definition gyro.cxx:71
virtual double get_spin_norm() const
Get the gyro's current spin.
Definition gyro.cxx:59
virtual void set_serviceable(bool serviceable)
Set the gyro's serviceability.
Definition gyro.cxx:77
void reinit() override
void bind() override
void update(double dt) override
void unbind() override
void init() override
void fgUntie(const char *name)
Untie a property from an external data source.
Definition fg_props.cxx:634
void fgTie(const char *name, V(*getter)(), void(*setter)(V)=0, bool useDefault=true)
Tie a property to a pair of simple functions.
Definition fg_props.hxx:751
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