diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 90eba53a9..15520295a 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -736,10 +737,17 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, double snr = calculate_attenuation(rec, parent, ground_to_air); if (snr <= 0) return; - if (snr > 0 && snr < 10) { - //for low snr values implement a way to make the conversation - //hard to understand (perhaps eliminate letters from words or such - return; + if (snr > 0 && snr < 12) { + //for low SNR values implement a way to make the conversation + //hard to understand but audible + 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); + } + } if (rec->allowTransmissions()) { @@ -753,12 +761,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, } } -int FGATCController::calculate_attenuation(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 - ///////////////////////////////////////////////// + ////////////////////////////////////////////////// + /// Implement radio attenuation // + /// based on the Longley-Rice propagation model// + ////////////////////////////////////////////////// FGScenery * scenery = globals->get_scenery(); // player aircraft position @@ -767,64 +775,96 @@ int FGATCController::calculate_attenuation(FGTrafficRecord * rec, FGAirportDynam 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 + // position of sender radio antenna (HAAT) // sender can be aircraft or ground station + double ATC_HAAT = 30.0; + double Aircraft_HAAT = 7.0; double sender_alt_ft,sender_alt; + double transceiver_height=0.0; + double receiver_height=0.0; SGGeod sender_pos; if(ground_to_air) { sender_alt_ft = parent->getElevation(); - sender_alt = sender_alt_ft * SG_FEET_TO_METER; + sender_alt = sender_alt_ft * SG_FEET_TO_METER + ATC_HAAT; sender_pos= SGGeod::fromDegM( parent->getLongitude(), parent->getLatitude(), sender_alt ); } else { sender_alt_ft = rec->getAltitude(); - sender_alt = sender_alt_ft * SG_FEET_TO_METER; + sender_alt = sender_alt_ft * SG_FEET_TO_METER + Aircraft_HAAT; sender_pos= SGGeod::fromDegM( rec->getLongitude(), rec->getLatitude(), sender_alt ); } - double point_distance= 100.0; // regular SRTM is 90 meters - double course = SGGeodesy::courseDeg(own_pos, sender_pos); + 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; + + cerr << "ITM:: Distance: " << distance_m << endl; + double max_points = distance_m / point_distance; deque _elevations; + SGGeod probe_pilot = SGGeod::fromGeoc(center.advanceRadM( course, 0 )); + double elevation_under_pilot = 0.0; + if (scenery->get_elevation_m( probe_pilot, elevation_under_pilot, NULL )) { + receiver_height = own_alt - elevation_under_pilot; + } + _elevations.push_front(receiver_height); + + SGGeod probe_sender = SGGeod::fromGeoc(center.advanceRadM( course, distance_m )); + double elevation_under_sender = 0.0; + if (scenery->get_elevation_m( probe_sender, elevation_under_sender, NULL )) { + transceiver_height = sender_alt - elevation_under_sender; + } + // If distance larger than this value (400 km), assume reception imposssible // technically 400 km is no problem if LOS conditions exist, // but we do this to spare resources if (distance_m > 400000) - return -1; + return -1.0; - while (_elevations.size() < (deque::size_type)max_points) { - SGGeod probe = SGGeod::fromGeoc(center.advanceRadM( course, point_distance )); + int e_size = (deque::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; } } - /* + _elevations.push_front(transceiver_height); double max_alt_between=0.0; for( deque::size_type i = 0; i < _elevations.size(); i++ ) { if (_elevations[i] > max_alt_between) { max_alt_between = _elevations[i]; } } - */ - double num_points= (int)_elevations.size(); - _elevations.push_front(distance_m); + 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(); + int size = _elevations.size(); double itm_elev[size]; for(int i=0;i