// Radar Altimeter // // Written by Vivian MEAZZA, started Feb 2008. // // // Copyright (C) 2008 Vivian Meazza // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // #ifdef HAVE_CONFIG_H # include "config.h" #endif #include
#include
#include "rad_alt.hxx" radAlt::radAlt(SGPropertyNode *node) : agRadar(node) { _name = node->getStringValue("name", "radar-altimeter"); _num = node->getIntValue("number", 0); } radAlt::~radAlt() { } void radAlt::init () { agRadar::init(); _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); _Instrument->getDoubleValue("az-step-deg", true); _Instrument->getDoubleValue("max-range-m", true); _Instrument->getDoubleValue("min-range-m", true); _Instrument->getDoubleValue("tilt", true); _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; } void radAlt::update (double delta_time_sec) { if ( ! _sim_init_done ) { if ( ! fgGetBool("sim/sceneryloaded", false) ) return; _sim_init_done = true; } if ( !_odg || ! _serviceable_node->getBoolValue() ) { _Instrument->setStringValue("status",""); return; } _time += delta_time_sec; if (_time < _interval) return; _time = 0.0; update_altitude(); } double radAlt::getDistanceAntennaToHit(SGVec3d nearestHit) const { //calculate the distance antenna to hit SGVec3d cartantennapos = getCartAntennaPos();; SGVec3d diff = nearestHit - cartantennapos; double distance = norm(diff); return distance ; } void radAlt::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(); 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 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; } } }