]> git.mxchange.org Git - flightgear.git/commitdiff
New TCAS display mode for wxradar.
authorThorstenB <brehmt@gmail.com>
Wed, 29 Dec 2010 21:10:54 +0000 (22:10 +0100)
committerThorstenB <brehmt@gmail.com>
Fri, 25 Feb 2011 20:12:35 +0000 (21:12 +0100)
- new mode to display traffic in TCAS-style
- select symbols according to TCAS-threat level

src/Instrumentation/wxradar.cxx
src/Instrumentation/wxradar.hxx

index c3b37d2cdc85f488e24a52cf378f34a8d2ae3040..d4d6d890c8f4028d8719590837d45d1d4ad39c9c 100644 (file)
@@ -69,18 +69,29 @@ using std::endl;
 static const float UNIT = 1.0f / 8.0f;  // 8 symbols in a row/column in the texture
 static const char *DEFAULT_FONT = "typewriter.txf";
 
-
 wxRadarBg::wxRadarBg(SGPropertyNode *node) :
     _name(node->getStringValue("name", "radar")),
     _num(node->getIntValue("number", 0)),
     _time(0.0),
     _interval(node->getDoubleValue("update-interval-sec", 1.0)),
+    _elapsed_time(0),
+    _persistance(0),
     _sim_init_done(false),
     _odg(0),
-    _last_switchKnob("off"),
+    _range_nm(0),
+    _scale(0),
+    _angle_offset(0),
+    _view_heading(0),
+    _x_offset(0),
+    _y_offset(0),
+    _radar_ref_rng(0),
+    _lat(0),
+    _lon(0),
     _antenna_ht(node->getDoubleValue("antenna-ht-ft", 0.0)),
     _resultTexture(0),
-    _wxEcho(0)
+    _wxEcho(0),
+    _font_size(0),
+    _font_spacing(0)
 {
     string branch;
     branch = "/instrumentation/" + _name;
@@ -174,6 +185,7 @@ wxRadarBg::init ()
     _radar_symbol_node      = n->getNode("symbol", true);
     _radar_centre_node      = n->getNode("centre", true);
     _radar_rotate_node      = n->getNode("rotate", true);
+    _radar_tcas_node        = n->getNode("tcas", true);
 
     _radar_centre_node->setBoolValue(false);
     if (!_radar_coverage_node->hasValue())
@@ -231,6 +243,8 @@ wxRadarBg::init ()
     osg::Camera *camera = _odg->getCamera();
     camera->addChild(_radarGeode.get());
     camera->addChild(_textGeode.get());
+
+    updateFont();
 }
 
 
@@ -305,16 +319,6 @@ wxRadarBg::update (double delta_time_sec)
     }
 
     string switchKnob = _Instrument->getStringValue("switch", "on");
