FlightGear next
rad_alt.cxx
Go to the documentation of this file.
1// Radar Altimeter
2//
3// Written by Vivian MEAZZA, started Feb 2008.
4//
5//
6// Copyright (C) 2008 Vivian Meazza
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License as
10// published by the Free Software Foundation; either version 2 of the
11// License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful, but
14// WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21//
22//
23
24#ifdef HAVE_CONFIG_H
25# include "config.h"
26#endif
27
28#include "rad_alt.hxx"
29
30#include <simgear/scene/material/mat.hxx>
31
32
33#include <Main/fg_props.hxx>
34#include <Main/globals.hxx>
35#include <Scenery/scenery.hxx>
36
37
38RadarAltimeter::RadarAltimeter(SGPropertyNode *node) :
39 _time(0.0),
40 _interval(node->getDoubleValue("update-interval-sec", 1.0))
41{
42 _name = node->getStringValue("name", "radar-altimeter");
43 _num = node->getIntValue("number", 0);
44}
45
49
50void
52{
53
54 std::string branch = "/instrumentation/" + _name;
55 _Instrument = fgGetNode(branch, _num, true);
56
57 _sceneryLoaded = fgGetNode("/sim/sceneryloaded", true);
58 _serviceable_node = _Instrument->getNode("serviceable", true);
59
60 _user_alt_agl_node = fgGetNode("/position/altitude-agl-ft", true);
61 _rad_alt_warning_node = fgGetNode("/sim/alarms/rad-alt-warning", true);
62
63 _Instrument->setFloatValue("tilt",-85);
64 _Instrument->setStringValue("status","RA");
65
66 _Instrument->getDoubleValue("elev-limit", true);
67 _Instrument->getDoubleValue("elev-step-deg", true);
68 _Instrument->getDoubleValue("az-limit-deg", true);
69 _Instrument->getDoubleValue("az-step-deg", true);
70 _Instrument->getDoubleValue("max-range-m", true);
71 _Instrument->getDoubleValue("min-range-m", true);
72 _Instrument->getDoubleValue("tilt", true);
73 _Instrument->getDoubleValue("set-height-ft", true);
74 _Instrument->getDoubleValue("set-excursion-percent", true);
75
76 _antennaOffset = SGVec3d(_Instrument->getDoubleValue("antenna/x-offset-m"),
77 _Instrument->getDoubleValue("antenna/y-offset-m"),
78 _Instrument->getDoubleValue("antenna/z-offset-m"));
79}
80
81void
82RadarAltimeter::update (double delta_time_sec)
83{
84 if (!_sceneryLoaded->getBoolValue())
85 return;
86
87 if ( ! _serviceable_node->getBoolValue() ) {
88 _Instrument->setStringValue("status","");
89 return;
90 }
91
92 _time += delta_time_sec;
93 if (_time < _interval)
94 return;
95
96 _time -= _interval;
97
98 update_altitude();
99 updateSetHeight();
100}
101
102double
103RadarAltimeter::getDistanceAntennaToHit(const SGVec3d& nearestHit) const
104{
105 return norm(nearestHit - getCartAntennaPos());
106}
107
108void
109RadarAltimeter::updateSetHeight()
110{
111 double set_ht_ft = _Instrument->getDoubleValue("set-height-ft", 9999);
112 double set_excur = _Instrument->getDoubleValue("set-excursion-percent", 0);
113 if (set_ht_ft == 9999) {
114 _rad_alt_warning_node->setIntValue(9999);
115 return;
116 }
117
118 double radarAltFt = _min_radalt * SG_METER_TO_FEET;
119 if (radarAltFt < set_ht_ft * (100 - set_excur)/100)
120 _rad_alt_warning_node->setIntValue(-1);
121 else if (radarAltFt > set_ht_ft * (100 + set_excur)/100)
122 _rad_alt_warning_node->setIntValue(1);
123 else
124 _rad_alt_warning_node->setIntValue(0);
125}
126
127void
128RadarAltimeter::update_altitude()
129{
130 double el_limit = _Instrument->getDoubleValue("elev-limit", 15);
131 double el_step = _Instrument->getDoubleValue("elev-step-deg", 15);
132 double az_limit = _Instrument->getDoubleValue("az-limit-deg", 15);
133 double az_step = _Instrument->getDoubleValue("az-step-deg", 15);
134 double max_range = _Instrument->getDoubleValue("max-range-m", 1500);
135 double min_range = _Instrument->getDoubleValue("min-range-m", 0.001);
136
137
138 _min_radalt = max_range;
139 bool haveHit = false;
140 SGVec3d cartantennapos = getCartAntennaPos();
141
142 for(double brg = -az_limit; brg <= az_limit; brg += az_step){
143 for(double elev = el_limit; elev >= - el_limit; elev -= el_step){
144 SGVec3d userVec = rayVector(brg, elev);
145
146 SGVec3d nearestHit;
147 globals->get_scenery()->get_cart_ground_intersection(cartantennapos, userVec, nearestHit);
148 double measuredDistance = dist(cartantennapos, nearestHit);
149
150 if (measuredDistance >= min_range && measuredDistance <= max_range) {
151 if (measuredDistance < _min_radalt) {
152 _min_radalt = measuredDistance;
153 haveHit = true;
154 }
155 } // of hit within permissible range
156 } // of elevation step
157 } // of azimuth step
158
159 _Instrument->setDoubleValue("radar-altitude-ft", _min_radalt * SG_METER_TO_FEET);
160 if (!haveHit) {
161 _rad_alt_warning_node->setIntValue(9999);
162 }
163}
164
165SGVec3d
166RadarAltimeter::getCartAntennaPos() const
167{
168 double yaw, pitch, roll;
169 globals->get_aircraft_orientation(yaw, pitch, roll);
170
171 // Transform to the right coordinate frame, configuration is done in
172 // the x-forward, y-right, z-up coordinates (feet), computation
173 // in the simulation usual body x-forward, y-right, z-down coordinates
174 // (meters) )
175
176 // Transform the user position to the horizontal local coordinate system.
177 SGQuatd hlTrans = SGQuatd::fromLonLat(globals->get_aircraft_position());
178
179 // and postrotate the orientation of the user model wrt the horizontal
180 // local frame
181 hlTrans *= SGQuatd::fromYawPitchRollDeg(yaw,pitch,roll);
182
183 // The offset converted to the usual body fixed coordinate system
184 // rotated to the earth-fixed coordinates axis
185 SGVec3d ecfOffset = hlTrans.backTransform(_antennaOffset);
186
187 // Add the position offset of the user model to get the geocentered position
188 return globals->get_aircraft_position_cart() + ecfOffset;
189}
190
191SGVec3d RadarAltimeter::rayVector(double az, double el) const
192{
193 double yaw, pitch, roll;
194 globals->get_aircraft_orientation(yaw, pitch, roll);
195
196 double tilt = _Instrument->getDoubleValue("tilt");
197 bool roll_stab = false,
198 pitch_stab = false;
199
200 SGQuatd offset = SGQuatd::fromYawPitchRollDeg(az, el + tilt, 0);
201
202 // Transform the antenna position to the horizontal local coordinate system.
203 SGQuatd hlTrans = SGQuatd::fromLonLat(globals->get_aircraft_position());
204
205 // and postrotate the orientation of the radar wrt the horizontal
206 // local frame
207 hlTrans *= SGQuatd::fromYawPitchRollDeg(yaw,
208 pitch_stab ? 0 :pitch,
209 roll_stab ? 0 : roll);
210 hlTrans *= offset;
211
212 // now rotate the rotation vector back into the
213 // earth centered frames coordinates
214 SGVec3d angleaxis(1,0,0);
215 return hlTrans.backTransform(angleaxis);
216
217}
218
219
220// Register the subsystem.
221#if 0
222SGSubsystemMgr::InstancedRegistrant<RadarAltimeter> registrantRadarAltimeter(
223 SGSubsystemMgr::FDM,
224 {{"instrumentation", SGSubsystemMgr::Dependency::HARD}});
225#endif
SGGeod get_aircraft_position() const
Definition globals.cxx:611
void get_aircraft_orientation(double &heading, double &pitch, double &roll)
Definition globals.cxx:624
SGVec3d get_aircraft_position_cart() const
Definition globals.cxx:619
FGScenery * get_scenery() const
Definition globals.cxx:950
bool get_cart_ground_intersection(const SGVec3d &start, const SGVec3d &dir, SGVec3d &nearestHit, const osg::Node *butNotFrom=0)
Compute the nearest intersection point of the line starting from start going in direction dir with th...
Definition scenery.cxx:536
virtual ~RadarAltimeter()
Definition rad_alt.cxx:46
RadarAltimeter(SGPropertyNode *node)
Definition rad_alt.cxx:38
void init() override
Definition rad_alt.cxx:51
void update(double dt) override
Definition rad_alt.cxx:82
FGGlobals * globals
Definition globals.cxx:142
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27