]> git.mxchange.org Git - flightgear.git/blobdiff - src/Instrumentation/rad_alt.cxx
Reset: work with threaded OSG modes
[flightgear.git] / src / Instrumentation / rad_alt.cxx
index e26c24763415342e037cf21ca8ed225be71719ee..0ab143bbd847274afc92825b58be53b08f6d0c2b 100644 (file)
 #  include "config.h"
 #endif
 
+#include "rad_alt.hxx"
+
+#include <simgear/scene/material/mat.hxx>
+
+
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
-#include "rad_alt.hxx"
+#include <Scenery/scenery.hxx>
 
 
-radAlt::radAlt(SGPropertyNode *node) : agRadar(node) 
+RadarAltimeter::RadarAltimeter(SGPropertyNode *node) :
+    _time(0.0),
+    _interval(node->getDoubleValue("update-interval-sec", 1.0))
 {
-
     _name = node->getStringValue("name", "radar-altimeter");
     _num = node->getIntValue("number", 0);
-
 }
 
-radAlt::~radAlt()
+RadarAltimeter::~RadarAltimeter()
 {
 }
 
 void
-radAlt::init ()
+RadarAltimeter::init ()
 {
-    agRadar::init();
+
+    std::string branch = "/instrumentation/" + _name;
+    _Instrument = fgGetNode(branch.c_str(), _num, true);
+
+    _sceneryLoaded = fgGetNode("/sim/sceneryloaded", true);
+    _serviceable_node = _Instrument->getNode("serviceable", true);
 
     _user_alt_agl_node     = fgGetNode("/position/altitude-agl-ft", true);
     _rad_alt_warning_node   = fgGetNode("/sim/alarms/rad-alt-warning", true);
 
-    //// those properties are used by a radar instrument of a MFD
-    //// input switch = OFF | TST | STBY | ON
-    //// input mode = WX | WXA | MAP | TW
-    //// output status = STBY | TEST | WX | WXA | MAP | blank
-    //// input lightning = true | false
-    //// input TRK = +/- n degrees
-    //// input TILT = +/- n degree
-    //// input autotilt = true | false
-    //// input range = n nm (20/40/80)
-    //// input display-mode = arc | rose | map | plan
-
     _Instrument->setFloatValue("tilt",-85);
     _Instrument->setStringValue("status","RA");
 
-    //_Instrument->setIntValue("mode-control", 10);
-
     _Instrument->getDoubleValue("elev-limit", true);
     _Instrument->getDoubleValue("elev-step-deg", true);
     _Instrument->getDoubleValue("az-limit-deg", true);
@@ -76,145 +73,146 @@ radAlt::init ()
     _Instrument->getDoubleValue("set-height-ft", true);
     _Instrument->getDoubleValue("set-excursion-percent", true);
 
-    _Instrument->setDoubleValue("hit/brg-deg", 0);
-    _Instrument->setDoubleValue("hit/range-m", 0);
-    _Instrument->setStringValue("hit/material", "");
-    _Instrument->setDoubleValue("hit/bumpiness", 0);
-
-
-
-    _Instrument->removeChild("terrain-warning");
-    _Instrument->removeChild("mode-control");
-    _Instrument->removeChild("limit-deg");
-    _Instrument->removeChild("reference-range-nm");
-    _Instrument->removeChild("heading-marker");
-    _Instrument->removeChild("display-controls");
-    _Instrument->removeChild("font");
-
-    //cout << " radar alt init done" << endl;
+    _antennaOffset = SGVec3d(_Instrument->getDoubleValue("antenna/x-offset-m"),
+                             _Instrument->getDoubleValue("antenna/y-offset-m"),
+                             _Instrument->getDoubleValue("antenna/z-offset-m"));
 }
 
 void
