1
0
Fork 0

Add airport dynamics manager

- decouple dynamic airport data from the static (nav-db) data.
This commit is contained in:
James Turner 2015-12-05 00:25:29 +00:00
parent fc887b106b
commit 2af076e6cb
18 changed files with 242 additions and 65 deletions

View file

@ -27,6 +27,7 @@
#include <iostream>
#include <Airports/dynamics.hxx>
#include <Airports/airportdynamicsmanager.hxx>
#include <Airports/airport.hxx>
#include <Scenery/scenery.hxx>
#include "atc_mgr.hxx"
@ -102,17 +103,17 @@ void FGATCManager::init() {
//time_t deptime = 0; // just make sure how flightplan processing is affected by this...
FGAirport *apt = FGAirport::findByIdent(airport);
if (apt && onGround) {// && !runway.empty()) {
FGAirportDynamics* dcs = apt->getDynamics();
FGAirportDynamicsRef dcs(flightgear::AirportDynamicsManager::find(airport));
if (dcs && onGround) {// && !runway.empty()) {
ParkingAssignment pk(dcs->getParkingByName(parking));
// No valid parking location, so either at the runway or at a random location.
if (pk.isValid()) {
dcs->setParkingAvailable(pk.parking(), false);
fp = new FGAIFlightPlan;
controller = apt->getDynamics()->getStartupController();
int stationFreq = apt->getDynamics()->getGroundFrequency(1);
controller = dcs->getStartupController();
int stationFreq = dcs->getGroundFrequency(1);
if (stationFreq > 0)
{
//cerr << "Setting radio frequency to : " << stationFreq << endl;
@ -128,7 +129,7 @@ void FGATCManager::init() {
fp->setGate(pk);
if (!(fp->createPushBack(&ai_ac,
false,
apt,
dcs->parent(),
aircraftRadius,
fltType,
aircraftType,
@ -140,8 +141,8 @@ void FGATCManager::init() {
} else if (!runway.empty()) {
controller = apt->getDynamics()->getTowerController();
int stationFreq = apt->getDynamics()->getTowerFrequency(2);
controller = dcs->getTowerController();
int stationFreq = dcs->getTowerFrequency(2);
if (stationFreq > 0)
{
//cerr << "Setting radio frequency to in airfrequency: " << stationFreq << endl;
@ -151,7 +152,7 @@ void FGATCManager::init() {
leg = 3;
string fltType = "ga";
fp->setRunway(runway);
fp->createTakeOff(&ai_ac, false, apt, 0, fltType);
fp->createTakeOff(&ai_ac, false, dcs->parent(), 0, fltType);
ai_ac.setTakeOffStatus(2);
} else {
// We're on the ground somewhere. Handle this case later.
@ -189,6 +190,15 @@ void FGATCManager::addController(FGATCController *controller) {
activeStations.push_back(controller);
}
void FGATCManager::removeController(FGATCController *controller)
{
AtcVecIterator it;
it = std::find(activeStations.begin(), activeStations.end(), controller);
if (it != activeStations.end()) {
activeStations.erase(it);
}
}
void FGATCManager::update ( double time ) {
//cerr << "ATC update code is running at time: " << time << endl;
// Test code: let my virtual co-pilot handle ATC:

View file

@ -59,6 +59,7 @@ public:
~FGATCManager();
void init();
void addController(FGATCController *controller);
void removeController(FGATCController* controller);
void update(double time);
};

View file

@ -490,7 +490,8 @@ FGATCController::FGATCController()
FGATCController::~FGATCController()
{
//cerr << "running FGATController destructor" << endl;
FGATCManager *mgr = (FGATCManager*) globals->get_subsystem("ATC");
mgr->removeController(this);
}
string FGATCController::getGateName(FGAIAircraft * ref)

View file

@ -15,6 +15,7 @@ set(SOURCES
sidstar.cxx
airport.cxx
xmlloader.cxx
airportdynamicsmanager.cxx
)
set(HEADERS
@ -33,6 +34,7 @@ set(HEADERS
sidstar.hxx
airport.hxx
xmlloader.hxx
airportdynamicsmanager.hxx
)
flightgear_component(Airports "${SOURCES}" "${HEADERS}")

View file

@ -46,8 +46,9 @@
#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
#include <Airports/pavement.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/xmlloader.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/airportdynamicsmanager.hxx>
#include <Navaids/procedure.hxx>
#include <Navaids/waypoint.hxx>
#include <ATC/CommStation.hxx>
@ -74,7 +75,6 @@ FGAirport::FGAirport( PositionedID aGuid,
FGPositioned(aGuid, aType, id, location),
_name(name),
_has_metar(has_metar),
_dynamics(0),
mTowerDataLoaded(false),
mHasTower(false),
mRunwaysLoaded(false),
@ -90,8 +90,6 @@ FGAirport::FGAirport( PositionedID aGuid,
FGAirport::~FGAirport()
{
SG_LOG(SG_NAVAID, SG_INFO, "deleting airport:" << ident());
delete _dynamics;
}
bool FGAirport::isAirport() const
@ -118,23 +116,6 @@ bool FGAirport::isAirportType(FGPositioned* pos)
return (pos->type() >= AIRPORT) && (pos->type() <= SEAPORT);
}
FGAirportDynamics * FGAirport::getDynamics()
{
if (_dynamics) {
return _dynamics;
}
_dynamics = new FGAirportDynamics(this);
XMLLoader::load(_dynamics);
_dynamics->init();
FGRunwayPreference rwyPrefs(this);
XMLLoader::load(&rwyPrefs);
_dynamics->setRwyUse(rwyPrefs);
return _dynamics;
}
//------------------------------------------------------------------------------
unsigned int FGAirport::numRunways() const
{
@ -983,6 +964,11 @@ void FGAirport::sortBySize(FGPositionedList& airportList)
}
}
FGAirportDynamicsRef FGAirport::getDynamics() const
{
return flightgear::AirportDynamicsManager::find(const_cast<FGAirport*>(this));
}
// get airport elevation
double fgGetAirportElev( const std::string& id )
{

View file

@ -89,7 +89,7 @@ class FGAirport : public FGPositioned
FGRunwayRef getActiveRunwayForUsage() const;
FGAirportDynamics *getDynamics();
FGAirportDynamicsRef getDynamics() const;
unsigned int numRunways() const;
unsigned int numHelipads() const;
@ -323,7 +323,6 @@ private:
std::string _name;
bool _has_metar;
FGAirportDynamics *_dynamics;
void loadRunways() const;
void loadHelipads() const;

View file

@ -0,0 +1,107 @@
// airportdynamicsmanager.cxx - manager for dynamic (changeable)
// part of airport state
//
// Written by James Turner, started December 2015
//
// Copyright (C) 2015 James Turner <zakalawe@mac.com>
//
// 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.
#include "airportdynamicsmanager.hxx"
#include <simgear/structure/exception.hxx>
#include "airport.hxx"
#include "xmlloader.hxx"
#include "dynamics.hxx"
#include "runwayprefs.hxx"
#include <Main/globals.hxx>
namespace flightgear
{
AirportDynamicsManager::AirportDynamicsManager()
{
}
AirportDynamicsManager::~AirportDynamicsManager()
{
}
void AirportDynamicsManager::init()
{
}
void AirportDynamicsManager::shutdown()
{
m_dynamics.clear();
}
void AirportDynamicsManager::update(double dt)
{
SG_UNUSED(dt);
}
void AirportDynamicsManager::reinit()
{
shutdown();
init();
}
FGAirportDynamicsRef AirportDynamicsManager::dynamicsForICAO(const std::string &icao)
{
ICAODynamicsDict::iterator it = m_dynamics.find(icao);
if (it != m_dynamics.end()) {
return it->second;
}
FGAirportRef apt(FGAirport::findByIdent(icao));
if (!apt)
throw sg_exception("dynamicsForICAO: Invalid ICAO:" + icao);
FGAirportDynamicsRef d(new FGAirportDynamics(apt));
XMLLoader::load(d.ptr());
d->init();
FGRunwayPreference rwyPrefs(apt);
XMLLoader::load(&rwyPrefs);
d->setRwyUse(rwyPrefs);
m_dynamics[icao] = d;
return d;
}
FGAirportDynamicsRef AirportDynamicsManager::find(const std::string &icao)
{
AirportDynamicsManager* instance = static_cast<AirportDynamicsManager*>(globals->get_subsystem("airport-dynamics"));
if (!instance)
return FGAirportDynamicsRef();
return instance->dynamicsForICAO(icao);
}
FGAirportDynamicsRef AirportDynamicsManager::find(const FGAirportRef& apt)
{
return find(apt->ident());
}
} // of namespace flightgear

View file

@ -0,0 +1,58 @@
// airportdynamicsmanager.hxx - manager for dynamic (changeable)
// part of airport state
//
// Written by James Turner, started December 2015
//
// Copyright (C) 2015 James Turner <zakalawe@mac.com>
//
// 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 AIRPORTDYNAMICSMANAGER_H
#define AIRPORTDYNAMICSMANAGER_H
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <map>
#include "airports_fwd.hxx"
namespace flightgear
{
class AirportDynamicsManager : public SGSubsystem
{
public:
AirportDynamicsManager();
virtual ~AirportDynamicsManager();
virtual void init();
virtual void shutdown();
virtual void update (double dt);
virtual void reinit();
static FGAirportDynamicsRef find(const std::string& icao);
static FGAirportDynamicsRef find(const FGAirportRef& apt);
FGAirportDynamicsRef dynamicsForICAO(const std::string& icao);
private:
typedef std::map<std::string, FGAirportDynamicsRef> ICAODynamicsDict;
ICAODynamicsDict m_dynamics;
};
} // of namespace
#endif // AIRPORTDYNAMICSMANAGER_H

View file

@ -79,6 +79,7 @@ typedef SGSharedPtr<FGHelipad> FGHelipadRef;
typedef SGSharedPtr<FGTaxiway> FGTaxiwayRef;
typedef SGSharedPtr<FGPavement> FGPavementRef;
typedef SGSharedPtr<FGParking> FGParkingRef;
typedef SGSharedPtr<FGAirportDynamics> FGAirportDynamicsRef;
typedef std::vector<FGRunwayRef> FGRunwayList;
typedef std::map<std::string, FGRunwayRef> FGRunwayMap;

View file

@ -53,19 +53,19 @@ using std::random_shuffle;
class ParkingAssignment::ParkingAssignmentPrivate
{
public:
ParkingAssignmentPrivate(FGParking* pk, FGAirport* apt) :
ParkingAssignmentPrivate(FGParking* pk, FGAirportDynamics* dyn) :
refCount(0),
parking(pk),
airport(apt)
dynamics(dyn)
{
assert(pk);
assert(apt);
assert(dyn);
retain(); // initial count of 1
}
~ParkingAssignmentPrivate()
{
airport->getDynamics()->releaseParking(parking);
dynamics->releaseParking(parking);
}
void release()
@ -82,7 +82,7 @@ public:
unsigned int refCount;
FGParkingRef parking;
FGAirportRef airport;
FGAirportDynamicsRef dynamics;
};
ParkingAssignment::ParkingAssignment() :
@ -97,11 +97,11 @@ ParkingAssignment::~ParkingAssignment()
}
}
ParkingAssignment::ParkingAssignment(FGParking* pk, FGAirport* apt) :
ParkingAssignment::ParkingAssignment(FGParking* pk, FGAirportDynamics* dyn) :
_sharedData(NULL)
{
if (pk) {
_sharedData = new ParkingAssignmentPrivate(pk, apt);
_sharedData = new ParkingAssignmentPrivate(pk, dyn);
}
}
@ -164,13 +164,14 @@ FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
// Destructor
FGAirportDynamics::~FGAirportDynamics()
{
SG_LOG(SG_AI, SG_INFO, "destroyed dynamics for:" << _ap->ident());
}
// Initialization required after XMLRead
void FGAirportDynamics::init()
{
groundNetwork.init(_ap);
groundNetwork.init(this);
groundNetwork.setTowerController(&towerController);
}
@ -213,18 +214,18 @@ ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const st
// most exact seach - airline codes must be present and match
FGParking* result = innerGetAvailableParking(radius, flType, airline, true);
if (result) {
return ParkingAssignment(result, _ap);
return ParkingAssignment(result, this);
}
// more tolerant - gates with empty airline codes are permitted
result = innerGetAvailableParking(radius, flType, airline, false);
if (result) {
return ParkingAssignment(result, _ap);
return ParkingAssignment(result, this);
}
// fallback - ignore the airline code entirely
result = innerGetAvailableParking(radius, flType, string(), false);
return result ? ParkingAssignment(result, _ap) : ParkingAssignment();
return result ? ParkingAssignment(result, this) : ParkingAssignment();
}
ParkingAssignment FGAirportDynamics::getParkingByName(const std::string& name) const
@ -233,7 +234,7 @@ ParkingAssignment FGAirportDynamics::getParkingByName(const std::string& name) c
FGParkingList::const_iterator it;
for (it = parkings.begin(); it != parkings.end(); ++it) {
if ((*it)->name() == name) {
return ParkingAssignment(*it, _ap);
return ParkingAssignment(*it, const_cast<FGAirportDynamics*>(this));
}
}

View file

@ -24,6 +24,8 @@
#include <set>
#include <simgear/structure/SGReferenced.hxx>
#include <ATC/trafficcontrol.hxx>
#include "airports_fwd.hxx"
#include "parking.hxx"
@ -37,7 +39,7 @@ public:
~ParkingAssignment();
// create a parking assignment (and mark it as unavailable)
ParkingAssignment(FGParking* pk, FGAirport* apt);
ParkingAssignment(FGParking* pk, FGAirportDynamics* apt);
ParkingAssignment(const ParkingAssignment& aOther);
void operator=(const ParkingAssignment& aOther);
@ -53,7 +55,8 @@ private:
ParkingAssignmentPrivate* _sharedData;
};
class FGAirportDynamics {
class FGAirportDynamics : public SGReferenced
{
private:
FGAirport* _ap;
@ -140,7 +143,6 @@ public:
bool isParkingAvailable(FGParking* parking) const;
FGParkingRef getParking(FGParking* i) const;
void releaseParking(FGParking* id);
FGParkingList getParkings(bool onlyAvailable, const std::string& type) const;

View file

@ -175,6 +175,7 @@ bool compare_trafficrecords(FGTrafficRecord a, FGTrafficRecord b)
}
FGGroundNetwork::FGGroundNetwork() :
dynamics(NULL),
parent(NULL)
{
hasNetwork = false;
@ -199,7 +200,7 @@ FGGroundNetwork::~FGGroundNetwork()
// owning references to ground-net nodes will also drop
}
void FGGroundNetwork::init(FGAirport* pr)
void FGGroundNetwork::init(FGAirportDynamics* dyn)
{
if (networkInitialized) {
SG_LOG(SG_GENERAL, SG_WARN, "duplicate ground-network init");
@ -207,7 +208,8 @@ void FGGroundNetwork::init(FGAirport* pr)
return;
}
parent = pr;
dynamics = dyn;
parent = dyn->parent();
assert(parent);
hasNetwork = true;
nextSave = 0;
@ -407,8 +409,8 @@ void FGGroundNetwork::announcePosition(int id,
FGAIAircraft * aircraft)
{
assert(parent);
init(parent);
assert(dynamics);
init(dynamics);
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id alread has an entry
@ -495,11 +497,11 @@ bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, Traffic
FGATCDialogNew::instance()->removeEntry(1);
} else {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), &(*parent->getDynamics()), msgId, msgDir, false);
transmit(&(*i), dynamics, msgId, msgDir, false);
return false;
}
}
transmit(&(*i), &(*parent->getDynamics()), msgId, msgDir, true);
transmit(&(*i), dynamics, msgId, msgDir, true);
i->updateState();
lastTransmission = now;
available = false;
@ -846,11 +848,11 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
if ((origStatus != currStatus) && available) {
//cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
if (currStatus == true) { // No has a hold short instruction
transmit(&(*current), &(*parent->getDynamics()), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
transmit(&(*current), dynamics, MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
//cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
current->setState(1);
} else {
transmit(&(*current), &(*parent->getDynamics()), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
transmit(&(*current), dynamics, MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
//cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
current->setState(2);
}
@ -1305,8 +1307,8 @@ void FGGroundNetwork::update(double dt)
//sort(activeTraffic.begin(), activeTraffic.end(), compare_trafficrecords);
// Handle traffic that is under ground control first; this way we'll prevent clutter at the gate areas.
// Don't allow an aircraft to pushback when a taxiing aircraft is currently using part of the intended route.
for (TrafficVectorIterator i = parent->getDynamics()->getStartupController()->getActiveTraffic().begin();
i != parent->getDynamics()->getStartupController()->getActiveTraffic().end(); i++) {
for (TrafficVectorIterator i = dynamics->getStartupController()->getActiveTraffic().begin();
i != dynamics->getStartupController()->getActiveTraffic().end(); i++) {
i->allowPushBack();
i->setPriority(priority++);
// in meters per second;

View file

@ -177,6 +177,7 @@ class FGGroundNetwork : public FGATCController
private:
friend class FGAirportDynamicsXMLLoader;
FGAirportDynamics* dynamics; // weak back-pointer to our owner
bool hasNetwork;
bool networkInitialized;
time_t nextSave;
@ -218,7 +219,7 @@ public:
void setVersion (int v) { version = v;};
int getVersion() { return version; };
void init(FGAirport* pr);
void init(FGAirportDynamics* pr);
bool exists() {
return hasNetwork;
};

View file

@ -49,9 +49,9 @@ void XMLLoader::load(FGAirportDynamics* d)
return;
}
SG_LOG(SG_NAVAID, SG_INFO, "reading groundnet data from " << path);
SGTimeStamp t;
t.stamp();
try {
FGAirportDynamicsXMLLoader visitor(d);
readXML(path.str(), visitor);

View file

@ -80,6 +80,7 @@
#include <Airports/runways.hxx>
#include <Airports/airport.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/airportdynamicsmanager.hxx>
#include <AIModel/AIManager.hxx>
@ -712,6 +713,11 @@ void fgCreateSubsystems(bool duringReset) {
globals->add_subsystem("properties", new FGProperties);
////////////////////////////////////////////////////////////////////
// Add the FlightGear property utilities.
////////////////////////////////////////////////////////////////////
globals->add_subsystem("airport-dynamics", new flightgear::AirportDynamicsManager);
////////////////////////////////////////////////////////////////////
// Add the performance monitoring system.
////////////////////////////////////////////////////////////////////

View file

@ -196,7 +196,7 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find airport " << id );
return false;
}
FGAirportDynamics* dcs = apt->getDynamics();
FGAirportDynamicsRef dcs = apt->getDynamics();
if (!dcs) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Airport " << id << "does not appear to have parking information available");

View file

@ -1351,7 +1351,7 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args)
onlyAvailable = (args[1].num != 0.0);
}
FGAirportDynamics* dynamics = apt->getDynamics();
FGAirportDynamicsRef dynamics = apt->getDynamics();
FGParkingList parkings = dynamics->getParkings(onlyAvailable, type);
FGParkingList::const_iterator it;
for (it = parkings.begin(); it != parkings.end(); ++it) {

View file

@ -208,7 +208,7 @@ f_airport_parking(FGAirport& apt, nasal::CallContext ctx)
{
std::string type = ctx.getArg<std::string>(0);
bool only_available = ctx.getArg<bool>(1);
FGAirportDynamics* dynamics = apt.getDynamics();
FGAirportDynamicsRef dynamics = apt.getDynamics();
return dynamics->getParkings(only_available, type);
}