FlightGear next
navrecord.cxx
Go to the documentation of this file.
1// navrecord.cxx -- generic vor/dme/ndb class
2//
3// Written by Curtis Olson, started May 2004.
4//
5// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License as
9// published by the Free Software Foundation; either version 2 of the
10// License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful, but
13// WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20//
21// $Id$
22
23#ifdef HAVE_CONFIG_H
24 #include "config.h"
25#endif
26
27#include <istream>
28
29#include <simgear/io/iostreams/sgstream.hxx>
30#include <simgear/misc/sg_path.hxx>
31#include <simgear/structure/exception.hxx>
32#include <simgear/debug/logstream.hxx>
33#include <simgear/sg_inlines.h>
34#include <simgear/props/props.hxx>
35
36
37#include <Navaids/navrecord.hxx>
38#include <Navaids/navdb.hxx>
39#include <Airports/runways.hxx>
40#include <Airports/airport.hxx>
42#include <Main/fg_props.hxx>
43
44FGNavRecord::FGNavRecord(PositionedID aGuid, Type aTy, const std::string& aIdent,
45 const std::string& aName, const SGGeod& aPos,
46 int aFreq, int aRange, double aMultiuse, PositionedID aRunway) :
47 FGPositioned(aGuid, aTy, aIdent, aPos),
48 freq(aFreq),
49 range(aRange),
50 multiuse(aMultiuse),
51 mName(aName),
52 mRunway(aRunway),
53 mColocated(0),
54 serviceable(true)
55{
56}
57
59{
60 return loadById<FGRunway>(mRunway);
61}
62
64{
65 if (!mRunway) {
66 return 6.0;
67 }
68
69 FGRunway* rwy = runway();
70 SGVec3d thresholdCart(SGVec3d::fromGeod(rwy->threshold()));
71 double axisLength = dist(cart(), thresholdCart);
72 double landingLength = dist(thresholdCart, SGVec3d::fromGeod(rwy->end()));
73
74// Reference: http://dcaa.slv.dk:8000/icaodocs/
75// ICAO standard width at threshold is 210 m = 689 feet = approx 700 feet.
76// ICAO 3.1.1 half course = DDM = 0.0775
77// ICAO 3.1.3.7.1 Sensitivity 0.00145 DDM/m at threshold
78// implies peg-to-peg of 214 m ... we will stick with 210.
79// ICAO 3.1.3.7.1 "Course sector angle shall not exceed 6 degrees."
80
81// Very short runway: less than 1200 m (4000 ft) landing length:
82 if (landingLength < 1200.0) {
83// ICAO fudges localizer sensitivity for very short runways.
84// This produces a non-monotonic sensitivity-versus length relation.
85 axisLength += 1050.0;
86 }
87
88// Example: very short: San Diego KMYF (Montgomery Field) ILS RWY 28R
89// Example: short: Tom's River KMJX (Robert J. Miller) ILS RWY 6
90// Example: very long: Denver KDEN (Denver) ILS RWY 16R
91 double raw_width = 210.0 / axisLength * SGD_RADIANS_TO_DEGREES;
92 return raw_width < 6.0? raw_width : 6.0;
93
94}
95
97{
98 return (mColocated > 0);
99}
100
101
102
104{
105 if (mType != VOR)
106 return false;
107
108 return mName.find(" VORTAC") != std::string::npos;
109}
110
112{
113 mColocated = other;
114}
115
117{
118 return mColocated;
119}
120
121void FGNavRecord::updateFromXML(const SGGeod& geod, double heading)
122{
124 multiuse = heading;
125}
126
128{
129 if (type() != FGPositioned::GS) {
130 SG_LOG(SG_NAVAID, SG_DEV_WARN, "called glideSlopeAngleDeg on non-GS navaid:" << ident());
131 return 0.0;
132 }
133
134 const auto tmp = static_cast<int>(get_multiuse() / 1000.0);
135 return static_cast<double>(tmp) / 100.0;
136}
137
138//------------------------------------------------------------------------------
140 Type type,
141 const std::string& ident,
142 const std::string& name,
143 const SGGeod& aPos,
144 int freq,
145 int range,
146 double multiuse,
147 PositionedID aRunway ):
148 FGNavRecord(aGuid, type, ident, name, aPos, freq, range, multiuse, aRunway),
149 _initial_elevation_ft(aPos.getElevationFt())
150{
151
152}
153
154//------------------------------------------------------------------------------
155const SGGeod& FGMobileNavRecord::geod() const
156{
157 const_cast<FGMobileNavRecord*>(this)->updatePos();
158 return FGNavRecord::geod();
159}
160
161//------------------------------------------------------------------------------
162const SGVec3d& FGMobileNavRecord::cart() const
163{
164 const_cast<FGMobileNavRecord*>(this)->updatePos();
165 return FGNavRecord::cart();
166}
167
168//------------------------------------------------------------------------------
170{
171 _vehicle_node.clear();
172}
173
175{
176 _vehicle_node.clear();
177
178 SGPropertyNode* ai_branch = fgGetNode("ai/models");
179 if( !ai_branch )
180 {
181 SG_LOG( SG_NAVAID,
182 SG_INFO,
183 "Can not update mobile navaid position (no ai/models branch)" );
184 return;
185 }
186
187 const std::string& nav_name = name();
188
189 // Try any aircraft carriers first
190 simgear::PropertyList carrier = ai_branch->getChildren("carrier");
191 for(size_t i = 0; i < carrier.size(); ++i)
192 {
193 const std::string carrier_name = carrier[i]->getStringValue("name");
194
195 if( carrier_name.empty()
196 || nav_name.find(carrier_name) == std::string::npos )
197 continue;
198
199 _vehicle_node = carrier[i];
200 return;
201 }
202
203 // Now the tankers
204 const std::string tanker_branches[] = {
205 // AI tankers
206 "tanker",
207 // And finally mp tankers
208 "multiplayer"
209 };
210
211 for(size_t i = 0; i < sizeof(tanker_branches)/sizeof(tanker_branches[0]); ++i)
212 {
213 simgear::PropertyList tanker = ai_branch->getChildren(tanker_branches[i]);
214 for(size_t j = 0; j < tanker.size(); ++j)
215 {
216 const std::string callsign = tanker[j]->getStringValue("callsign");
217
218 if( callsign.empty()
219 || nav_name.find(callsign) == std::string::npos )
220 continue;
221
222 _vehicle_node = tanker[j];
223 return;
224 }
225 }
226}
227
228//------------------------------------------------------------------------------
230{
231 SGTimeStamp now = SGTimeStamp::now();
232 if( (now - _last_vehicle_update).toSecs() > (_vehicle_node.valid() ? 5 : 2) )
233 {
236 }
237
238 if( _vehicle_node.valid() )
239 modifyPosition(SGGeod::fromDegFt(
240 _vehicle_node->getDoubleValue("position/longitude-deg"),
241 _vehicle_node->getDoubleValue("position/latitude-deg"),
242 _vehicle_node->getNameString() == "carrier"
244 : _vehicle_node->getDoubleValue("position/altitude-ft")
245 ));
246 else
248
249 serviceable = _vehicle_node.valid();
250}
251
252//------------------------------------------------------------------------------
254 channel(""),
255 freq(0)
256
257{
258}
259
260std::istream&
261operator >> ( std::istream& in, FGTACANRecord& n )
262{
263 in >> n.channel >> n.freq ;
264 //getline( in, n.name );
265
266 return in;
267}
#define i(x)
SGSharedPtr< FGRunway > FGRunwayRef
virtual const SGGeod & geod() const
virtual const SGVec3d & cart() const
The cartesian position associated with this object.
FGMobileNavRecord(PositionedID aGuid, Type type, const std::string &ident, const std::string &name, const SGGeod &aPos, int freq, int range, double multiuse, PositionedID aRunway)
double _initial_elevation_ft
SGTimeStamp _last_vehicle_update
SGPropertyNode_ptr _vehicle_node
FGNavRecord(PositionedID aGuid, Type type, const std::string &ident, const std::string &name, const SGGeod &aPos, int freq, int range, double multiuse, PositionedID aRunway)
Definition navrecord.cxx:44
void setColocatedDME(PositionedID other)
bool hasDME() const
Definition navrecord.cxx:96
virtual const std::string & name() const
Return the name of this positioned.
Definition navrecord.hxx:85
double get_multiuse() const
Definition navrecord.hxx:78
double glideSlopeAngleDeg() const
extract the glide slope angle, in degrees, from the multiuse field Return 0.0 for non-GS navaids (inc...
PositionedID colocatedDME() const
double localizerWidth() const
return the localizer width, in degrees computation is based up ICAO stdandard width at the runway thr...
Definition navrecord.cxx:63
bool serviceable
Definition navrecord.hxx:56
FGRunwayRef runway() const
Retrieve the runway this navaid is associated with (for ILS/LOC/GS)
Definition navrecord.cxx:58
void updateFromXML(const SGGeod &geod, double heading)
bool isVORTAC() const
FGPositioned(PositionedID aGuid, Type ty, const std::string &aIdent, const SGGeod &aPos)
void modifyPosition(const SGGeod &newPos)
virtual const SGGeod & geod() const
virtual const SGVec3d & cart() const
The cartesian position associated with this object.
void invalidatePosition()
static SGSharedPtr< T > loadById(PositionedID id)
const Type mType
Type type() const
const std::string & ident() const
SGGeod end() const
Get the 'far' end - this is equivalent to calling pointOnCenterline(lengthFt());.
Definition runways.cxx:94
SGGeod threshold() const
Get the (possibly displaced) threshold point.
Definition runways.cxx:99
FGTACANRecord(void)
std::istream & operator>>(std::istream &in, FGTACANRecord &n)
int64_t PositionedID
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27