-radAlt::update (double delta_time_sec)
+RadarAltimeter::update (double delta_time_sec)
 {
-    if ( ! _sim_init_done ) {
-
-        if ( ! fgGetBool("sim/sceneryloaded", false) )
-            return;
-
-        _sim_init_done = true;
-    }
+    if (!_sceneryLoaded->getBoolValue())
+        return;
 
-    if ( !_odg || ! _serviceable_node->getBoolValue() ) {
+    if ( ! _serviceable_node->getBoolValue() ) {
         _Instrument->setStringValue("status","");
         return;
     }
 
     _time += delta_time_sec;
-
     if (_time < _interval)
         return;
 
-    _time = 0.0;
+    _time -= _interval;
+
     update_altitude();
+    updateSetHeight();
 }
 
-
-
 double
-radAlt::getDistanceAntennaToHit(SGVec3d nearestHit) const 
+RadarAltimeter::getDistanceAntennaToHit(const SGVec3d& nearestHit) const
 {
-    //calculate the distance antenna to hit
-
-    SGVec3d cartantennapos = getCartAntennaPos();;
+    return norm(nearestHit - getCartAntennaPos());
+}
 
-    SGVec3d diff = nearestHit - cartantennapos;
-    double distance = norm(diff);
-    return distance ;
+void
+RadarAltimeter::updateSetHeight()
+{
+    double set_ht_ft   = _Instrument->getDoubleValue("set-height-ft", 9999);
+    double set_excur   = _Instrument->getDoubleValue("set-excursion-percent", 0);
+    if (set_ht_ft == 9999) {
+        _rad_alt_warning_node->setIntValue(9999);
+        return;
+    }
+    
+    double radarAltFt = _min_radalt * SG_METER_TO_FEET;
+    if (radarAltFt < set_ht_ft * (100 - set_excur)/100)
+        _rad_alt_warning_node->setIntValue(-1);
+    else if (radarAltFt > set_ht_ft * (100 + set_excur)/100)
+        _rad_alt_warning_node->setIntValue(1);
+    else
+        _rad_alt_warning_node->setIntValue(0);
 }
 
 void
-radAlt::update_altitude()
+RadarAltimeter::update_altitude()
 {
-//    int mode           = _radar_mode_control_node->getIntValue();
-//    double tilt        = _Instrument->getDoubleValue("tilt", -85);
     double el_limit    = _Instrument->getDoubleValue("elev-limit", 15);
     double el_step     = _Instrument->getDoubleValue("elev-step-deg", 15);
     double az_limit    = _Instrument->getDoubleValue("az-limit-deg", 15);
     double az_step     = _Instrument->getDoubleValue("az-step-deg", 15);
     double max_range   = _Instrument->getDoubleValue("max-range-m", 1500);
     double min_range   = _Instrument->getDoubleValue("min-range-m", 0.001);
-    double set_ht_ft   = _Instrument->getDoubleValue("set-height-ft", 9999);
-    double set_excur   = _Instrument->getDoubleValue("set-excursion-percent", 0);
 
-    _min_radalt = max_range;
 
-    setUserPos();
-    setAntennaPos();
+    _min_radalt = max_range;
+    bool haveHit = false;
     SGVec3d cartantennapos = getCartAntennaPos();
 
     for(double brg = -az_limit; brg <= az_limit; brg += az_step){
         for(double elev = el_limit; elev >= - el_limit; elev -= el_step){
-            setUserVec(brg, elev);
+            SGVec3d userVec = rayVector(brg, elev);
 
             SGVec3d nearestHit;
-            globals->get_scenery()->get_cart_ground_intersection(cartantennapos, uservec, nearestHit);
-            SGGeodesy::SGCartToGeod(nearestHit, hitpos);
-
-            double radalt = getDistanceAntennaToHit(nearestHit);
-            double course1, course2, distance;
-
-            SGGeodesy::inverse(hitpos, antennapos, course1, course2, distance);
-            _Instrument->setDoubleValue("hit/altitude-agl-ft",
-                     _user_alt_agl_node->getDoubleValue());
-
-            if (radalt >= min_range && radalt <= max_range) {
-                getMaterial();
-                
-                if (radalt < _min_radalt)
-                    _min_radalt = radalt;
-
-                _Instrument->setDoubleValue("radar-altitude-ft", _min_radalt * SG_METER_TO_FEET);
-                _Instrument->setDoubleValue("hit/radar-altitude-ft", radalt * SG_METER_TO_FEET);
-                _Instrument->setDoubleValue("hit/brg-deg", course2);
-                _Instrument->setDoubleValue("hit/range-m", distance);
-                _Instrument->setStringValue("hit/material", _mat_name.c_str());
-                _Instrument->setDoubleValue("hit/bumpiness", _bumpinessFactor);
-
-                if (set_ht_ft!= 9999){
-
-                    if (_min_radalt * SG_METER_TO_FEET < set_ht_ft * (100 - set_excur)/100)
-                        _rad_alt_warning_node->setIntValue(-1);
-                    else if (_min_radalt * SG_METER_TO_FEET > set_ht_ft * (100 + set_excur)/100)
-                        _rad_alt_warning_node->setIntValue(1);
-                    else
-                        _rad_alt_warning_node->setIntValue(0);
-
-                } else
-                    _rad_alt_warning_node->setIntValue(9999);
-
-            } else {
-                _rad_alt_warning_node->setIntValue(9999);
-                _Instrument->setDoubleValue("radar-altitude-ft", _min_radalt * SG_METER_TO_FEET);
-                _Instrument->setDoubleValue("hit/radar-altitude-ft",0);
-                _Instrument->setDoubleValue("hit/brg-deg", 0);
-                _Instrument->setDoubleValue("hit/range-m", 0);
-                _Instrument->setStringValue("hit/material", "");
-                _Instrument->setDoubleValue("hit/bumpiness", 0);
-            }
-
-            //cout  << "usr hdg " << _user_hdg_deg_node->getDoubleValue()
-            //    << " ant brg " << course2 
-            //    << " elev " << _Instrument->getDoubleValue("tilt")
-            //    << " gnd rng nm " << distance * SG_METER_TO_NM
-            //    << " ht " << hitpos.getElevationFt()
-            //    << " mat " << _mat_name
-            //    << " solid " << _solid
-            //    << " bumpiness " << _bumpinessFactor
-            //    << endl;
-
-        }
+            globals->get_scenery()->get_cart_ground_intersection(cartantennapos, userVec, nearestHit);
+            double measuredDistance = dist(cartantennapos, nearestHit);
+
+            if (measuredDistance >= min_range && measuredDistance <= max_range) {                
+                if (measuredDistance < _min_radalt) {
+                    _min_radalt = measuredDistance;
+                    haveHit = true;
+                }
+            } // of hit within permissible range
+        } // of elevation step
+    } // of azimuth step
+    
+    _Instrument->setDoubleValue("radar-altitude-ft", _min_radalt * SG_METER_TO_FEET);
+    if (!haveHit) {
+        _rad_alt_warning_node->setIntValue(9999);
     }
 }
 
