1
0
Fork 0
flightgear/src/Traffic/SchedFlight.cxx

282 lines
8.1 KiB
C++
Raw Normal View History

/******************************************************************************
* SchedFlight.cxx
* Written by Durk Talsma, started May 5, 2004.
*
* 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
2006-02-21 01:16:04 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
**************************************************************************/
/* This a prototype version of a top-level flight plan manager for Flightgear.
* It parses the fgtraffic.txt file and determine for a specific time/date,
* where each aircraft listed in this file is at the current time.
*
* I'm currently assuming the following simplifications:
* 1) The earth is a perfect sphere
* 2) Each aircraft flies a perfect great circle route.
* 3) Each aircraft flies at a constant speed (with infinite accelerations and
* decelerations)
* 4) Each aircraft leaves at exactly the departure time.
* 5) Each aircraft arrives at exactly the specified arrival time.
*
* TODO:
* - Check the code for known portability issues
* - Find an alternative for the depricated Point3D class
*
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <plib/sg.h>
#include <simgear/compiler.h>
#include <simgear/math/polar3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/props/props.hxx>
#include <simgear/route/waypoint.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/xml/easyxml.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <AIModel/AIManager.hxx>
#include <Airports/simple.hxx>
#include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
#include <Main/globals.hxx>
#include "SchedFlight.hxx"
/******************************************************************************
* FGScheduledFlight stuff
*****************************************************************************/
FGScheduledFlight::FGScheduledFlight()
{
}
FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
{
callsign = other.callsign;
fltRules = other.fltRules;
departurePort = other.departurePort;
depId = other.depId;
arrId = other.arrId;
departureTime = other.departureTime;
cruiseAltitude = other.cruiseAltitude;
arrivalPort = other.arrivalPort;
arrivalTime = other.arrivalTime;
repeatPeriod = other.repeatPeriod;
initialized = other.initialized;
}
FGScheduledFlight::FGScheduledFlight(const string& cs,
const string& fr,
const string& depPrt,
const string& arrPrt,
int cruiseAlt,
const string& deptime,
const string& arrtime,
const string& rep)
{
callsign = cs;
fltRules = fr;
//departurePort.setId(depPrt);
//arrivalPort.setId(arrPrt);
depId = depPrt;
arrId = arrPrt;
//cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
//departureTime = processTimeString(deptime);
//arrivalTime = processTimeString(arrtime);
cruiseAltitude = cruiseAlt;
// Process the repeat period string
if (rep.find("WEEK",0) != string::npos)
{
repeatPeriod = 7*24*60*60; // in seconds
}
else if (rep.find("Hr", 0) != string::npos)
{
repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
}
else
{
cerr << "Unknown repeat period" << endl;
exit(1);
}
// What we still need to do is preprocess the departure and
// arrival times.
departureTime = processTimeString(deptime);
arrivalTime = processTimeString(arrtime);
if (departureTime > arrivalTime)
{
departureTime -= repeatPeriod;
}
initialized = false;
}
FGScheduledFlight:: ~FGScheduledFlight()
{
}
time_t FGScheduledFlight::processTimeString(const string& theTime)
{
int weekday;
int timeOffsetInDays;
int targetHour;
int targetMinute;
int targetSecond;
tm targetTimeDate;
SGTime* currTimeDate = globals->get_time_params();
string timeCopy = theTime;
// okay first split theTime string into
// weekday, hour, minute, second;
// Check if a week day is specified
if (timeCopy.find("/",0) != string::npos)
{
weekday = atoi(timeCopy.substr(0,1).c_str());
timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
timeCopy = timeCopy.substr(2,timeCopy.length());
}
else
{
timeOffsetInDays = 0;
}
targetHour = atoi(timeCopy.substr(0,2).c_str());
targetMinute = atoi(timeCopy.substr(3,5).c_str());
targetSecond = atoi(timeCopy.substr(6,8).c_str());
targetTimeDate.tm_year = currTimeDate->getGmt()->tm_year;
targetTimeDate.tm_mon = currTimeDate->getGmt()->tm_mon;
targetTimeDate.tm_mday = currTimeDate->getGmt()->tm_mday;
targetTimeDate.tm_hour = targetHour;
targetTimeDate.tm_min = targetMinute;
targetTimeDate.tm_sec = targetSecond;
time_t processedTime = sgTimeGetGMT(&targetTimeDate);
processedTime += timeOffsetInDays*24*60*60;
if (processedTime < currTimeDate->get_cur_time())
{
processedTime += repeatPeriod;
}
//tm *temp = currTimeDate->getGmt();
//char buffer[512];
//sgTimeFormatTime(&targetTimeDate, buffer);
//cout << "Scheduled Time " << buffer << endl;
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
return processedTime;
}
void FGScheduledFlight::update()
{
departureTime += repeatPeriod;
arrivalTime += repeatPeriod;
}
void FGScheduledFlight::adjustTime(time_t now)
{
//cerr << "1: Adjusting schedule please wait: " << now
// << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
// Make sure that the arrival time is in between
// the current time and the next repeat period.
while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
{
if (arrivalTime < now)
{
departureTime += repeatPeriod;
arrivalTime += repeatPeriod;
}
else if (arrivalTime > now+repeatPeriod)
{
departureTime -= repeatPeriod;
arrivalTime -= repeatPeriod;
}
// cerr << "2: Adjusting schedule please wait: " << now
// << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
}
}
FGAirport *FGScheduledFlight::getDepartureAirport()
{
if (!(initialized))
{
initializeAirports();
}
if (initialized)
return departurePort;
else
return 0;
}
FGAirport * FGScheduledFlight::getArrivalAirport ()
{
if (!(initialized))
{
initializeAirports();
}
if (initialized)
return arrivalPort;
else
return 0;
}
// Upon the first time of requesting airport information
// for this scheduled flight, these data need to be
// looked up in the main FlightGear database.
// Missing or bogus Airport codes are currently ignored,
// but we should improve that. The best idea is probably to cancel
// this flight entirely by removing it from the schedule, if one
// of the airports cannot be found.
bool FGScheduledFlight::initializeAirports()
{
//cerr << "Initializing using : " << depId << " " << arrId << endl;
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
departurePort = globals->get_airports()->search(depId);
if(departurePort == NULL)
{
cerr << "Could not find " << depId << endl;
return false;
}
David Luff: Attached is a patch to the airport data storage that I would like committed after review if acceptable. Currently the storage of airports mapped by ID is by locally created objects - about 12 Meg or so created on the stack if I am not mistaken. I've changed this to creating the airports on the heap, and storing pointers to them - see FGAirportList.add(...) in src/Airports/simple.cxx. I believe that this is probably better practice, and it's certainly cured some strange problems I was seeing when accessing the airport data with some gps unit code. Changes resulting from this have cascaded through a few files which access the data - 11 files are modified in all. Melchior and Durk - you might want to test this and shout if there are problems since the metar and traffic code are probably the biggest users of the airport data. I've also added a fuzzy search function that returns the next matching airport code in ASCII sequence in order to support gps units that have autocompletion of partially entered codes. More generally, the simple airport class seems to have grown a lot with the fairly recent addition of the parking, runway preference and schedule time code. It is no longer just an encapsulation of the global airport data file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!). My personal opinion is that we should look to just store the basic data in apt.dat for all global airports in a simple airport class, plus globally needed data (metar available?), and then have the traffic, AI and ATC subsystems create more advanced airports for themselves as needed in the area of interest. Once a significant number of airports worldwide have ground networks and parking defined, it will be impractical and unnecessary to store them all in memory. That's just a thought for the future though.
2005-09-20 20:26:57 +00:00
arrivalPort = globals->get_airports()->search(arrId);
if(arrivalPort == NULL)
{
cerr << "Could not find " << arrId << endl;
return false;
}
//cerr << "Found : " << departurePort->getId() << endl;
//cerr << "Found : " << arrivalPort->getId() << endl;
initialized = true;
return true;
}