1
0
Fork 0

David Luff writes:

Heres an update to the ATIS stuff.  In brief:

The possible buffer overflow in the display with wind should
hopefully be fixed.

Temperature is taken from the global temperature property instead
of being hardwired.

The display class now includes an implementation of the member
function to change the repeating message.

The message callsign is no longer hardwired.  The first message
from each station is generated with a random callsign.
Subsequent messages from the same station have the callsign
incremented every hour.  A map of airport-id vs. last callsign and
transmission time is kept for each station that has transmitted for
the duration of the FlightGear session.  The logic might be flaky if
FlightGear is run for more than 24 hours at a stretch between
visiting the same ATIS station though!  (ie I don't check the day.)
This map is kept in the atislist class.  This might not be the best
long-term place for it (in an ATC class of some sort might be
better), but it works for now.
This commit is contained in:
curt 2001-11-19 23:53:36 +00:00
parent 36de63366b
commit e35fffa035
9 changed files with 172 additions and 32 deletions

2
aclocal.m4 vendored
View file

@ -1,4 +1,4 @@
dnl aclocal.m4 generated automatically by aclocal 1.4-p4 dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation dnl This file is free software; the Free Software Foundation

View file

@ -37,6 +37,7 @@ FGATCDisplay *current_atcdisplay;
// Constructor // Constructor
FGATCDisplay::FGATCDisplay( void ) { FGATCDisplay::FGATCDisplay( void ) {
rep_msg = false; rep_msg = false;
change_msg_flag = false;
dsp_offset1 = 0; dsp_offset1 = 0;
dsp_offset2 = 0; dsp_offset2 = 0;
} }
@ -53,7 +54,30 @@ void FGATCDisplay::init( void ) {
// update - this actually draws the visuals and should be called from the main Flightgear rendering loop. // update - this actually draws the visuals and should be called from the main Flightgear rendering loop.
void FGATCDisplay::update() { void FGATCDisplay::update() {
// These strings are used for temporary storage of the transmission string in order
// that the string we view only changes when the next repitition starts scrolling
// even though the master string (rep_msg_str) may change at any time.
static string msg1 = "";
static string msg2 = "";
if(rep_msg) { if(rep_msg) {
//cout << "dsp_offset1 = " << dsp_offset1 << " dsp_offset2 = " << dsp_offset2 << endl;
if(dsp_offset1 == 0) {
msg1 = rep_msg_str;
}
if(dsp_offset2 == 0) {
msg2 = rep_msg_str;
}
// Check for the situation where one offset is negative and the message is changed
if(change_msg_flag) {
if(dsp_offset1 < 0) {
msg1 = rep_msg_str;
} else if(dsp_offset2 < 0) {
msg2 = rep_msg_str;
}
change_msg_flag = false;
}
float fps = general.get_frame_rate(); float fps = general.get_frame_rate();
//cout << "In FGATC::update()" << endl; //cout << "In FGATC::update()" << endl;
@ -62,13 +86,6 @@ void FGATCDisplay::update() {
int iwidth = xsize_node->getIntValue(); int iwidth = xsize_node->getIntValue();
int iheight = ysize_node->getIntValue(); int iheight = ysize_node->getIntValue();
//TODO - if the string is bigger than the buffer the program exits - we really ought to have a robust check here
char buf[256];
//float fps = visibility/1600;
// sprintf(buf,"%-4.1f %7.0f %7.0f", fps, tris, culled);
// sprintf(buf,"%s %-5.1f", "visibility ", visibility);
sprintf(buf,"%s", rep_msg_str.c_str());
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
@ -82,13 +99,13 @@ void FGATCDisplay::update() {
glColor3f( 0.9, 0.4, 0.2 ); glColor3f( 0.9, 0.4, 0.2 );
// guiFnt.drawString( buf, // guiFnt.drawString( rep_msg_str.c_str(),
// int(iwidth - guiFnt.getStringWidth(buf) - 10 - (int)dsp_offset), // int(iwidth - guiFnt.getStringWidth(buf) - 10 - (int)dsp_offset),
// (iheight - 20) ); // (iheight - 20) );
guiFnt.drawString( buf, guiFnt.drawString( msg1.c_str(),
int(iwidth - 10 - dsp_offset1), int(iwidth - 10 - dsp_offset1),
(iheight - 20) ); (iheight - 20) );
guiFnt.drawString( buf, guiFnt.drawString( msg2.c_str(),
int(iwidth - 10 - dsp_offset2), int(iwidth - 10 - dsp_offset2),
(iheight - 20) ); (iheight - 20) );
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
@ -123,7 +140,8 @@ void FGATCDisplay::RegisterRepeatingMessage(string msg) {
} }
void FGATCDisplay::ChangeRepeatingMessage(string newmsg) { void FGATCDisplay::ChangeRepeatingMessage(string newmsg) {
//Not implemented yet rep_msg_str = newmsg;
change_msg_flag = true;
return; return;
} }

View file

@ -47,6 +47,7 @@ class FGATCDisplay {
private: private:
bool rep_msg; // Flag to indicate there is a repeating transmission to display bool rep_msg; // Flag to indicate there is a repeating transmission to display
bool change_msg_flag; // Flag to indicate that the repeating message has changed
float dsp_offset1; // Used to set the correct position of scrolling display float dsp_offset1; // Used to set the correct position of scrolling display
float dsp_offset2; float dsp_offset2;
string rep_msg_str; // The repeating transmission to play string rep_msg_str; // The repeating transmission to play

View file

@ -25,17 +25,17 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <stdlib.h> // atoi()
#include <string> #include <string>
SG_USING_STD(string); SG_USING_STD(string);
//#include STL_IOSTREAM #include STL_IOSTREAM
//#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
//SG_USING_STD(cout); SG_USING_STD(cout);
//#endif #endif
//#include <simgear/debug/logstream.hxx> //#include <simgear/debug/logstream.hxx>
//#include <simgear/misc/sgstream.hxx> //#include <simgear/misc/sgstream.hxx>
//#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
//#ifndef FG_OLD_WEATHER //#ifndef FG_OLD_WEATHER
@ -48,6 +48,41 @@ SG_USING_STD(string);
#include <Airports/runways.hxx> #include <Airports/runways.hxx>
#include "atis.hxx" #include "atis.hxx"
#include "atislist.hxx"
string GetPhoneticIdent(int i) {
// TODO - Check i is between 1 and 26 and wrap if necessary
switch(i) {
case 1 : return("Alpha");
case 2 : return("Bravo");
case 3 : return("Charlie");
case 4 : return("Delta");
case 5 : return("Echo");
case 6 : return("Foxtrot");
case 7 : return("Golf");
case 8 : return("Hotel");
case 9 : return("Indigo");
case 10 : return("Juliet");
case 11 : return("Kilo");
case 12 : return("Lima");
case 13 : return("Mike");
case 14 : return("November");
case 15 : return("Oscar");
case 16 : return("Papa");
case 17 : return("Quebec");
case 18 : return("Romeo");
case 19 : return("Sierra");
case 20 : return("Tango");
case 21 : return("Uniform");
case 22 : return("Victor");
case 23 : return("Whiskey");
case 24 : return("X-ray");
case 25 : return("Yankee");
case 26 : return("Zulu");
}
// We shouldn't get here
return("Error");
}
// Constructor // Constructor
FGATIS::FGATIS() { FGATIS::FGATIS() {
@ -64,6 +99,11 @@ string FGATIS::get_transmission() {
double visibility; double visibility;
double temperature; double temperature;
char buf[10]; char buf[10];
int phonetic_id;
string phonetic_id_string;
string time_str = fgGetString("sim/time/gmt-string");
int hours;
int minutes;
// Only update every so-many loops - FIXME - possibly register this with the event scheduler // Only update every so-many loops - FIXME - possibly register this with the event scheduler
// Ack this doesn't work since the static counter is shared between all instances of FGATIS // Ack this doesn't work since the static counter is shared between all instances of FGATIS
@ -76,25 +116,34 @@ string FGATIS::get_transmission() {
// Start with the transmitted station name. // Start with the transmitted station name.
transmission += name; transmission += name;
//cout << "In atis.cxx, time_str = " << time_str << '\n';
// Add the recording identifier // Add the recording identifier
// TODO - this is hardwired for now - ultimately we need to start with a random one and then increment it with each recording // For now we will assume we only transmit every hour
transmission += " Charlie"; hours = atoi((time_str.substr(1,2)).c_str()); //Warning - this is fragile if the
//time string format changes
//cout << "In atis.cxx, hours = " << hours << endl;
phonetic_id = current_atislist->GetCallSign(ident, hours, 0);
phonetic_id_string = GetPhoneticIdent(phonetic_id);
transmission += " ";
transmission += phonetic_id_string;
// Output the recording time. - we'll just output the last whole hour for now. // Output the recording time. - we'll just output the last whole hour for now.
string time_str = fgGetString("sim/time/gmt-string");
// FIXME - this only gets GMT time but that appears to be all the clock outputs for now // FIXME - this only gets GMT time but that appears to be all the clock outputs for now
//cout << "in atis.cxx, time = " << time_str << endl; //cout << "in atis.cxx, time = " << time_str << endl;
transmission = transmission + " Weather " + time_str.substr(0,3) + "00 hours Zulu"; transmission = transmission + " Weather " + time_str.substr(0,3) + "00 hours Zulu";
// Get the temperature // Get the temperature
// Hardwire the temperature for now - is the local weather database running yet? temperature = fgGetDouble("/environment/weather/temperature-K");
transmission += " Temperature 25 degrees Celcius"; sprintf(buf, "%i", int(temperature - 273.15));
transmission += " Temperature ";
transmission += buf;
transmission += " degrees Celcius";
// Get the pressure / altimeter // Get the pressure / altimeter
// Get the visibility // Get the visibility
visibility = fgGetDouble("/environment/visibility-m"); visibility = fgGetDouble("/environment/visibility-m");
sprintf(buf, "%d", int(visibility/1600)); sprintf(buf, "%i", int(visibility/1600));
transmission += " Visibility "; transmission += " Visibility ";
transmission += buf; transmission += buf;
transmission += " miles"; transmission += " miles";
@ -128,7 +177,7 @@ string FGATIS::get_transmission() {
transmission += " Winds light and variable"; transmission += " Winds light and variable";
} else { } else {
//add a description of the wind to the transmission //add a description of the wind to the transmission
char buf2[48]; char buf2[72];
sprintf(buf2, "%s %i %s %i %s", " Winds ", int(speed), " knots from ", int(hdg), " degrees"); sprintf(buf2, "%s %i %s %i %s", " Winds ", int(speed), " knots from ", int(hdg), " degrees");
transmission += buf2; transmission += buf2;
} }
@ -143,7 +192,8 @@ string FGATIS::get_transmission() {
// Anything else? // Anything else?
// TODO - unhardwire the identifier // TODO - unhardwire the identifier
transmission += " Advise controller on initial contact you have Charlie"; transmission += " Advise controller on initial contact you have ";
transmission += phonetic_id_string;
//} //}

View file

@ -26,6 +26,7 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx> #include <simgear/misc/sgstream.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_random.h>
#include "atislist.hxx" #include "atislist.hxx"
@ -147,3 +148,53 @@ bool FGATISList::query( double lon, double lat, double elev, double freq,
return false; return false;
} }
int FGATISList::GetCallSign( string apt_id, int hours, int mins )
{
atis_transmission_type tran;
if(atislog.find(apt_id) == atislog.end()) {
// This station has not transmitted yet - return a random identifier
// and add the transmission to the log
tran.hours = hours;
tran.mins = mins;
sg_srandom_time();
tran.callsign = int(sg_random() * 25) + 1; // This *should* give a random int between 1 and 26
//atislog[apt_id].push_back(tran);
atislog[apt_id] = tran;
} else {
// This station has transmitted - calculate the appropriate identifier
// and add the transmission to the log if it has changed
tran = atislog[apt_id];
// This next bit assumes that no-one comes back to the same ATIS station
// after running FlightGear for more than 24 hours !!
if((tran.hours == hours) && (tran.mins == mins)) {
return(tran.callsign);
} else {
if(tran.hours == hours) {
// The minutes must have changed
tran.mins = mins;
tran.callsign++;
} else {
if(hours < tran.hours) {
hours += 24;
}
tran.callsign += (hours - tran.hours);
if(mins != 0) {
// Assume transmissions were made on every hour
tran.callsign++;
}
tran.hours = hours;
tran.mins = mins;
}
// Wrap if we've exceeded Zulu
if(tran.callsign > 26) {
tran.callsign -= 26;
}
// And write the new transmission to the log
atislog[apt_id] = tran;
}
}
return(tran.callsign);
}

View file

@ -28,11 +28,13 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <string>
#include "atis.hxx" #include "atis.hxx"
SG_USING_STD(map); SG_USING_STD(map);
SG_USING_STD(vector); SG_USING_STD(vector);
SG_USING_STD(string);
class FGATISList { class FGATISList {
@ -49,6 +51,21 @@ class FGATISList {
atis_map_type atislist; atis_map_type atislist;
// Add structure and map for storing a log of atis transmissions
// made in this session of FlightGear. This allows the callsign
// to be allocated correctly wrt time.
typedef struct {
int hours;
int mins;
int callsign;
} atis_transmission_type;
typedef map < string, atis_transmission_type > atis_log_type;
typedef atis_log_type::iterator atis_log_iterator;
typedef atis_log_type::const_iterator atis_log_const_iterator;
atis_log_type atislog;
public: public:
FGATISList(); FGATISList();
@ -60,6 +77,9 @@ public:
// query the database for the specified frequency, lon and lat are // query the database for the specified frequency, lon and lat are
// in degrees, elev is in meters // in degrees, elev is in meters
bool query( double lon, double lat, double elev, double freq, FGATIS *a ); bool query( double lon, double lat, double elev, double freq, FGATIS *a );
// Return the callsign for a transmission given transmission time and airpord id
int GetCallSign( string apt_id, int hours, int mins );
}; };

View file

@ -429,14 +429,14 @@ FGRadioStack::update()
// TODO - only get the transmission and register every now and then // TODO - only get the transmission and register every now and then
if(dcl_i == 0) { if(dcl_i == 0) {
transmission = atis.get_transmission(); transmission = atis.get_transmission();
//ChangeRepeatingMessage(transmission); current_atcdisplay->ChangeRepeatingMessage(transmission);
} }
if(!repeating_message_registered) { if(!repeating_message_registered) {
current_atcdisplay->RegisterRepeatingMessage( transmission ); current_atcdisplay->RegisterRepeatingMessage(transmission);
repeating_message_registered = true; repeating_message_registered = true;
} }
dcl_i++; dcl_i++;
if(dcl_i == 3000) { if(dcl_i == 2000) {
dcl_i = 0; dcl_i = 0;
} }
} else { } else {

View file

@ -270,12 +270,12 @@ void guiMotionFunc ( int x, int y )
if (mouse_mode == MOUSE_POINTER) { if (mouse_mode == MOUSE_POINTER) {
// TURN MENU ON IF MOUSE AT TOP // TURN MENU ON IF MOUSE AT TOP
if( y < 2 ) { if( y == 0 ) {
if( !gui_menu_on ) if( !gui_menu_on )
guiToggleMenu(); guiToggleMenu();
} }
// TURN MENU OFF IF MOUSE AT BOTTOM // TURN MENU OFF IF MOUSE AT BOTTOM
else if( y > wh-2 ) { else if( y > wh-1 ) {
if( gui_menu_on ) if( gui_menu_on )
guiToggleMenu(); guiToggleMenu();
} }

View file

@ -1,4 +1,4 @@
/* src/Include/config.h.in. Generated automatically from configure.in by autoheader 2.13. */ /* src/Include/config.h.in. Generated automatically from configure.in by autoheader. */
/* Define to empty if the keyword does not work. */ /* Define to empty if the keyword does not work. */
#undef const #undef const