a4fde6c4d8
recover instead - it was apparently planned to run the updated loop only every 1000th frame, but the counter isn't reset, so it runs every frame - use SG_LOG instead of cerr - don't add redundant slashes in SGPath::append()
289 lines
8.5 KiB
C++
289 lines
8.5 KiB
C++
/******************************************************************************
|
|
* 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
|
|
* 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
|
|
{
|
|
repeatPeriod = 365*24*60*60;
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Unknown repeat period in flight plan "
|
|
"of flight '" << cs << "': " << rep );
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
// TODO: verify status of each token.
|
|
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;
|
|
departurePort = globals->get_airports()->search(depId);
|
|
if(departurePort == NULL)
|
|
{
|
|
SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find departure airport : " << depId);
|
|
return false;
|
|
}
|
|
arrivalPort = globals->get_airports()->search(arrId);
|
|
if(arrivalPort == NULL)
|
|
{
|
|
SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airport : " << arrId);
|
|
return false;
|
|
}
|
|
|
|
//cerr << "Found : " << departurePort->getId() << endl;
|
|
//cerr << "Found : " << arrivalPort->getId() << endl;
|
|
initialized = true;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b)
|
|
{
|
|
return (*a) < (*b);
|
|
};
|