Read antenna radiation pattern from file
This commit is contained in:
parent
6d816823db
commit
500086adec
4 changed files with 61 additions and 14 deletions
|
@ -32,17 +32,37 @@ using namespace std;
|
||||||
|
|
||||||
FGRadioAntenna::FGRadioAntenna(string type) {
|
FGRadioAntenna::FGRadioAntenna(string type) {
|
||||||
|
|
||||||
_mirror_y = 1;
|
_mirror_y = 1; // normally we want to mirror these axis because the pattern is simetric
|
||||||
_mirror_z = 1;
|
_mirror_z = 1;
|
||||||
_invert_ground = 0;
|
_invert_ground = 0;
|
||||||
load_antenna_pattern(type);
|
load_antenna_pattern(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGRadioAntenna::~FGRadioAntenna() {
|
FGRadioAntenna::~FGRadioAntenna() {
|
||||||
|
_pattern.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGRadioAntenna::calculate_gain(double azimuth, double elevation) {
|
double FGRadioAntenna::calculate_gain(double bearing, double angle) {
|
||||||
|
|
||||||
|
// TODO: what if the pattern is assimetric?
|
||||||
|
bearing = fabs(bearing);
|
||||||
|
if (bearing > 180)
|
||||||
|
bearing = 360 - bearing;
|
||||||
|
// for plots with 2 degrees resolution:
|
||||||
|
int azimuth = (int)floor(bearing);
|
||||||
|
azimuth += azimuth % 2;
|
||||||
|
int elevation = (int)floor(angle);
|
||||||
|
elevation += elevation % 2;
|
||||||
|
|
||||||
|
for (unsigned int i =0; i < _pattern.size(); i++) {
|
||||||
|
AntennaGain point_gain = _pattern[i];
|
||||||
|
|
||||||
|
if ( (azimuth == point_gain.azimuth) && (elevation == point_gain.elevation)) {
|
||||||
|
return point_gain.gain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,10 +83,16 @@ void FGRadioAntenna::load_antenna_pattern(string type) {
|
||||||
double gain;
|
double gain;
|
||||||
while(!file_in.eof()) {
|
while(!file_in.eof()) {
|
||||||
file_in >> heading >> elevation >> gain;
|
file_in >> heading >> elevation >> gain;
|
||||||
cerr << "head: " << heading << " elev: " << elevation << " gain: " << gain << endl;
|
if( (_mirror_y == 1) && (heading > 180) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( (_mirror_z == 1) && (elevation < 0) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//cerr << "head: " << heading << " elev: " << elevation << " gain: " << gain << endl;
|
||||||
AntennaGain datapoint;
|
AntennaGain datapoint;
|
||||||
datapoint.azimuth = heading;
|
datapoint.azimuth = heading;
|
||||||
datapoint.elevation = elevation;
|
datapoint.elevation = 90.0 - fabs(elevation);
|
||||||
datapoint.gain = gain;
|
datapoint.gain = gain;
|
||||||
_pattern.push_back(datapoint);
|
_pattern.push_back(datapoint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
FGRadioAntenna(string type);
|
FGRadioAntenna(string type);
|
||||||
~FGRadioAntenna();
|
~FGRadioAntenna();
|
||||||
double calculate_gain(double azimuth, double elevation);
|
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 ;};
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,6 +66,8 @@ FGRadioTransmission::FGRadioTransmission() {
|
||||||
|
|
||||||
_root_node = fgGetNode("sim/radio", true);
|
_root_node = fgGetNode("sim/radio", true);
|
||||||
_terrain_sampling_distance = _root_node->getDoubleValue("sampling-distance", 90.0); // regular SRTM is 90 meters
|
_terrain_sampling_distance = _root_node->getDoubleValue("sampling-distance", 90.0); // regular SRTM is 90 meters
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGRadioTransmission::~FGRadioTransmission()
|
FGRadioTransmission::~FGRadioTransmission()
|
||||||
|
@ -202,11 +204,8 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i
|
||||||
double eps_dielect=15.0;
|
double eps_dielect=15.0;
|
||||||
double sgm_conductivity = 0.005;
|
double sgm_conductivity = 0.005;
|
||||||
double eno = 301.0;
|
double eno = 301.0;
|
||||||
double frq_mhz;
|
double frq_mhz = freq;
|
||||||
if( (freq < 118.0) || (freq > 137.0) )
|
|
||||||
frq_mhz = 125.0; // sane value, middle of bandplan
|
|
||||||
else
|
|
||||||
frq_mhz = freq;
|
|
||||||
int radio_climate = 5; // continental temperate
|
int radio_climate = 5; // continental temperate
|
||||||
int pol= _polarization;
|
int pol= _polarization;
|
||||||
double conf = 0.90; // 90% of situations and time, take into account speed
|
double conf = 0.90; // 90% of situations and time, take into account speed
|
||||||
|
@ -233,6 +232,7 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i
|
||||||
double own_lat = fgGetDouble("/position/latitude-deg");
|
double own_lat = fgGetDouble("/position/latitude-deg");
|
||||||
double own_lon = fgGetDouble("/position/longitude-deg");
|
double own_lon = fgGetDouble("/position/longitude-deg");
|
||||||
double own_alt_ft = fgGetDouble("/position/altitude-ft");
|
double own_alt_ft = fgGetDouble("/position/altitude-ft");
|
||||||
|
double own_heading = fgGetDouble("/orientation/heading-deg");
|
||||||
double own_alt= own_alt_ft * SG_FEET_TO_METER;
|
double own_alt= own_alt_ft * SG_FEET_TO_METER;
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i
|
||||||
|
|
||||||
double point_distance= _terrain_sampling_distance;
|
double point_distance= _terrain_sampling_distance;
|
||||||
double course = SGGeodesy::courseRad(own_pos_c, sender_pos_c);
|
double course = SGGeodesy::courseRad(own_pos_c, sender_pos_c);
|
||||||
|
double reverse_course = SGGeodesy::courseRad(sender_pos_c, own_pos_c);
|
||||||
double distance_m = SGGeodesy::distanceM(own_pos, sender_pos);
|
double distance_m = SGGeodesy::distanceM(own_pos, sender_pos);
|
||||||
double probe_distance = 0.0;
|
double probe_distance = 0.0;
|
||||||
/** If distance larger than this value (300 km), assume reception imposssible */
|
/** If distance larger than this value (300 km), assume reception imposssible */
|
||||||
|
@ -400,6 +401,22 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i
|
||||||
//cerr << "Clutter loss: " << clutter_loss << endl;
|
//cerr << "Clutter loss: " << clutter_loss << endl;
|
||||||
//if (errnum == 4) // if parameters are outside sane values for lrprop, the alternative method is used
|
//if (errnum == 4) // if parameters are outside sane values for lrprop, the alternative method is used
|
||||||
// return -1;
|
// return -1;
|
||||||
|
double sender_heading = 270.0; // due West
|
||||||
|
double tx_antenna_bearing = sender_heading - reverse_course;
|
||||||
|
double rx_antenna_bearing = own_heading - course;
|
||||||
|
double rx_elev_angle = atan((itm_elev[2] + transmitter_height - itm_elev[(int)itm_elev[0] + 2] + receiver_height) / distance_m) * SGD_RADIANS_TO_DEGREES;
|
||||||
|
double tx_elev_angle = 0.0 - rx_elev_angle;
|
||||||
|
_TX_antenna = new FGRadioAntenna("Plot2");
|
||||||
|
_TX_antenna->set_heading(sender_heading);
|
||||||
|
_TX_antenna->set_elevation_angle(0);
|
||||||
|
double tx_pattern_gain = _TX_antenna->calculate_gain(tx_antenna_bearing, tx_elev_angle);
|
||||||
|
_RX_antenna = new FGRadioAntenna("Plot2");
|
||||||
|
_RX_antenna->set_heading(own_heading);
|
||||||
|
_RX_antenna->set_elevation_angle(fgGetDouble("/orientation/pitch-deg"));
|
||||||
|
double rx_pattern_gain = _RX_antenna->calculate_gain(rx_antenna_bearing, rx_elev_angle);
|
||||||
|
|
||||||
|
delete _TX_antenna;
|
||||||
|
delete _RX_antenna;
|
||||||
signal = link_budget - dbloss - clutter_loss + pol_loss;
|
signal = link_budget - dbloss - clutter_loss + pol_loss;
|
||||||
double signal_strength_dbm = signal_strength - dbloss - clutter_loss + pol_loss;
|
double signal_strength_dbm = signal_strength - dbloss - clutter_loss + pol_loss;
|
||||||
double field_strength_uV = dbm_to_microvolt(signal_strength_dbm);
|
double field_strength_uV = dbm_to_microvolt(signal_strength_dbm);
|
||||||
|
@ -407,6 +424,8 @@ double FGRadioTransmission::ITM_calculate_attenuation(SGGeod pos, double freq, i
|
||||||
_root_node->setDoubleValue("station[0]/field-strength-uV", field_strength_uV);
|
_root_node->setDoubleValue("station[0]/field-strength-uV", field_strength_uV);
|
||||||
_root_node->setDoubleValue("station[0]/signal", signal);
|
_root_node->setDoubleValue("station[0]/signal", signal);
|
||||||
_root_node->setDoubleValue("station[0]/tx-erp", tx_erp);
|
_root_node->setDoubleValue("station[0]/tx-erp", tx_erp);
|
||||||
|
_root_node->setDoubleValue("station[0]/tx-pattern-gain", tx_pattern_gain);
|
||||||
|
_root_node->setDoubleValue("station[0]/rx-pattern-gain", rx_pattern_gain);
|
||||||
return signal;
|
return signal;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include "antenna.hxx"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ private:
|
||||||
double _tx_antenna_gain;
|
double _tx_antenna_gain;
|
||||||
double _rx_line_losses;
|
double _rx_line_losses;
|
||||||
double _tx_line_losses;
|
double _tx_line_losses;
|
||||||
|
FGRadioAntenna* _TX_antenna;
|
||||||
|
FGRadioAntenna* _RX_antenna;
|
||||||
double _terrain_sampling_distance;
|
double _terrain_sampling_distance;
|
||||||
int _polarization;
|
int _polarization;
|
||||||
std::map<string, double[2]> _mat_database;
|
std::map<string, double[2]> _mat_database;
|
||||||
|
|
Loading…
Add table
Reference in a new issue