begin work on radio subsystem
This commit is contained in:
parent
80e5585cc3
commit
f96123de1c
7 changed files with 353 additions and 200 deletions
|
@ -5,7 +5,6 @@ set(SOURCES
|
||||||
atcdialog.cxx
|
atcdialog.cxx
|
||||||
trafficcontrol.cxx
|
trafficcontrol.cxx
|
||||||
CommStation.cxx
|
CommStation.cxx
|
||||||
itm.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
flightgear_component(ATC "${SOURCES}")
|
flightgear_component(ATC "${SOURCES}")
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <math.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
|
@ -50,8 +47,6 @@
|
||||||
#include <Airports/groundnetwork.hxx>
|
#include <Airports/groundnetwork.hxx>
|
||||||
#include <Airports/dynamics.hxx>
|
#include <Airports/dynamics.hxx>
|
||||||
#include <Airports/simple.hxx>
|
#include <Airports/simple.hxx>
|
||||||
#define WITH_POINT_TO_POINT
|
|
||||||
#include "itm.cpp"
|
|
||||||
|
|
||||||
using std::sort;
|
using std::sort;
|
||||||
|
|
||||||
|
@ -736,25 +731,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
|| (onBoardRadioFreqI1 == stationFreq)) {
|
|| (onBoardRadioFreqI1 == stationFreq)) {
|
||||||
|
|
||||||
if (rec->allowTransmissions()) {
|
if (rec->allowTransmissions()) {
|
||||||
double snr = calculate_attenuation(rec, parent, ground_to_air);
|
|
||||||
if (snr <= 0)
|
|
||||||
return;
|
|
||||||
if (snr > 0 && snr < 12) {
|
|
||||||
//for low SNR values implement a way to make the conversation
|
|
||||||
//hard to understand but audible
|
|
||||||
//how this works in the real world, is the receiver AGC fails to capture the slope
|
|
||||||
//and the signal, due to being amplitude modulated, decreases volume after demodulation
|
|
||||||
//the implementation below is more akin to what would happen on a FM transmission
|
|
||||||
//therefore the correct way would be to work on the volume
|
|
||||||
string hash_noise = " ";
|
|
||||||
int reps = fabs((int)snr - 11);
|
|
||||||
int t_size = text.size();
|
|
||||||
for (int n=1;n<=reps * 2;n++) {
|
|
||||||
int pos = rand() % t_size -1;
|
|
||||||
text.replace(pos,1, hash_noise);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fgSetString("/sim/messages/atc", text.c_str());
|
fgSetString("/sim/messages/atc", text.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -765,180 +742,6 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGATCController::calculate_attenuation(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|
||||||
int ground_to_air) {
|
|
||||||
|
|
||||||
/// Implement radio attenuation
|
|
||||||
/// based on the Longley-Rice propagation model
|
|
||||||
|
|
||||||
FGScenery * scenery = globals->get_scenery();
|
|
||||||
// player aircraft position
|
|
||||||
double own_lat = fgGetDouble("/position/latitude-deg");
|
|
||||||
double own_lon = fgGetDouble("/position/longitude-deg");
|
|
||||||
double own_alt_ft = fgGetDouble("/position/altitude-ft");
|
|
||||||
double own_alt= own_alt_ft * SG_FEET_TO_METER;
|
|
||||||
|
|
||||||
//cerr << "ITM:: pilot Lat: " << own_lat << ", Lon: " << own_lon << ", Alt: " << own_alt << endl;
|
|
||||||
|
|
||||||
SGGeod own_pos = SGGeod::fromDegM( own_lon, own_lat, own_alt );
|
|
||||||
SGGeod max_own_pos = SGGeod::fromDegM( own_lon, own_lat, SG_MAX_ELEVATION_M );
|
|
||||||
SGGeoc center = SGGeoc::fromGeod( max_own_pos );
|
|
||||||
SGGeoc own_pos_c = SGGeoc::fromGeod( own_pos );
|
|
||||||
|
|
||||||
// position of sender radio antenna (HAAT)
|
|
||||||
// sender can be aircraft or ground station
|
|
||||||
double ATC_HAAT = 30.0;
|
|
||||||
double Aircraft_HAAT = 5.0;
|
|
||||||
double sender_alt_ft,sender_alt;
|
|
||||||
double transmitter_height=0.0;
|
|
||||||
double receiver_height=0.0;
|
|
||||||
SGGeod sender_pos;
|
|
||||||
SGGeod max_sender_pos;
|
|
||||||
if(ground_to_air) {
|
|
||||||
sender_alt_ft = parent->getElevation();
|
|
||||||
sender_alt = sender_alt_ft * SG_FEET_TO_METER;
|
|
||||||
sender_pos= SGGeod::fromDegM( parent->getLongitude(),
|
|
||||||
parent->getLatitude(), sender_alt );
|
|
||||||
max_sender_pos = SGGeod::fromDegM( parent->getLongitude(),
|
|
||||||
parent->getLatitude(), SG_MAX_ELEVATION_M );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sender_alt_ft = rec->getAltitude();
|
|
||||||
sender_alt = sender_alt_ft * SG_FEET_TO_METER;
|
|
||||||
sender_pos= SGGeod::fromDegM( rec->getLongitude(),
|
|
||||||
rec->getLatitude(), sender_alt );
|
|
||||||
max_sender_pos = SGGeod::fromDegM( rec->getLongitude(),
|
|
||||||
rec->getLatitude(), SG_MAX_ELEVATION_M );
|
|
||||||
}
|
|
||||||
SGGeoc sender_pos_c = SGGeoc::fromGeod( sender_pos );
|
|
||||||
//cerr << "ITM:: sender Lat: " << parent->getLatitude() << ", Lon: " << parent->getLongitude() << ", Alt: " << sender_alt << endl;
|
|
||||||
|
|
||||||
double point_distance= 90.0; // regular SRTM is 90 meters
|
|
||||||
double course = SGGeodesy::courseRad(own_pos_c, sender_pos_c);
|
|
||||||
double distance_m = SGGeodesy::distanceM(own_pos, sender_pos);
|
|
||||||
double probe_distance = 0.0;
|
|
||||||
// If distance larger than this value (300 km), assume reception imposssible
|
|
||||||
// technically 300 km is no problem if LOS conditions exist,
|
|
||||||
// but we do this to spare resources
|
|
||||||
if (distance_m > 300000)
|
|
||||||
return -1.0;
|
|
||||||
|
|
||||||
|
|
||||||
double max_points = distance_m / point_distance;
|
|
||||||
deque<double> _elevations;
|
|
||||||
|
|
||||||
|
|
||||||
double elevation_under_pilot = 0.0;
|
|
||||||
if (scenery->get_elevation_m( max_own_pos, elevation_under_pilot, NULL )) {
|
|
||||||
receiver_height = own_alt - elevation_under_pilot + 3; //assume antenna located 3 meters above ground
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double elevation_under_sender = 0.0;
|
|
||||||
if (scenery->get_elevation_m( max_sender_pos, elevation_under_sender, NULL )) {
|
|
||||||
transmitter_height = sender_alt - elevation_under_sender;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
transmitter_height = sender_alt;
|
|
||||||
}
|
|
||||||
if(ground_to_air)
|
|
||||||
transmitter_height += ATC_HAAT;
|
|
||||||
else
|
|
||||||
transmitter_height += Aircraft_HAAT;
|
|
||||||
|
|
||||||
cerr << "ITM:: RX-height: " << receiver_height << ", TX-height: " << transmitter_height << ", Distance: " << distance_m << endl;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int e_size = (deque<unsigned>::size_type)max_points;
|
|
||||||
|
|
||||||
while (_elevations.size() <= e_size) {
|
|
||||||
probe_distance += point_distance;
|
|
||||||
SGGeod probe = SGGeod::fromGeoc(center.advanceRadM( course, probe_distance ));
|
|
||||||
|
|
||||||
double elevation_m = 0.0;
|
|
||||||
|
|
||||||
if (scenery->get_elevation_m( probe, elevation_m, NULL )) {
|
|
||||||
_elevations.push_front(elevation_m);
|
|
||||||
//cerr << "ITM:: Probe elev: " << elevation_m << endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_elevations.push_front(0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_elevations.push_back(elevation_under_pilot);
|
|
||||||
_elevations.push_front(elevation_under_sender);
|
|
||||||
double max_alt_between=0.0;
|
|
||||||
for( deque<double>::size_type i = 0; i < _elevations.size(); i++ ) {
|
|
||||||
if (_elevations[i] > max_alt_between) {
|
|
||||||
max_alt_between = _elevations[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double num_points= (double)_elevations.size();
|
|
||||||
//cerr << "ITM:: Max alt between: " << max_alt_between << ", num points:" << num_points << endl;
|
|
||||||
_elevations.push_front(point_distance);
|
|
||||||
_elevations.push_front(num_points -1);
|
|
||||||
int size = _elevations.size();
|
|
||||||
double itm_elev[size];
|
|
||||||
for(int i=0;i<size;i++) {
|
|
||||||
itm_elev[i]=_elevations[i];
|
|
||||||
//cerr << "ITM:: itm_elev: " << _elevations[i] << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////// ITM default parameters //////////////
|
|
||||||
// later perhaps take them from tile materials?
|
|
||||||
double eps_dielect=15.0;
|
|
||||||
double sgm_conductivity = 0.005;
|
|
||||||
double eno = 301.0;
|
|
||||||
double frq_mhz = 125.0; // middle of bandplan
|
|
||||||
int radio_climate = 5; // continental temperate
|
|
||||||
int pol=1; // assuming vertical polarization although this is more complex in reality
|
|
||||||
double conf = 0.90; // my own tests in Radiomobile have worked best with these values
|
|
||||||
double rel = 0.80; // ^^
|
|
||||||
double dbloss;
|
|
||||||
char strmode[150];
|
|
||||||
int errnum;
|
|
||||||
|
|
||||||
/////////// radio parameters ///////////
|
|
||||||
double receiver_sensitivity = -110.0; // typical AM receiver sensitivity seems to be 0.8 microVolt at 12dB SINAD
|
|
||||||
// AM transmitter power in dBm.
|
|
||||||
// Note this value is calculated from the typical final transistor stage output
|
|
||||||
// !!! small aircraft have portable transmitters which operate at 36 dBm output (4 Watts)
|
|
||||||
// later store this value in aircraft description
|
|
||||||
// ATC comms usually operate high power equipment, thus making the link asymetrical; this is ignored for now
|
|
||||||
double transmitter_power = 43.0;
|
|
||||||
double antenna_gain = 2.0; //real-life gain for conventional monopole/dipole antenna
|
|
||||||
if(ground_to_air)
|
|
||||||
transmitter_power = 49.0;
|
|
||||||
else
|
|
||||||
transmitter_power = 43.0;
|
|
||||||
if(ground_to_air)
|
|
||||||
antenna_gain = 5.0; //pilot plane's antenna gain + ground station antenna gain
|
|
||||||
else
|
|
||||||
antenna_gain = 2.0; //pilot plane's antenna gain + AI aircraft antenna gain
|
|
||||||
double link_budget = transmitter_power - receiver_sensitivity + antenna_gain;
|
|
||||||
|
|
||||||
|
|
||||||
// first Fresnel zone radius
|
|
||||||
// frequency in the middle of the bandplan, more accuracy is not necessary
|
|
||||||
double fz_clr= 8.657 * sqrt(distance_m / 0.125);
|
|
||||||
|
|
||||||
// TODO: If we clear the first Fresnel zone, we are into line of sight teritory
|
|
||||||
|
|
||||||
// else we need to calculate point to point link loss
|
|
||||||
|
|
||||||
point_to_point(itm_elev, transmitter_height, receiver_height,
|
|
||||||
eps_dielect, sgm_conductivity, eno, frq_mhz, radio_climate,
|
|
||||||
pol, conf, rel, dbloss, strmode, errnum);
|
|
||||||
|
|
||||||
cerr << "ITM:: Link budget: " << link_budget << ", Attenuation: " << dbloss << " dBm, " << strmode << ", Error: " << errnum << endl;
|
|
||||||
|
|
||||||
//if (errnum !=0 && errnum !=1)
|
|
||||||
// return -1;
|
|
||||||
double snr = link_budget - dbloss;
|
|
||||||
return snr;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
string FGATCController::formatATCFrequency3_2(int freq)
|
string FGATCController::formatATCFrequency3_2(int freq)
|
||||||
{
|
{
|
||||||
|
|
|
@ -304,7 +304,6 @@ public:
|
||||||
string getGateName(FGAIAircraft *aircraft);
|
string getGateName(FGAIAircraft *aircraft);
|
||||||
virtual void render(bool) = 0;
|
virtual void render(bool) = 0;
|
||||||
virtual string getName() = 0;
|
virtual string getName() = 0;
|
||||||
double calculate_attenuation(FGTrafficRecord * rec, FGAirportDynamics *parent, int ground_to_air);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
include(FlightGearComponent)
|
include(FlightGearComponent)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
itm.cpp
|
||||||
adf.cxx
|
adf.cxx
|
||||||
agradar.cxx
|
agradar.cxx
|
||||||
airspeed_indicator.cxx
|
airspeed_indicator.cxx
|
||||||
|
|
282
src/Instrumentation/commradio.cxx
Normal file
282
src/Instrumentation/commradio.cxx
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// commradio.cxx -- implementation of FGCommRadio
|
||||||
|
//
|
||||||
|
// Written by Adrian Musceac, 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
|
||||||
|
// 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 <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <Scenery/scenery.hxx>
|
||||||
|
|
||||||
|
#define WITH_POINT_TO_POINT 1
|
||||||
|
#include "itm.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
FGCommRadio::FGCommRadio(SGPropertyNode *node) {
|
||||||
|
|
||||||
|
/////////// radio parameters ///////////
|
||||||
|
_receiver_sensitivity = -110.0; // typical AM receiver sensitivity seems to be 0.8 microVolt at 12dB SINAD
|
||||||
|
// AM transmitter power in dBm.
|
||||||
|
// Note this value is calculated from the typical final transistor stage output
|
||||||
|
// !!! small aircraft have portable transmitters which operate at 36 dBm output (4 Watts)
|
||||||
|
// later store this value in aircraft description
|
||||||
|
// ATC comms usually operate high power equipment, thus making the link asymetrical; this is ignored for now
|
||||||
|
_transmitter_power = 43.0;
|
||||||
|
//pilot plane's antenna gain + AI aircraft antenna gain
|
||||||
|
//real-life gain for conventional monopole/dipole antenna
|
||||||
|
_antenna_gain = 2.0;
|
||||||
|
_propagation_model = 2; // in the future choose between models via option: realistic radio on/off
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FGCommRadio::~FGCommRadio()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGCommRadio::init ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FGCommRadio::bind ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FGCommRadio::update ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double FGCommRadio::getFrequency(int radio) {
|
||||||
|
double freq = 118.0;
|
||||||
|
switch (radio) {
|
||||||
|
case 1:
|
||||||
|
freq = fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
freq = fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
freq = fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
|
||||||
|
|
||||||
|
}
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FGCommRadio::receive(SGGeod tx_pos, double freq, string text,
|
||||||
|
int ground_to_air) {
|
||||||
|
|
||||||
|
comm1 = getFrequency(1);
|
||||||
|
comm2 = getFrequency(2);
|
||||||
|
if ( (freq != comm1) && (freq != comm2) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
double signal = ITM_calculate_attenuation(tx_pos, freq, ground_to_air);
|
||||||
|
if (signal <= 0)
|
||||||
|
return;
|
||||||
|
if ((signal > 0) && (signal < 12)) {
|
||||||
|
//for low SNR values implement a way to make the conversation
|
||||||
|
//hard to understand but audible
|
||||||
|
//how this works in the real world, is the receiver AGC fails to capture the slope
|
||||||
|
//and the signal, due to being amplitude modulated, decreases volume after demodulation
|
||||||
|
//the implementation below is more akin to what would happen on a FM transmission
|
||||||
|
//therefore the correct way would be to work on the volume
|
||||||
|
string hash_noise = " ";
|
||||||
|
int reps = fabs((int)signal - 11);
|
||||||
|
int t_size = text.size();
|
||||||
|
for (int n=1;n<=reps * 2;n++) {
|
||||||
|
int pos = rand() % t_size -1;
|
||||||
|
text.replace(pos,1, hash_noise);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
fgSetString("/sim/messages/atc", text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double FGCommRadio::ITM_calculate_attenuation(SGGeod pos, double freq,
|
||||||
|
int ground_to_air) {
|
||||||
|
|
||||||
|
/// Implement radio attenuation
|
||||||
|
/// based on the Longley-Rice propagation model
|
||||||
|
|
||||||
|
////////////// ITM default parameters //////////////
|
||||||
|
// in the future perhaps take them from tile materials?
|
||||||
|
double eps_dielect=15.0;
|
||||||
|
double sgm_conductivity = 0.005;
|
||||||
|
double eno = 301.0;
|
||||||
|
double frq_mhz;
|
||||||
|
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 pol=1; // assuming vertical polarization although this is more complex in reality
|
||||||
|
double conf = 0.90; // 90% of situations and time, take into account speed
|
||||||
|
double rel = 0.90; // ^^
|
||||||
|
double dbloss;
|
||||||
|
char strmode[150];
|
||||||
|
int errnum;
|
||||||
|
|
||||||
|
double tx_pow,ant_gain;
|
||||||
|
double signal = 0.0;
|
||||||
|
|
||||||
|
if(ground_to_air)
|
||||||
|
tx_pow = _transmitter_power + 6.0;
|
||||||
|
|
||||||
|
if(ground_to_air)
|
||||||
|
ant_gain = _antenna_gain + 3.0; //pilot plane's antenna gain + ground station antenna gain
|
||||||
|
|
||||||
|
double link_budget = tx_pow - _receiver_sensitivity + ant_gain;
|
||||||
|
|
||||||
|
FGScenery * scenery = globals->get_scenery();
|
||||||
|
|
||||||
|
double own_lat = fgGetDouble("/position/latitude-deg");
|
||||||
|
double own_lon = fgGetDouble("/position/longitude-deg");
|
||||||
|
double own_alt_ft = fgGetDouble("/position/altitude-ft");
|
||||||
|
double own_alt= own_alt_ft * SG_FEET_TO_METER;
|
||||||
|
|
||||||
|
|
||||||
|
//cerr << "ITM:: pilot Lat: " << own_lat << ", Lon: " << own_lon << ", Alt: " << own_alt << endl;
|
||||||
|
|
||||||
|
SGGeod own_pos = SGGeod::fromDegM( own_lon, own_lat, own_alt );
|
||||||
|
SGGeod max_own_pos = SGGeod::fromDegM( own_lon, own_lat, SG_MAX_ELEVATION_M );
|
||||||
|
SGGeoc center = SGGeoc::fromGeod( max_own_pos );
|
||||||
|
SGGeoc own_pos_c = SGGeoc::fromGeod( own_pos );
|
||||||
|
|
||||||
|
// position of sender radio antenna (HAAT)
|
||||||
|
// sender can be aircraft or ground station
|
||||||
|
double ATC_HAAT = 30.0;
|
||||||
|
double Aircraft_HAAT = 5.0;
|
||||||
|
double sender_alt_ft,sender_alt;
|
||||||
|
double transmitter_height=0.0;
|
||||||
|
double receiver_height=0.0;
|
||||||
|
SGGeod sender_pos = pos;
|
||||||
|
|
||||||
|
sender_alt_ft = sender_pos.getElevationFt();
|
||||||
|
sender_alt = sender_alt_ft * SG_FEET_TO_METER;
|
||||||
|
SGGeod max_sender_pos = SGGeod::fromGeodM( pos, SG_MAX_ELEVATION_M );
|
||||||
|
SGGeoc sender_pos_c = SGGeoc::fromGeod( sender_pos );
|
||||||
|
//cerr << "ITM:: sender Lat: " << parent->getLatitude() << ", Lon: " << parent->getLongitude() << ", Alt: " << sender_alt << endl;
|
||||||
|
|
||||||
|
double point_distance= 90.0; // regular SRTM is 90 meters
|
||||||
|
double course = SGGeodesy::courseRad(own_pos_c, sender_pos_c);
|
||||||
|
double distance_m = SGGeodesy::distanceM(own_pos, sender_pos);
|
||||||
|
double probe_distance = 0.0;
|
||||||
|
// If distance larger than this value (300 km), assume reception imposssible to preserve resources
|
||||||
|
if (distance_m > 300000)
|
||||||
|
return -1.0;
|
||||||
|
// If above 9000, consider LOS mode and calculate free-space att
|
||||||
|
if (own_alt > 9000) {
|
||||||
|
dbloss = 20 * log10(distance_m) +20 * log10(frq_mhz) -27.55;
|
||||||
|
signal = link_budget - dbloss;
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double max_points = distance_m / point_distance;
|
||||||
|
deque<double> _elevations;
|
||||||
|
|
||||||
|
double elevation_under_pilot = 0.0;
|
||||||
|
if (scenery->get_elevation_m( max_own_pos, elevation_under_pilot, NULL )) {
|
||||||
|
receiver_height = own_alt - elevation_under_pilot + 3; //assume antenna located 3 meters above ground
|
||||||
|
}
|
||||||
|
|
||||||
|
double elevation_under_sender = 0.0;
|
||||||
|
if (scenery->get_elevation_m( max_sender_pos, elevation_under_sender, NULL )) {
|
||||||
|
transmitter_height = sender_alt - elevation_under_sender;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
transmitter_height = sender_alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ground_to_air)
|
||||||
|
transmitter_height += ATC_HAAT;
|
||||||
|
else
|
||||||
|
transmitter_height += Aircraft_HAAT;
|
||||||
|
|
||||||
|
cerr << "ITM:: RX-height: " << receiver_height << ", TX-height: " << transmitter_height << ", Distance: " << distance_m << endl;
|
||||||
|
|
||||||
|
unsigned int e_size = (deque<unsigned>::size_type)max_points;
|
||||||
|
|
||||||
|
while (_elevations.size() <= e_size) {
|
||||||
|
probe_distance += point_distance;
|
||||||
|
SGGeod probe = SGGeod::fromGeoc(center.advanceRadM( course, probe_distance ));
|
||||||
|
|
||||||
|
double elevation_m = 0.0;
|
||||||
|
|
||||||
|
if (scenery->get_elevation_m( probe, elevation_m, NULL )) {
|
||||||
|
_elevations.push_front(elevation_m);
|
||||||
|
//cerr << "ITM:: Probe elev: " << elevation_m << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_elevations.push_front(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_elevations.push_back(elevation_under_pilot);
|
||||||
|
_elevations.push_front(elevation_under_sender);
|
||||||
|
|
||||||
|
double max_alt_between=0.0;
|
||||||
|
for( deque<double>::size_type i = 0; i < _elevations.size(); i++ ) {
|
||||||
|
if (_elevations[i] > max_alt_between) {
|
||||||
|
max_alt_between = _elevations[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double num_points= (double)_elevations.size();
|
||||||
|
//cerr << "ITM:: Max alt between: " << max_alt_between << ", num points:" << num_points << endl;
|
||||||
|
_elevations.push_front(point_distance);
|
||||||
|
_elevations.push_front(num_points -1);
|
||||||
|
int size = _elevations.size();
|
||||||
|
double itm_elev[size];
|
||||||
|
for(int i=0;i<size;i++) {
|
||||||
|
itm_elev[i]=_elevations[i];
|
||||||
|
//cerr << "ITM:: itm_elev: " << _elevations[i] << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// first Fresnel zone radius
|
||||||
|
// frequency in the middle of the bandplan, more accuracy is not necessary
|
||||||
|
double fz_clr= 8.657 * sqrt(distance_m / 0.125);
|
||||||
|
|
||||||
|
// TODO: If we clear the first Fresnel zone, we are into line of sight teritory
|
||||||
|
|
||||||
|
// else we need to calculate point to point link loss
|
||||||
|
|
||||||
|
point_to_point(itm_elev, transmitter_height, receiver_height,
|
||||||
|
eps_dielect, sgm_conductivity, eno, frq_mhz, radio_climate,
|
||||||
|
pol, conf, rel, dbloss, strmode, errnum);
|
||||||
|
|
||||||
|
cerr << "ITM:: Link budget: " << link_budget << ", Attenuation: " << dbloss << " dBm, " << strmode << ", Error: " << errnum << endl;
|
||||||
|
|
||||||
|
//if (errnum == 4)
|
||||||
|
// return -1;
|
||||||
|
signal = link_budget - dbloss;
|
||||||
|
return signal;
|
||||||
|
|
||||||
|
}
|
69
src/Instrumentation/commradio.hxx
Normal file
69
src/Instrumentation/commradio.hxx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// commradio.hxx -- class to manage a comm radio instance
|
||||||
|
//
|
||||||
|
// Written by Adrian Musceac, 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
|
||||||
|
// 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 __cplusplus
|
||||||
|
# error This library requires C++
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
|
||||||
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
|
class FGCommRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool isOperable() const
|
||||||
|
{ return _operable; }
|
||||||
|
bool _operable; ///< is the unit serviceable, on, powered, etc
|
||||||
|
|
||||||
|
double _receiver_sensitivity;
|
||||||
|
double _transmitter_power;
|
||||||
|
double _antenna_gain;
|
||||||
|
|
||||||
|
int _propagation_model; /// 0 none, 1 round Earth, 2 ITM
|
||||||
|
double ITM_calculate_attenuation(SGGeod tx_pos, double freq, int ground_to_air)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FGCommRadio(SGPropertyNode *node);
|
||||||
|
~FGCommRadio();
|
||||||
|
|
||||||
|
void init ();
|
||||||
|
void bind ();
|
||||||
|
void unbind ();
|
||||||
|
void update (double dt);
|
||||||
|
|
||||||
|
void setFrequency(double freq, int radio);
|
||||||
|
double getFrequency(int radio);
|
||||||
|
void setTxPower(double txpower) { _transmitter_power = txpower; };
|
||||||
|
void receive_text(SGGeod tx_pos, double freq, string text, int ground_to_air);
|
||||||
|
void setPropagationModel(int model) { _propagation_model = model; };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue