X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fnavradio.cxx;h=bde228991c0786444485f03347c6aa228c3d32e4;hb=cd20c6073c8f4341d0f82070abae14b765cc8630;hp=391e0a720a5862c3f9ebd160e25f62888c53bcfd;hpb=02f42b881649a0c37c75f2eea5192a41de7fdd3f;p=flightgear.git diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index 391e0a720..bde228991 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -61,28 +61,37 @@ static double sawtooth(double xx) return 4.0 * fabs(xx/4.0 + 0.25 - floor(xx/4.0 + 0.75)) - 1.0; } -// Calculate a unit vector in the horizontal tangent plane -// starting at the given "tail" of the vector and going off -// with the given heading. -static SGVec3d tangentVector(const SGGeod& tail, const SGVec3d& tail_xyz, - const double heading) +// Calculate a Cartesian unit vector in the +// local horizontal plane, i.e. tangent to the +// surface of the earth at the local ground zero. +// The tangent vector passes through the given +// and points forward along the given . +// The is given in degrees. +static SGVec3d tangentVector(const SGGeod& midpoint, const double heading) { -// The fudge factor here is presumably intended to improve -// numerical stability. I don't know if it is necessary. -// It gets divided out later. - double fudge(100.0); - SGGeod head; - double az2; // ignored - SGGeodesy::direct(tail, heading, fudge, head, az2); - head.setElevationM(tail.getElevationM()); +// The size of the delta is presumably chosen to give +// numerical stability. I don't know how the value was chosen. +// It probably doesn't matter much. It gets divided out. + double delta(100.0); // in meters + SGGeod head, tail; + double az2; // ignored + SGGeodesy::direct(midpoint, heading, delta, head, az2); + SGGeodesy::direct(midpoint, 180+heading, delta, tail, az2); + head.setElevationM(midpoint.getElevationM()); + tail.setElevationM(midpoint.getElevationM()); SGVec3d head_xyz = SGVec3d::fromGeod(head); - return (head_xyz - tail_xyz) * (1.0/fudge); + SGVec3d tail_xyz = SGVec3d::fromGeod(tail); +// Awkward formula here, needed because vector-by-scalar +// multiplication is defined, but not vector-by-scalar division. + return (head_xyz - tail_xyz) * (0.5/delta); } // Create a "serviceable" node with a default value of "true" -SGPropertyNode_ptr createServiceableProp(SGPropertyNode* aParent, const char* aName) +SGPropertyNode_ptr createServiceableProp(SGPropertyNode* aParent, + const char* aName) { - SGPropertyNode_ptr n = (aParent->getChild(aName, 0, true)->getChild("serviceable", 0, true)); + SGPropertyNode_ptr n = + aParent->getChild(aName, 0, true)->getChild("serviceable", 0, true); simgear::props::Type typ = n->getType(); if ((typ == simgear::props::NONE) || (typ == simgear::props::UNSPECIFIED)) { n->setBoolValue(true); @@ -599,9 +608,21 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig SGVec3d pos = aircraft - _gsCart; // relative vector from gs antenna to aircraft // The positive GS axis points along the runway in the landing direction, // toward the far end, not toward the approach area, so we need a - sign here: - double dot_h = -dot(pos, _gsAxis); - double dot_v = dot(pos, _gsVertical); - _gsDirect = atan2(dot_v, dot_h) * SGD_RADIANS_TO_DEGREES; + double comp_h = -dot(pos, _gsAxis); // component in horiz direction + double comp_v = dot(pos, _gsVertical); // component in vertical direction + //double comp_b = dot(pos, _gsBaseline); // component in baseline direction + //if (comp_b) {} // ... (useful for debugging) + +// _gsDirect represents the angle of elevation of the aircraft +// as seen by the GS transmitter. + _gsDirect = atan2(comp_v, comp_h) * SGD_RADIANS_TO_DEGREES; +// At this point, if the aircraft is centered on the glide slope, +// _gsDirect will be a small positive number, e.g. 3.0 degrees + +// Aim the branch cut straight down +// into the ground below the GS transmitter: + if (_gsDirect < -90.0) _gsDirect += 360.0; + double deflectionAngle = target_gs - _gsDirect; if (falseCoursesEnabledNode->getBoolValue()) { @@ -622,10 +643,17 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig } } +// GS is documented to be 1.4 degrees thick, +// i.e. plus or minus 0.7 degrees from the midline: + SG_CLAMP_RANGE(deflectionAngle, -0.7, 0.7); + +// Many older instrument xml frontends depend on +// the un-normalized gs-needle-deflection. +// Apparently the interface standard is plus or minus 3.5 "volts" +// for a full-scale deflection: _gsNeedleDeflection = deflectionAngle * 5.0; _gsNeedleDeflection *= signal_quality_norm; - SG_CLAMP_RANGE(deflectionAngle, -0.7, 0.7); _gsNeedleDeflectionNorm = (deflectionAngle / 0.7) * signal_quality_norm; ////////////////////////////////////////////////////////// @@ -912,7 +940,11 @@ void FGNavRadio::search() _navaid = nav; string identBuffer(4, ' '); if (nav) { - _dme = globals->get_dmelist()->findByFreq(freq, pos); + // use ILS signals as DME, otherwise search by frequency + if (nav->type()==FGPositioned::ILS) + _dme = nav; + else + _dme = globals->get_dmelist()->findByFreq(freq, pos); nav_id_node->setStringValue(nav->get_ident()); identBuffer = simgear::strutils::rpad( nav->ident(), 4, ' ' ); @@ -945,12 +977,12 @@ void FGNavRadio::search() // GS axis unit tangent vector // (along the runway): - _gsAxis = tangentVector(_gs->geod(), _gsCart, gs_radial); + _gsAxis = tangentVector(_gs->geod(), gs_radial); // GS baseline unit tangent vector - // (perpendicular to the runay along the ground) - SGVec3d baseline = tangentVector(_gs->geod(), _gsCart, gs_radial + 90.0); - _gsVertical = cross(baseline, _gsAxis); + // (transverse to the runay along the ground) + _gsBaseline = tangentVector(_gs->geod(), gs_radial + 90.0); + _gsVertical = cross(_gsBaseline, _gsAxis); } // of have glideslope } // of found LOC or ILS