+SGVec3d
+RadarAltimeter::getCartAntennaPos() const
+{
+    double yaw, pitch, roll;
+    globals->get_aircraft_orientation(yaw, pitch, roll);
+    
+    // Transform to the right coordinate frame, configuration is done in
+    // the x-forward, y-right, z-up coordinates (feet), computation
+    // in the simulation usual body x-forward, y-right, z-down coordinates
+    // (meters) )
+    
+    // Transform the user position to the horizontal local coordinate system.
+    SGQuatd hlTrans = SGQuatd::fromLonLat(globals->get_aircraft_position());
+    
+    // and postrotate the orientation of the user model wrt the horizontal
+    // local frame
+    hlTrans *= SGQuatd::fromYawPitchRollDeg(yaw,pitch,roll);
+    
+    // The offset converted to the usual body fixed coordinate system
+    // rotated to the earth-fixed coordinates axis
+    SGVec3d ecfOffset = hlTrans.backTransform(_antennaOffset);
+    
+    // Add the position offset of the user model to get the geocentered position
+    return globals->get_aircraft_position_cart() + ecfOffset;
+}
+
+SGVec3d RadarAltimeter::rayVector(double az, double el) const
+{
+    double yaw, pitch, roll;
+    globals->get_aircraft_orientation(yaw, pitch, roll);
+    
+    double tilt = _Instrument->getDoubleValue("tilt");
+    bool roll_stab = false,
+        pitch_stab = false;
+    
+    SGQuatd offset = SGQuatd::fromYawPitchRollDeg(az, el + tilt, 0);
+    
+    // Transform the antenna position to the horizontal local coordinate system.
+    SGQuatd hlTrans = SGQuatd::fromLonLat(globals->get_aircraft_position());
+    
+    // and postrotate the orientation of the radar wrt the horizontal
+    // local frame
+    hlTrans *= SGQuatd::fromYawPitchRollDeg(yaw,
+                                            pitch_stab ? 0 :pitch,
+                                            roll_stab ? 0 : roll);
+    hlTrans *= offset;
+    
+    // now rotate the rotation vector back into the
+    // earth centered frames coordinates
+    SGVec3d angleaxis(1,0,0);
+    return hlTrans.backTransform(angleaxis);
+    
+}