-    if (_last_switchKnob != switchKnob) {
-        // since 3D models don't share textures with the rest of the world
-        // we must locate them and replace their handle by hand
-        // only do that when the instrument is turned on
-        //if (_last_switchKnob == "off")
-        //_odg->set_texture(_texture_path.c_str(), _resultTexture->getHandle());
-
-        _last_switchKnob = switchKnob;
-    }
-
     if (switchKnob == "off") {
         _Instrument->setStringValue("status", "");
     } else if (switchKnob == "stby") {
@@ -666,6 +670,7 @@ wxRadarBg::update_aircraft()
     if (!_ai_enabled_node->getBoolValue())
         return;
 
+    bool draw_tcas = _radar_tcas_node->getBoolValue();
     bool draw_echoes = _radar_position_node->getBoolValue();
     bool draw_symbols = _radar_symbol_node->getBoolValue();
     bool draw_data = _radar_data_node->getBoolValue();
@@ -697,7 +702,8 @@ wxRadarBg::update_aircraft()
             model = ai->getChild(i);
             if (!model->nChildren())
                 continue;
-            if (model->getIntValue("id") == selected_id) {
+            if ((model->getIntValue("id") == selected_id)&&
+                (!draw_tcas)) {
                 selected_ac = model;  // save selected model for last iteration
                 continue;
             }
@@ -752,8 +758,14 @@ wxRadarBg::update_aircraft()
         bearing += _angle_offset;
         heading += _angle_offset;
 
+        bool is_tcas_contact = false;
+        if (draw_tcas)
+        {
+            is_tcas_contact = update_tcas(model,range,user_alt,alt,bearing,radius);
+        }
+
         // pos mode
-        if (draw_echoes) {
+        if (draw_echoes && (!is_tcas_contact)) {
             float size = echo_radius * 120 * UNIT;
 
             const osg::Vec2f texBase(3 * UNIT, 3 * UNIT);
@@ -764,7 +776,7 @@ wxRadarBg::update_aircraft()
         }
 
         // data mode
-        if (draw_symbols) {
+        if (draw_symbols && (!draw_tcas)) {
             const osg::Vec2f texBase(0, 3 * UNIT);
             float size = 600 * UNIT;
             osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f)
@@ -774,11 +786,91 @@ wxRadarBg::update_aircraft()
             addQuad(_vertices, _texCoords, m, texBase);
         }
 
-        if (draw_data || i < 0)  // selected one (i == -1) is always drawn
+        if ((draw_data || i < 0)&&  // selected one (i == -1) is always drawn
+            ((!draw_tcas)||(is_tcas_contact)||(draw_echoes)))
             update_data(model, alt, heading, radius, bearing, i < 0);
     }
 }
 
+/** Update TCAS display.
+ * Return true when processed as TCAS contact, false otherwise. */
+bool
+wxRadarBg::update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt,
+                       double bearing,double radius)
+{
+    int threatLevel=0;
+    {
+        // update TCAS symbol
+        osg::Vec2f texBase;
+        threatLevel = model->getIntValue("tcas/threat-level",-1);
+        if (threatLevel == -1)
+        {
+            // no TCAS information (i.e. no transponder) => not visible to TCAS
+            return false;
+        }
+        int row = 7 - threatLevel;
+        int col = 4;
+        double vspeed = model->getDoubleValue("velocities/vertical-speed-fps");
+        if (vspeed < -3.0) // descending
+            col+=1;
+        else
+        if (vspeed > 3.0) // climbing
+            col+=2;
+        texBase = osg::Vec2f(col*UNIT,row * UNIT);
+        float size = 200 * UNIT;
+            osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f)
+                * wxRotate(-bearing)
+                * osg::Matrixf::translate(0.0f, radius, 0.0f)
+                * wxRotate(bearing) * _centerTrans);
+            addQuad(_vertices, _texCoords, m, texBase);
+    }
+
+    {
+        // update TCAS data
+        osgText::Text *altStr = new osgText::Text;
+        altStr->setFont(_font.get());
+        altStr->setFontResolution(12, 12);
+        altStr->setCharacterSize(_font_size);
+        altStr->setColor(_tcas_colors[threatLevel]);
+        osg::Matrixf m(wxRotate(-bearing)
+            * osg::Matrixf::translate(0.0f, radius, 0.0f)
+            * wxRotate(bearing) * _centerTrans);
+    
+        osg::Vec3 pos = m.preMult(osg::Vec3(16, 16, 0));
+        // cast to int's, otherwise text comes out ugly
+        altStr->setLineSpacing(_font_spacing);
+    
+        stringstream text;
+        altStr->setAlignment(osgText::Text::LEFT_CENTER);
+        int altDif = (alt-user_alt+50)/100;
+        char sign = 0;
+        int dy=0;
+        if (altDif>=0)
+        {
+            sign='+';
+            dy=2;
+        }
+        else
+        if (altDif<0)
+        {
+            sign='-';
+            altDif = -altDif;
+            dy=-30;
+        }
+        altStr->setPosition(osg::Vec3((int)pos.x()-30, (int)pos.y()+dy, 0));
+        if (sign)
+        {
+            text << sign
+                 << setprecision(0) << fixed
+                 << setw(2) << setfill('0') << altDif << endl;
+        }
+    
+        altStr->setText(text.str());
+        _textGeode->addDrawable(altStr);
+    }
+
+    return true;
+}
 
 void
 wxRadarBg::update_tacan()
@@ -983,11 +1075,23 @@ wxRadarBg::updateFont()
         _font->setGlyphImageMargin(0);
         _font->setGlyphImageMarginRatio(0);
     }
+
+    for (int i=0;i<4;i++)
+    {
+        const float defaultColors[4][3] = {{0,1,1},{0,1,1},{1,0.5,0},{1,0,0}};
+        SGPropertyNode_ptr color_node = _font_node->getNode("tcas/color",i,true);
+        float red   = color_node->getFloatValue("red",defaultColors[i][0]);
+        float green = color_node->getFloatValue("green",defaultColors[i][1]);
+        float blue  = color_node->getFloatValue("blue",defaultColors[i][2]);
+        float alpha = color_node->getFloatValue("alpha",1);
+        _tcas_colors[i]=osg::Vec4(red, green, blue, alpha);
+    }
 }
 
 void
 wxRadarBg::valueChanged(SGPropertyNode*)
 {
     updateFont();
+    _time = _interval;
 }
 
index 376410d1732e0d0bb638a17927eeb39212f3b46a..20ddbe8b69bae2b152f64f7ab7b2d6065efc1869 100644 (file)
@@ -96,8 +96,6 @@ private:
     typedef enum { ARC, MAP, PLAN, ROSE, BSCAN} DisplayMode;
     DisplayMode _display_mode;
 
-    string _last_switchKnob;
-
     float _range_nm;
     float _scale;   // factor to convert nm to display units
     float _angle_offset;
@@ -130,6 +128,7 @@ private:
     SGPropertyNode_ptr _radar_ref_rng_node;
     SGPropertyNode_ptr _radar_hdg_marker_node;
     SGPropertyNode_ptr _radar_rotate_node;
+    SGPropertyNode_ptr _radar_tcas_node;
 
     SGPropertyNode_ptr _font_node;
     SGPropertyNode_ptr _ai_enabled_node;
@@ -144,6 +143,7 @@ private:
     osg::Matrixf _centerTrans;
     osg::ref_ptr<osgText::Font> _font;
     osg::Vec4 _font_color;
+    osg::Vec4 _tcas_colors[4];
     float _font_size;
     float _font_spacing;
 
@@ -155,6 +155,8 @@ private:
     void update_heading_marker();
     void update_data(const SGPropertyNode *ac, double alt, double heading,
         double radius, double bearing, bool selected);
+    bool update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt,
+                     double bearing,double radius);
     void center_map();
     void apply_map_offset();
     void updateFont();