diff --git a/src/Radio/antenna.cxx b/src/Radio/antenna.cxx index 2be67f351..bb5770fb5 100644 --- a/src/Radio/antenna.cxx +++ b/src/Radio/antenna.cxx @@ -1,6 +1,6 @@ // antenna.cxx -- implementation of FGRadioAntenna // Class to represent a virtual radio antenna properties -// Written by Adrian Musceac, started December 2011. +// Written by Adrian Musceac YO8RZZ, started December 2011. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -34,8 +34,8 @@ FGRadioAntenna::FGRadioAntenna(string type) { _mirror_y = 1; // normally we want to mirror these axis because the pattern is simetric _mirror_z = 1; - _invert_ground = 0; - load_antenna_pattern(type); + _invert_ground = 0; // TODO: use for inverting the antenna ground, for instance aircraft body reflection + load_NEC_antenna_pattern(type); } FGRadioAntenna::~FGRadioAntenna() { @@ -44,9 +44,9 @@ FGRadioAntenna::~FGRadioAntenna() { delete point_gain; } _pattern.clear(); - } +// WIP double FGRadioAntenna::calculate_gain(double bearing, double angle) { // TODO: what if the pattern is assimetric? @@ -58,7 +58,7 @@ double FGRadioAntenna::calculate_gain(double bearing, double angle) { azimuth += azimuth % 2; int elevation = (int)floor(angle); elevation += elevation % 2; - cerr << "Bearing: " << bearing << " angle: " << angle << " azimuth: " << azimuth << " elevation: " << elevation << endl; + //cerr << "Bearing: " << bearing << " angle: " << angle << " azimuth: " << azimuth << " elevation: " << elevation << endl; for (unsigned i =0; i < _pattern.size(); i++) { AntennaGain *point_gain = _pattern[i]; @@ -71,13 +71,11 @@ double FGRadioAntenna::calculate_gain(double bearing, double angle) { } - -/*** load external plot file generated by NEC2 -***/ -void FGRadioAntenna::load_antenna_pattern(string type) { +void FGRadioAntenna::load_NEC_antenna_pattern(string type) { - SGPath pattern_file(fgGetString("/sim/fg-home")); - pattern_file.append("antennas"); + //SGPath pattern_file(fgGetString("/sim/fg-home")); + SGPath pattern_file(globals->get_fg_root()); + pattern_file.append("Navaids/Antennas"); pattern_file.append(type + ".txt"); if (!pattern_file.exists()) { return; @@ -100,6 +98,4 @@ void FGRadioAntenna::load_antenna_pattern(string type) { datapoint->gain = gain; _pattern.push_back(datapoint); } - - } diff --git a/src/Radio/antenna.hxx b/src/Radio/antenna.hxx index 0421a7f0c..55247e61e 100644 --- a/src/Radio/antenna.hxx +++ b/src/Radio/antenna.hxx @@ -1,6 +1,6 @@ // antenna.hxx -- FGRadioAntenna: class to represent antenna properties // -// Written by Adrian Musceac, started December 2011. +// Written by Adrian Musceac YO8RZZ, started December 2011. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -32,8 +32,16 @@ using std::string; class FGRadioAntenna { private: - void load_antenna_pattern(string type); - int _mirror_y; + +/*** load external plot file generated by NEC2. needs to have a txt extension +* when naming plots, use the following scheme: type_frequencyMHz.txt +* eg: yagi_110.txt or LPDA_333.txt +* @param: name of file +* @return: none +***/ + void load_NEC_antenna_pattern(string type); + + int _mirror_y; int _mirror_z; int _invert_ground; double _heading_deg; @@ -51,7 +59,14 @@ public: FGRadioAntenna(string type); ~FGRadioAntenna(); + +/*** calculate far-field antenna gain on a 3D volume around it +* @param: bearing to the other station, vertical angle (some call it theta) +* @return: gain relative to maximum normalized gain. will be negative in all cases +***/ double calculate_gain(double bearing, double angle); - void set_heading(double heading_deg) {_heading_deg = heading_deg ;}; - void set_elevation_angle(double elevation_angle_deg) {_elevation_angle_deg = elevation_angle_deg ;}; + + /// some convenience setters and getters (unused for now) + inline void set_heading(double heading_deg) {_heading_deg = heading_deg ;}; + inline void set_elevation_angle(double elevation_angle_deg) {_elevation_angle_deg = elevation_angle_deg ;}; }; diff --git a/src/Radio/radio.cxx b/src/Radio/radio.cxx index 2c983285f..f5ec063ce 100644 --- a/src/Radio/radio.cxx +++ b/src/Radio/radio.cxx @@ -1,6 +1,6 @@ // radio.cxx -- implementation of FGRadio // Class to manage radio propagation using the ITM model -// Written by Adrian Musceac, started August 2011. +// Written by Adrian Musceac YO8RZZ, started August 2011. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -291,7 +291,7 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i double delta_last = fmod(distance_m, point_distance); deque elevations; - deque materials; + deque materials; double elevation_under_pilot = 0.0; @@ -329,42 +329,48 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i elevations.push_back(elevation_m); if(mat) { const std::vector mat_names = mat->get_names(); - materials.push_back(mat_names[0]); + string* name = new string(mat_names[0]); + materials.push_back(name); } else { - materials.push_back("None"); + string* no_material = new string("None"); + materials.push_back(no_material); } } else { elevations.push_front(elevation_m); if(mat) { const std::vector mat_names = mat->get_names(); - materials.push_front(mat_names[0]); + string* name = new string(mat_names[0]); + materials.push_front(name); } else { - materials.push_front("None"); + string* no_material = new string("None"); + materials.push_front(no_material); } } } else { if((transmission_type == 3) || (transmission_type == 4)) { elevations.push_back(0.0); - materials.push_back("None"); + string* no_material = new string("None"); + materials.push_back(no_material); } else { + string* no_material = new string("None"); elevations.push_front(0.0); - materials.push_front("None"); + materials.push_front(no_material); } } } if((transmission_type == 3) || (transmission_type == 4)) { elevations.push_front(elevation_under_pilot); - if (delta_last > (point_distance / 2) ) // only add last point if it's farther than half point_distance + //if (delta_last > (point_distance / 2) ) // only add last point if it's farther than half point_distance elevations.push_back(elevation_under_sender); } else { elevations.push_back(elevation_under_pilot); - if (delta_last > (point_distance / 2) ) + //if (delta_last > (point_distance / 2) ) elevations.push_front(elevation_under_sender); } @@ -452,18 +458,21 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i //_root_node->setDoubleValue("station[0]/rx-pattern-gain", rx_pattern_gain); delete[] itm_elev; - + for (unsigned i =0; i < materials.size(); i++) { + delete materials[i]; + } + return signal; } -void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], deque &materials, +void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], deque &materials, double transmitter_height, double receiver_height, int p_mode, double horizons[], double &clutter_loss) { double distance_m = itm_elev[0] * itm_elev[1]; // only consider elevation points - + unsigned mat_size = materials.size(); if (p_mode == 0) { // LOS: take each point and see how clutter height affects first Fresnel zone int mat = 0; int j=1; @@ -471,6 +480,9 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[2] + transmitter_height - itm_elev[(int)itm_elev[0] + 2] + receiver_height) / distance_m; @@ -522,6 +534,10 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], break; double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[2] + transmitter_height - itm_elev[num_points_1st + 2] + clutter_height) / distance_m; @@ -566,6 +582,10 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], break; double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[last+1] + clutter_height - itm_elev[(int)itm_elev[0] + 2] + receiver_height) / distance_m; @@ -618,6 +638,9 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], break; double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[2] + transmitter_height - itm_elev[num_points_1st + 2] + clutter_height) / distance_m; @@ -650,6 +673,7 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], // no losses } j++; + mat++; last = k; } mat +=1; @@ -661,6 +685,9 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], break; double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[last+1] + clutter_height - itm_elev[num_points_1st + num_points_2nd + 2] + clutter_height) / distance_m; @@ -705,6 +732,9 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], break; double clutter_height = 0.0; // mean clutter height for a certain terrain type double clutter_density = 0.0; // percent of reflected wave + if((unsigned)mat >= mat_size) { + break; + } get_material_properties(materials[mat], clutter_height, clutter_density); double grad = fabs(itm_elev[last2+1] + clutter_height - itm_elev[(int)itm_elev[0] + 2] + receiver_height) / distance_m; @@ -751,107 +781,110 @@ void FGRadioTransmission::calculate_clutter_loss(double freq, double itm_elev[], } -void FGRadioTransmission::get_material_properties(string mat_name, double &height, double &density) { +void FGRadioTransmission::get_material_properties(string* mat_name, double &height, double &density) { - if(mat_name == "Landmass") { + if(!mat_name) + return; + + if(*mat_name == "Landmass") { height = 15.0; density = 0.2; } - else if(mat_name == "SomeSort") { + else if(*mat_name == "SomeSort") { height = 15.0; density = 0.2; } - else if(mat_name == "Island") { + else if(*mat_name == "Island") { height = 15.0; density = 0.2; } - else if(mat_name == "Default") { + else if(*mat_name == "Default") { height = 15.0; density = 0.2; } - else if(mat_name == "EvergreenBroadCover") { + else if(*mat_name == "EvergreenBroadCover") { height = 20.0; density = 0.2; } - else if(mat_name == "EvergreenForest") { + else if(*mat_name == "EvergreenForest") { height = 20.0; density = 0.2; } - else if(mat_name == "DeciduousBroadCover") { + else if(*mat_name == "DeciduousBroadCover") { height = 15.0; density = 0.3; } - else if(mat_name == "DeciduousForest") { + else if(*mat_name == "DeciduousForest") { height = 15.0; density = 0.3; } - else if(mat_name == "MixedForestCover") { + else if(*mat_name == "MixedForestCover") { height = 20.0; density = 0.25; } - else if(mat_name == "MixedForest") { + else if(*mat_name == "MixedForest") { height = 15.0; density = 0.25; } - else if(mat_name == "RainForest") { + else if(*mat_name == "RainForest") { height = 25.0; density = 0.55; } - else if(mat_name == "EvergreenNeedleCover") { + else if(*mat_name == "EvergreenNeedleCover") { height = 15.0; density = 0.2; } - else if(mat_name == "WoodedTundraCover") { + else if(*mat_name == "WoodedTundraCover") { height = 5.0; density = 0.15; } - else if(mat_name == "DeciduousNeedleCover") { + else if(*mat_name == "DeciduousNeedleCover") { height = 5.0; density = 0.2; } - else if(mat_name == "ScrubCover") { + else if(*mat_name == "ScrubCover") { height = 3.0; density = 0.15; } - else if(mat_name == "BuiltUpCover") { + else if(*mat_name == "BuiltUpCover") { height = 30.0; density = 0.7; } - else if(mat_name == "Urban") { + else if(*mat_name == "Urban") { height = 30.0; density = 0.7; } - else if(mat_name == "Construction") { + else if(*mat_name == "Construction") { height = 30.0; density = 0.7; } - else if(mat_name == "Industrial") { + else if(*mat_name == "Industrial") { height = 30.0; density = 0.7; } - else if(mat_name == "Port") { + else if(*mat_name == "Port") { height = 30.0; density = 0.7; } - else if(mat_name == "Town") { + else if(*mat_name == "Town") { height = 10.0; density = 0.5; } - else if(mat_name == "SubUrban") { + else if(*mat_name == "SubUrban") { height = 10.0; density = 0.5; } - else if(mat_name == "CropWoodCover") { + else if(*mat_name == "CropWoodCover") { height = 10.0; density = 0.1; } - else if(mat_name == "CropWood") { + else if(*mat_name == "CropWood") { height = 10.0; density = 0.1; } - else if(mat_name == "AgroForest") { + else if(*mat_name == "AgroForest") { height = 10.0; density = 0.1; } diff --git a/src/Radio/radio.hxx b/src/Radio/radio.hxx index 06ab98894..d6ff10349 100644 --- a/src/Radio/radio.hxx +++ b/src/Radio/radio.hxx @@ -1,6 +1,6 @@ // radio.hxx -- FGRadio: class to manage radio propagation // -// Written by Adrian Musceac, started August 2011. +// Written by Adrian Musceac YO8RZZ, started August 2011. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -74,7 +74,7 @@ private: * @param: frequency, elevation data, terrain type, horizon distances, calculated loss * @return: none ***/ - void calculate_clutter_loss(double freq, double itm_elev[], std::deque &materials, + void calculate_clutter_loss(double freq, double itm_elev[], std::deque &materials, double transmitter_height, double receiver_height, int p_mode, double horizons[], double &clutter_loss); @@ -82,7 +82,7 @@ private: * @param: terrain type, median clutter height, radiowave attenuation factor * @return: none ***/ - void get_material_properties(string mat_name, double &height, double &density); + void get_material_properties(string* mat_name, double &height, double &density); public: