ground radar from Vivian Mezza
This commit is contained in:
parent
d03e63a059
commit
c2040f30a2
8 changed files with 739 additions and 36 deletions
|
@ -31,6 +31,7 @@ libInstrumentation_a_SOURCES = \
|
|||
tacan.cxx tacan.hxx mk_viii.cxx mk_viii.hxx \
|
||||
dclgps.cxx dclgps.hxx \
|
||||
render_area_2d.cxx render_area_2d.hxx \
|
||||
groundradar.cxx groundradar.hxx
|
||||
groundradar.cxx groundradar.hxx \
|
||||
agradar.cxx agradar.hxx rad_alt.cxx rad_alt.hxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_builddir)/src
|
||||
|
|
333
src/Instrumentation/agradar.cxx
Normal file
333
src/Instrumentation/agradar.cxx
Normal file
|
@ -0,0 +1,333 @@
|
|||
// Air Ground Radar
|
||||
//
|
||||
// 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 "agradar.hxx"
|
||||
|
||||
|
||||
agRadar::agRadar(SGPropertyNode *node) : wxRadarBg(node)
|
||||
{
|
||||
|
||||
_name = node->getStringValue("name", "air-ground-radar");
|
||||
_num = node->getIntValue("number", 0);
|
||||
|
||||
}
|
||||
|
||||
agRadar::~agRadar ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::init ()
|
||||
{
|
||||
_user_hdg_deg_node = fgGetNode("/orientation/heading-deg", true);
|
||||
_user_pitch_deg_node = fgGetNode("/orientation/pitch-deg", true);
|
||||
_user_roll_deg_node = fgGetNode("/orientation/roll-deg", true);
|
||||
|
||||
_terrain_warning_node = fgGetNode("/sim/alarms/terrain-warning", true);
|
||||
_terrain_warning_node->setBoolValue(false);
|
||||
|
||||
wxRadarBg::init();
|
||||
|
||||
// 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("trk", 0.0);
|
||||
_Instrument->setFloatValue("tilt",-2.5);
|
||||
_Instrument->setStringValue("status","");
|
||||
_Instrument->setIntValue("mode-control", 5);
|
||||
|
||||
_Instrument->setBoolValue("stabilisation/roll", false);
|
||||
_Instrument->setBoolValue("stabilisation/pitch", false);
|
||||
|
||||
_Instrument->getNode("antenna/x-offset-m", true);
|
||||
_Instrument->getNode("antenna/y-offset-m", true);
|
||||
_Instrument->getNode("antenna/z-offset-m", true);
|
||||
|
||||
_Instrument->getNode("terrain-warning/elev-limit-deg", true);
|
||||
_Instrument->getNode("terrain-warning/elev-step-deg", true);
|
||||
_Instrument->getNode("terrain-warning/az-limit-deg", true);
|
||||
_Instrument->getNode("terrain-warning/az-step-deg", true);
|
||||
_Instrument->getNode("terrain-warning/max-range-m", true);
|
||||
_Instrument->getNode("terrain-warning/min-range-m", true);
|
||||
_Instrument->getNode("terrain-warning/tilt",true);
|
||||
|
||||
_Instrument->getNode("terrain-warning/hit/brg-deg", true);
|
||||
_Instrument->getNode("terrain-warning/hit/range-m", true);
|
||||
_Instrument->getNode("terrain-warning/hit/material", true);
|
||||
_Instrument->getNode("terrain-warning/hit/bumpiness", true);
|
||||
|
||||
_Instrument->getNode("terrain-warning/stabilisation/roll", true);
|
||||
_Instrument->getNode("terrain-warning/stabilisation/pitch", true);
|
||||
// cout << "init done" << endl;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::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_terrain();
|
||||
// wxRadarBg::update(delta_time_sec);
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::setUserPos()
|
||||
{
|
||||
userpos.setLatitudeDeg(_user_lat_node->getDoubleValue());
|
||||
userpos.setLongitudeDeg(_user_lon_node->getDoubleValue());
|
||||
userpos.setElevationM(_user_alt_node->getDoubleValue() * SG_FEET_TO_METER);
|
||||
}
|
||||
|
||||
SGVec3d
|
||||
agRadar::getCartUserPos() const {
|
||||
SGVec3d cartUserPos = SGVec3d::fromGeod(userpos);
|
||||
return cartUserPos;
|
||||
}
|
||||
|
||||
SGVec3d
|
||||
agRadar::getCartAntennaPos() const {
|
||||
|
||||
float yaw = _user_hdg_deg_node->getDoubleValue();
|
||||
float pitch = _user_pitch_deg_node->getDoubleValue();
|
||||
float roll = _user_roll_deg_node->getDoubleValue();
|
||||
|
||||
double x_offset_m =_Instrument->getDoubleValue("antenna/x-offset-m", 0);
|
||||
double y_offset_m =_Instrument->getDoubleValue("antenna/y-offset-m", 0);
|
||||
double z_offset_m =_Instrument->getDoubleValue("antenna/y-offset-m", 0);
|
||||
|
||||
// convert geodetic positions to geocentered
|
||||
SGVec3d cartuserPos = getCartUserPos();
|
||||
|
||||
// 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) )
|
||||
SGVec3d _off(x_offset_m, y_offset_m, -z_offset_m);
|
||||
|
||||
// Transform the user position to the horizontal local coordinate system.
|
||||
SGQuatd hlTrans = SGQuatd::fromLonLat(userpos);
|
||||
|
||||
// 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 off = hlTrans.backTransform(_off);
|
||||
|
||||
// Add the position offset of the user model to get the geocentered position
|
||||
SGVec3d offsetPos = cartuserPos + off;
|
||||
|
||||
return offsetPos;
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::setAntennaPos() {
|
||||
SGGeodesy::SGCartToGeod(getCartAntennaPos(), antennapos);
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::setUserVec(int az, double el)
|
||||
{
|
||||
float yaw = _user_hdg_deg_node->getDoubleValue();
|
||||
float pitch = _user_pitch_deg_node->getDoubleValue();
|
||||
float roll = _user_roll_deg_node->getDoubleValue();
|
||||
int mode = _radar_mode_control_node->getIntValue();
|
||||
double tilt = _Instrument->getDoubleValue("tilt");
|
||||
double trk = _Instrument->getDoubleValue("trk");
|
||||
bool roll_stab = _Instrument->getBoolValue("stabilisation/roll");
|
||||
bool pitch_stab = _Instrument->getBoolValue("stabilisation/pitch");
|
||||
|
||||
SGQuatd offset = SGQuatd::fromYawPitchRollDeg(az + trk, el + tilt, 0);
|
||||
|
||||
// Transform the antenna position to the horizontal local coordinate system.
|
||||
SGQuatd hlTrans = SGQuatd::fromLonLat(antennapos);
|
||||
|
||||
// and postrotate the orientation of the radar wrt the horizontal
|
||||
// local frame
|
||||
hlTrans *= SGQuatd::fromYawPitchRollDeg(yaw, pitch, roll);
|
||||
hlTrans *= offset;
|
||||
|
||||
if (roll_stab)
|
||||
hlTrans *= SGQuatd::fromYawPitchRollDeg(0, 0, -roll);
|
||||
|
||||
if (pitch_stab)
|
||||
hlTrans *= SGQuatd::fromYawPitchRollDeg(0, -pitch, 0);
|
||||
|
||||
// now rotate the rotation vector back into the
|
||||
// earth centered frames coordinates
|
||||
SGVec3d angleaxis(1,0,0);
|
||||
uservec = hlTrans.backTransform(angleaxis);
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
agRadar::getMaterial(){
|
||||
|
||||
if (globals->get_scenery()->get_elevation_m(hitpos, _elevation_m, &_material)){
|
||||
//_ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET;
|
||||
if (_material) {
|
||||
const vector<string>& names = _material->get_names();
|
||||
|
||||
_solid = _material->get_solid();
|
||||
_load_resistance = _material->get_load_resistance();
|
||||
_frictionFactor =_material->get_friction_factor();
|
||||
_bumpinessFactor = _material->get_bumpiness();
|
||||
|
||||
if (!names.empty())
|
||||
_mat_name = names[0].c_str();
|
||||
else
|
||||
_mat_name = "";
|
||||
|
||||
}
|
||||
/*cout << "material " << mat_name
|
||||
<< " solid " << _solid
|
||||
<< " load " << _load_resistance
|
||||
<< " frictionFactor " << frictionFactor
|
||||
<< " _bumpinessFactor " << _bumpinessFactor
|
||||
<< endl;*/
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
agRadar::update_terrain()
|
||||
{
|
||||
int mode = _radar_mode_control_node->getIntValue();
|
||||
|
||||
double el_limit = 1;
|
||||
double el_step = 1;
|
||||
double az_limit = 50;
|
||||
double az_step = 10;
|
||||
double max_range = 40000;
|
||||
double min_range = 250;
|
||||
double tilt = -2.5;
|
||||
bool roll_stab = _Instrument->getBoolValue("stabilisation/roll");
|
||||
bool pitch_stab = _Instrument->getBoolValue("stabilisation/pitch");
|
||||
//string status = "";
|
||||
const char* status;
|
||||
bool hdg_mkr = true;
|
||||
|
||||
if (mode == 5){
|
||||
status = "TW";
|
||||
hdg_mkr = false;
|
||||
roll_stab = _Instrument->getBoolValue("terrain-warning/stabilisation/roll", true);
|
||||
pitch_stab = _Instrument->getBoolValue("terrain-warning/stabilisation/pitch", false);
|
||||
tilt = _Instrument->getDoubleValue("terrain-warning/tilt", -2);
|
||||
el_limit = _Instrument->getDoubleValue("terrain-warning/elev-limit-deg", 2);
|
||||
el_step = _Instrument->getDoubleValue("terrain-warning/elev-step-deg", 1);
|
||||
az_limit = _Instrument->getDoubleValue("terrain-warning/az-limit-deg", 1);
|
||||
az_step = _Instrument->getDoubleValue("terrain-warning/az-step-deg", 1.5);
|
||||
max_range = _Instrument->getDoubleValue("terrain-warning/max-range-m", 4000);
|
||||
min_range = _Instrument->getDoubleValue("terrain-warning/min-range-m", 250);
|
||||
}
|
||||
|
||||
_Instrument->setDoubleValue("tilt", tilt);
|
||||
_Instrument->setBoolValue("stabilisation/roll", roll_stab);
|
||||
_Instrument->setBoolValue("stabilisation/pitch", pitch_stab);
|
||||
_Instrument->setStringValue("status", status);
|
||||
_Instrument->setDoubleValue("limit-deg", az_limit);
|
||||
_Instrument->setBoolValue("heading-marker", hdg_mkr);
|
||||
|
||||
for(double brg = -az_limit; brg <= az_limit; brg += az_step){
|
||||
setUserPos();
|
||||
setAntennaPos();
|
||||
SGVec3d cartantennapos = getCartAntennaPos();
|
||||
|
||||
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 course1, course2, distance;
|
||||
|
||||
SGGeodesy::inverse(hitpos, antennapos, course1, course2, distance);
|
||||
|
||||
if (distance >= min_range && distance <= max_range) {
|
||||
_terrain_warning_node->setBoolValue(true);
|
||||
getMaterial();
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/brg-deg", course2);
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/range-m", distance);
|
||||
_Instrument->setStringValue("terrain-warning/hit/material", _mat_name.c_str());
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/bumpiness", _bumpinessFactor);
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/elevation-m", _elevation_m);
|
||||
} else {
|
||||
_terrain_warning_node->setBoolValue(false);
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/brg-deg", 0);
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/range-m", 0);
|
||||
_Instrument->setStringValue("terrain-warning/hit/material", "");
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/bumpiness", 0);
|
||||
_Instrument->setDoubleValue("terrain-warning/hit/elevation-m",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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
75
src/Instrumentation/agradar.hxx
Normal file
75
src/Instrumentation/agradar.hxx
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Air Ground Radar
|
||||
//
|
||||
// Written by Vivian MEAZZA, started Feb 2008.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2008 Vivain MEAZZA - vivian.meazza@lineone.net
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _INST_AGRADAR_HXX
|
||||
#define _INST_AGRADAR_HXX
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
||||
#include "wxradar.hxx"
|
||||
|
||||
class agRadar : public wxRadarBg{
|
||||
public:
|
||||
|
||||
agRadar ( SGPropertyNode *node );
|
||||
agRadar ();
|
||||
virtual ~agRadar ();
|
||||
|
||||
virtual void init ();
|
||||
virtual void update (double dt);
|
||||
|
||||
void setUserPos();
|
||||
void setUserVec(int az, double el);
|
||||
void update_terrain();
|
||||
void setAntennaPos();
|
||||
|
||||
bool getMaterial();
|
||||
|
||||
double _load_resistance; // ground load resistanc N/m^2
|
||||
double _frictionFactor; // dimensionless modifier for Coefficient of Friction
|
||||
double _bumpinessFactor; // dimensionless modifier for Bumpiness
|
||||
double _elevation_m; // ground elevation in meters
|
||||
bool _solid; // if true ground is solid for FDMs
|
||||
|
||||
const SGMaterial* _material;
|
||||
|
||||
string _mat_name; // ground material
|
||||
|
||||
SGVec3d getCartUserPos() const;
|
||||
SGVec3d getCartAntennaPos()const;
|
||||
|
||||
SGVec3d uservec;
|
||||
|
||||
SGPropertyNode_ptr _user_hdg_deg_node;
|
||||
SGPropertyNode_ptr _user_roll_deg_node;
|
||||
SGPropertyNode_ptr _user_pitch_deg_node;
|
||||
SGPropertyNode_ptr _terrain_warning_node;
|
||||
|
||||
SGGeod userpos;
|
||||
SGGeod hitpos;
|
||||
SGGeod antennapos;
|
||||
};
|
||||
|
||||
#endif // _INST_AGRADAR_HXX
|
|
@ -48,6 +48,8 @@
|
|||
#include "mk_viii.hxx"
|
||||
#include "mrg.hxx"
|
||||
#include "groundradar.hxx"
|
||||
#include "agradar.hxx"
|
||||
#include "rad_alt.hxx"
|
||||
|
||||
FGInstrumentMgr::FGInstrumentMgr ()
|
||||
{
|
||||
|
@ -168,7 +170,7 @@ bool FGInstrumentMgr::build ()
|
|||
set_subsystem( id, new VerticalSpeedIndicator( node ) );
|
||||
|
||||
} else if ( name == "radar" ) {
|
||||
set_subsystem( id, new wxRadarBg ( node ), 0.5 );
|
||||
set_subsystem( id, new wxRadarBg ( node ), 1);
|
||||
|
||||
} else if ( name == "inst-vertical-speed-indicator" ) {
|
||||
set_subsystem( id, new InstVerticalSpeedIndicator( node ) );
|
||||
|
@ -185,6 +187,12 @@ bool FGInstrumentMgr::build ()
|
|||
} else if ( name == "groundradar" ) {
|
||||
set_subsystem( id, new GroundRadar( node ), 1 );
|
||||
|
||||
} else if ( name == "air-ground-radar" ) {
|
||||
set_subsystem( id, new agRadar( node ),1);
|
||||
|
||||
} else if ( name == "radar-altimeter" ) {
|
||||
set_subsystem( id, new radAlt( node ),1);
|
||||
|
||||
} else {
|
||||
SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: "
|
||||
<< name );
|
||||
|
|
218
src/Instrumentation/rad_alt.cxx
Normal file
218
src/Instrumentation/rad_alt.cxx
Normal file
|
@ -0,0 +1,218 @@
|
|||
// 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 "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;
|
||||
|
||||
for(double brg = -az_limit; brg <= az_limit; brg += az_step){
|
||||
setUserPos();
|
||||
setAntennaPos();
|
||||
SGVec3d cartantennapos = getCartAntennaPos();
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
55
src/Instrumentation/rad_alt.hxx
Normal file
55
src/Instrumentation/rad_alt.hxx
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Radar Altimeter
|
||||
//
|
||||
// Written by Vivian MEAZZA, started Feb 2008.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2008 Vivain MEAZZA - vivian.meazza@lineone.net
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _INST_RADALT_HXX
|
||||
#define _INST_RADALT_HXX
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
||||
#include "agradar.hxx"
|
||||
|
||||
class radAlt : public agRadar{
|
||||
public:
|
||||
|
||||
radAlt ( SGPropertyNode *node );
|
||||
radAlt ();
|
||||
virtual ~radAlt ();
|
||||
|
||||
private:
|
||||
|
||||
virtual void init ();
|
||||
virtual void update (double dt);
|
||||
|
||||
void update_altitude();
|
||||
double getDistanceAntennaToHit(SGVec3d h) const;
|
||||
|
||||
SGPropertyNode_ptr _user_alt_agl_node;
|
||||
SGPropertyNode_ptr _rad_alt_warning_node;
|
||||
|
||||
double _min_radalt;
|
||||
|
||||
};
|
||||
|
||||
#endif // _INST_AGRADAR_HXX
|
|
@ -591,12 +591,12 @@ wxRadarBg::update_aircraft()
|
|||
return;
|
||||
|
||||
radar_list_type radar_list = _ai->get_ai_list();
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: AI submodel list size" << radar_list.size());
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: AI submodel list size" << radar_list.size());
|
||||
if (radar_list.empty())
|
||||
return;
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: Loading AI submodels ");
|
||||
const double echo_radii[] = {0, 1, 1.5, 1.5, 0.001, 0.1, 1.5, 2, 1.5, 1.5};
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: Loading AI submodels ");
|
||||
const double echo_radii[] = {0, 1, 1.5, 1.5, 0.001, 0.1, 1.5, 2, 1.5, 1.5, 1.5};
|
||||
|
||||
double user_lat = _user_lat_node->getDoubleValue();
|
||||
double user_lon = _user_lon_node->getDoubleValue();
|
||||
|
@ -628,16 +628,16 @@ wxRadarBg::update_aircraft()
|
|||
calcRangeBearing(user_lat, user_lon, lat, lon, range, bearing);
|
||||
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG,
|
||||
// "Radar: ID=" << ac->getID() << "(" << radar_list.size() << ")"
|
||||
// << " type=" << type
|
||||
// << " view_heading=" << _view_heading * SG_RADIANS_TO_DEGREES
|
||||
// << " alt=" << alt
|
||||
// << " heading=" << heading
|
||||
// << " range=" << range
|
||||
// << " bearing=" << bearing);
|
||||
/* "Radar: ID=" << ac->getID() << "(" << radar_list.size() << ")"
|
||||
<< " type=" << type
|
||||
<< " view_heading=" << _view_heading * SG_RADIANS_TO_DEGREES
|
||||
<< " alt=" << alt
|
||||
<< " heading=" << heading
|
||||
<< " range=" << range
|
||||
<< " bearing=" << bearing);*/
|
||||
|
||||
bool isVisible = withinRadarHorizon(user_alt, alt, range);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: visible " << isVisible);
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: visible " << isVisible);
|
||||
if (!isVisible)
|
||||
continue;
|
||||
|
||||
|
@ -668,7 +668,8 @@ wxRadarBg::update_aircraft()
|
|||
addQuad(_vertices, _texCoords, m, texBase);
|
||||
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: drawing AI"
|
||||
// << " x=" << x << " y=" << y
|
||||
//<< " ID=" << ac->getID()
|
||||
//<< " type=" << type
|
||||
// << " radius=" << radius
|
||||
// << " angle=" << angle * SG_RADIANS_TO_DEGREES);
|
||||
}
|
||||
|
@ -797,7 +798,7 @@ wxRadarBg::withinRadarHorizon(double user_alt, double alt, double range_nm)
|
|||
alt = 0;
|
||||
|
||||
double radarhorizon = 1.23 * (sqrt(alt) + sqrt(user_alt));
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: horizon " << radarhorizon);
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: horizon " << radarhorizon);
|
||||
return radarhorizon >= range_nm;
|
||||
}
|
||||
|
||||
|
@ -819,14 +820,14 @@ wxRadarBg::inRadarRange(int type, double range_nm)
|
|||
//
|
||||
// TODO - make the maximum range adjustable at runtime
|
||||
|
||||
const double sigma[] = {0, 1, 100, 100, 0.001, 0.1, 100, 100, 1, 1};
|
||||
const double sigma[] = {0, 1, 100, 100, 0.001, 0.1, 100, 100, 1, 1, 1};
|
||||
double constant = _radar_ref_rng;
|
||||
|
||||
if (constant <= 0)
|
||||
constant = 35;
|
||||
|
||||
double maxrange = constant * pow(sigma[type], 0.25);
|
||||
SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: max range " << maxrange);
|
||||
//SG_LOG(SG_GENERAL, SG_DEBUG, "Radar: max range " << maxrange);
|
||||
return maxrange >= range_nm;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,36 +56,47 @@ public:
|
|||
virtual void update (double dt);
|
||||
virtual void valueChanged(SGPropertyNode*);
|
||||
|
||||
private:
|
||||
string _name;
|
||||
int _num;
|
||||
double _interval;
|
||||
double _time;
|
||||
|
||||
bool _sim_init_done;
|
||||
|
||||
string _name;
|
||||
|
||||
int _num;
|
||||
|
||||
SGPropertyNode_ptr _serviceable_node;
|
||||
SGPropertyNode_ptr _Instrument;
|
||||
SGPropertyNode_ptr _radar_mode_control_node;
|
||||
|
||||
SGPropertyNode_ptr _user_lat_node;
|
||||
SGPropertyNode_ptr _user_lon_node;
|
||||
SGPropertyNode_ptr _user_heading_node;
|
||||
SGPropertyNode_ptr _user_alt_node;
|
||||
|
||||
FGODGauge *_odg;
|
||||
|
||||
private:
|
||||
|
||||
string _texture_path;
|
||||
|
||||
typedef enum { ARC, MAP, PLAN, ROSE } DisplayMode;
|
||||
DisplayMode _display_mode;
|
||||
|
||||
string _last_switchKnob;
|
||||
bool _sim_init_done;
|
||||
|
||||
float _range_nm;
|
||||
float _scale; // factor to convert nm to display units
|
||||
double _radar_ref_rng;
|
||||
float _angle_offset;
|
||||
float _view_heading;
|
||||
double _lat, _lon;
|
||||
float _x_offset, _y_offset;
|
||||
|
||||
SGPropertyNode_ptr _serviceable_node;
|
||||
SGPropertyNode_ptr _Instrument;
|
||||
double _radar_ref_rng;
|
||||
double _lat, _lon;
|
||||
|
||||
SGPropertyNode_ptr _Tacan;
|
||||
SGPropertyNode_ptr _Radar_controls;
|
||||
|
||||
SGPropertyNode_ptr _user_lat_node;
|
||||
SGPropertyNode_ptr _user_lon_node;
|
||||
SGPropertyNode_ptr _user_heading_node;
|
||||
SGPropertyNode_ptr _user_alt_node;
|
||||
SGPropertyNode_ptr _user_speed_east_fps_node;
|
||||
SGPropertyNode_ptr _user_speed_north_fps_node;
|
||||
|
||||
|
@ -99,7 +110,7 @@ private:
|
|||
SGPropertyNode_ptr _radar_position_node;
|
||||
SGPropertyNode_ptr _radar_data_node;
|
||||
SGPropertyNode_ptr _radar_symbol_node;
|
||||
SGPropertyNode_ptr _radar_mode_control_node;
|
||||
|
||||
SGPropertyNode_ptr _radar_centre_node;
|
||||
SGPropertyNode_ptr _radar_coverage_node;
|
||||
SGPropertyNode_ptr _radar_ref_rng_node;
|
||||
|
@ -121,7 +132,6 @@ private:
|
|||
|
||||
list_of_SGWxRadarEcho _radarEchoBuffer;
|
||||
|
||||
FGODGauge *_odg;
|
||||
FGAIManager* _ai;
|
||||
|
||||
void update_weather();
|
||||
|
@ -129,15 +139,17 @@ private:
|
|||
void update_tacan();
|
||||
void update_heading_marker();
|
||||
void update_data(FGAIBase* ac, double radius, double bearing, bool selected);
|
||||
|
||||
void center_map();
|
||||
void apply_map_offset();
|
||||
bool withinRadarHorizon(double user_alt, double alt, double range);
|
||||
bool inRadarRange(int type, double range);
|
||||
float calcRelBearing(float bearing, float heading);
|
||||
void updateFont();
|
||||
void calcRangeBearing(double lat, double lon, double lat2, double lon2,
|
||||
double &range, double &bearing) const;
|
||||
void updateFont();
|
||||
|
||||
bool withinRadarHorizon(double user_alt, double alt, double range);
|
||||
bool inRadarRange(int type, double range);
|
||||
|
||||
float calcRelBearing(float bearing, float heading);
|
||||
|
||||
};
|
||||
|
||||
#endif // _INST_WXRADAR_HXX
|
||||
|
|
Loading…
Add table
Reference in a new issue