Checkpoint - ground-net skips the cache
This commit is contained in:
parent
d56fbfd415
commit
fc887b106b
27 changed files with 378 additions and 704 deletions
|
@ -187,7 +187,7 @@ private:
|
|||
time_t arrivalTime; // For AI/ATC purposes.
|
||||
int leg;
|
||||
ParkingAssignment gate;
|
||||
PositionedID lastNodeVisited;
|
||||
FGTaxiNodeRef lastNodeVisited;
|
||||
std::string activeRunway;
|
||||
std::string name;
|
||||
bool isValid;
|
||||
|
|
|
@ -247,11 +247,11 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
return true;
|
||||
}
|
||||
|
||||
PositionedID runwayId = 0;
|
||||
FGTaxiNodeRef runwayNode;
|
||||
if (gn->getVersion() > 0) {
|
||||
runwayId = gn->findNearestNodeOnRunway(runwayTakeoff);
|
||||
FGTaxiNodeRef runwayNode = gn->findNearestNodeOnRunway(runwayTakeoff);
|
||||
} else {
|
||||
runwayId = gn->findNearestNode(runwayTakeoff);
|
||||
FGTaxiNodeRef runwayNode = gn->findNearestNode(runwayTakeoff);
|
||||
}
|
||||
|
||||
// A negative gateId indicates an overflow parking, use a
|
||||
|
@ -262,17 +262,15 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
// taxiRoute = new FGTaxiRoute;
|
||||
|
||||
// Determine which node to start from.
|
||||
PositionedID node = 0;
|
||||
FGTaxiNodeRef node;
|
||||
// Find out which node to start from
|
||||
FGParking *park = gate.parking();
|
||||
if (park) {
|
||||
node = park->getPushBackPoint();
|
||||
if (node == -1) {
|
||||
node = park->guid();
|
||||
} else if (node == 0) {
|
||||
if (node == 0) {
|
||||
// Handle case where parking doesn't have a node
|
||||
if (firstFlight) {
|
||||
node = park->guid();
|
||||
node = park;
|
||||
} else {
|
||||
node = lastNodeVisited;
|
||||
}
|
||||
|
@ -280,8 +278,8 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
}
|
||||
|
||||
FGTaxiRoute taxiRoute;
|
||||
if ( runwayId != 0 )
|
||||
taxiRoute = gn->findShortestRoute(node, runwayId);
|
||||
if ( runwayNode )
|
||||
taxiRoute = gn->findShortestRoute(node, runwayNode);
|
||||
|
||||
if (taxiRoute.empty()) {
|
||||
createDefaultTakeoffTaxi(ac, apt, rwy);
|
||||
|
@ -289,6 +287,8 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
}
|
||||
|
||||
taxiRoute.first();
|
||||
FGTaxiNodeRef skipNode;
|
||||
|
||||
//bool isPushBackPoint = false;
|
||||
if (firstFlight) {
|
||||
// If this is called during initialization, randomly
|
||||
|
@ -298,13 +298,13 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
// but make sure we always keep two active waypoints
|
||||
// to prevent a segmentation fault
|
||||
for (int i = 0; i < nrWaypointsToSkip - 3; i++) {
|
||||
taxiRoute.next(&node, &route);
|
||||
taxiRoute.next(skipNode, &route);
|
||||
}
|
||||
|
||||
gate.release(); // free up our gate as required
|
||||
} else {
|
||||
if (taxiRoute.size() > 1) {
|
||||
taxiRoute.next(&node, &route); // chop off the first waypoint, because that is already the last of the pushback route
|
||||
taxiRoute.next(skipNode, &route); // chop off the first waypoint, because that is already the last of the pushback route
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,13 +315,11 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
|
|||
// Note that the line wpt->setRouteIndex was commented out by revision [afcdbd] 2012-01-01,
|
||||
// which breaks the rendering functions.
|
||||
// These can probably be generated on the fly however.
|
||||
while (taxiRoute.next(&node, &route)) {
|
||||
while (taxiRoute.next(node, &route)) {
|
||||
char buffer[10];
|
||||
snprintf(buffer, 10, "%lld", (long long int) node);
|
||||
FGTaxiNode *tn =
|
||||
apt->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
snprintf(buffer, 10, "%d", node->getIndex());
|
||||
FGAIWaypoint *wpt =
|
||||
createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
|
||||
createOnGround(ac, buffer, node->geod(), apt->getElevation(),
|
||||
ac->getPerformance()->vTaxi());
|
||||
wpt->setRouteIndex(route);
|
||||
//cerr << "Nodes left " << taxiRoute->nodesLeft() << " ";
|
||||
|
@ -388,11 +386,11 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
|
|||
return true;
|
||||
}
|
||||
|
||||
PositionedID runwayId = 0;
|
||||
FGTaxiNodeRef runwayNode;
|
||||
if (gn->getVersion() == 1) {
|
||||
runwayId = gn->findNearestNodeOnRunway(lastWptPos);
|
||||
runwayNode = gn->findNearestNodeOnRunway(lastWptPos);
|
||||
} else {
|
||||
runwayId = gn->findNearestNode(lastWptPos);
|
||||
runwayNode = gn->findNearestNode(lastWptPos);
|
||||
}
|
||||
//cerr << "Using network node " << runwayId << endl;
|
||||
// A negative gateId indicates an overflow parking, use a
|
||||
|
@ -400,26 +398,25 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
|
|||
// Starting from gate 0 doesn't work, so don't try it
|
||||
FGTaxiRoute taxiRoute;
|
||||
if (gate.isValid())
|
||||
taxiRoute = gn->findShortestRoute(runwayId, gate.parking()->guid());
|
||||
taxiRoute = gn->findShortestRoute(runwayNode, gate.parking());
|
||||
|
||||
if (taxiRoute.empty()) {
|
||||
createDefaultLandingTaxi(ac, apt);
|
||||
return true;
|
||||
}
|
||||
|
||||
PositionedID node;
|
||||
FGTaxiNodeRef node;
|
||||
taxiRoute.first();
|
||||
int size = taxiRoute.size();
|
||||
// Omit the last two waypoints, as
|
||||
// those are created by createParking()
|
||||
// int route;
|
||||
for (int i = 0; i < size - 2; i++) {
|
||||
taxiRoute.next(&node, &route);
|
||||
taxiRoute.next(node, &route);
|
||||
char buffer[10];
|
||||
snprintf(buffer, 10, "%lld", (long long int) node);
|
||||
FGTaxiNode *tn = gn->findNode(node);
|
||||
snprintf(buffer, 10, "%d", node->getIndex());
|
||||
FGAIWaypoint *wpt =
|
||||
createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
|
||||
createOnGround(ac, buffer, node->geod(), apt->getElevation(),
|
||||
ac->getPerformance()->vTaxi());
|
||||
|
||||
wpt->setRouteIndex(route);
|
||||
|
@ -638,10 +635,9 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
|||
}
|
||||
|
||||
double dAlt = 0; // = alt - (apt->getElevation() + 2000);
|
||||
FGTaxiNode * tn = 0;
|
||||
FGTaxiNodeRef tn;
|
||||
if (apt->getDynamics()->getGroundNetwork()) {
|
||||
int node = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint);
|
||||
tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
tn = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint);
|
||||
}
|
||||
|
||||
if (tn) {
|
||||
|
@ -967,14 +963,13 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
|
|||
}
|
||||
|
||||
coord = rwy->pointOnCenterline(mindist);
|
||||
int nodeId = 0;
|
||||
FGTaxiNodeRef tn;
|
||||
if (gn->getVersion() > 0) {
|
||||
nodeId = gn->findNearestNodeOnRunway(coord, rwy);
|
||||
tn = gn->findNearestNodeOnRunway(coord, rwy);
|
||||
} else {
|
||||
nodeId = gn->findNearestNode(coord);
|
||||
tn = gn->findNearestNode(coord);
|
||||
}
|
||||
|
||||
FGTaxiNode* tn = gn->findNode(nodeId);
|
||||
if (tn) {
|
||||
wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi);
|
||||
pushBackWaypoint(wpt);
|
||||
|
|
|
@ -87,7 +87,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
FGGroundNetwork* groundNet = dep->getDynamics()->getGroundNetwork();
|
||||
FGParking *parking = gate.parking();
|
||||
if (parking && parking->getPushBackPoint() > 0) {
|
||||
FGTaxiRoute route = groundNet->findShortestRoute(parking->guid(), parking->getPushBackPoint(), false);
|
||||
FGTaxiRoute route = groundNet->findShortestRoute(parking, parking->getPushBackPoint(), false);
|
||||
|
||||
int size = route.size();
|
||||
if (size < 2) {
|
||||
|
@ -96,15 +96,14 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
}
|
||||
|
||||
route.first();
|
||||
PositionedID node;
|
||||
FGTaxiNodeRef node;
|
||||
int rte;
|
||||
|
||||
while (route.next(&node, &rte))
|
||||
while (route.next(node, &rte))
|
||||
{
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%lld", (long long int) node);
|
||||
FGTaxiNode *tn = groundNet->findNode(node);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->geod(), dep->getElevation(), vTaxiBackward);
|
||||
snprintf (buffer, 10, "%d", node->getIndex());
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), node->geod(), dep->getElevation(), vTaxiBackward);
|
||||
|
||||
/*
|
||||
if (previous) {
|
||||
|
@ -128,14 +127,14 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
ac->setTaxiClearanceRequest(false);
|
||||
double az2 = 0.0;
|
||||
|
||||
FGTaxiSegment* pushForwardSegment = dep->getDynamics()->getGroundNetwork()->findSegment(parking->guid(), 0);
|
||||
FGTaxiSegment* pushForwardSegment = dep->getDynamics()->getGroundNetwork()->findSegment(parking, 0);
|
||||
// there aren't any routes for this parking.
|
||||
if (!pushForwardSegment) {
|
||||
SG_LOG(SG_AI, SG_ALERT, "Gate " << parking->ident() << "doesn't seem to have routes associated with it.");
|
||||
return false;
|
||||
}
|
||||
|
||||
lastNodeVisited = pushForwardSegment->getEnd()->getIndex();
|
||||
lastNodeVisited = pushForwardSegment->getEnd();
|
||||
double distance = pushForwardSegment->getLength();
|
||||
|
||||
double parkingHeading = parking->getHeading();
|
||||
|
|
|
@ -109,7 +109,7 @@ void FGATCManager::init() {
|
|||
|
||||
// No valid parking location, so either at the runway or at a random location.
|
||||
if (pk.isValid()) {
|
||||
dcs->setParkingAvailable(pk.parking()->guid(), false);
|
||||
dcs->setParkingAvailable(pk.parking(), false);
|
||||
fp = new FGAIFlightPlan;
|
||||
controller = apt->getDynamics()->getStartupController();
|
||||
int stationFreq = apt->getDynamics()->getGroundFrequency(1);
|
||||
|
|
|
@ -90,6 +90,7 @@ FGAirport::FGAirport( PositionedID aGuid,
|
|||
|
||||
FGAirport::~FGAirport()
|
||||
{
|
||||
SG_LOG(SG_NAVAID, SG_INFO, "deleting airport:" << ident());
|
||||
delete _dynamics;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
@ -62,21 +63,21 @@ void FGAirportDynamicsXMLLoader::startXML () {
|
|||
|
||||
void FGAirportDynamicsXMLLoader::endXML ()
|
||||
{
|
||||
std::map<PositionedID, int>::iterator it;
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
ParkingPushbackIndex::const_iterator it;
|
||||
|
||||
for (it = _parkingPushbacks.begin(); it != _parkingPushbacks.end(); ++it) {
|
||||
std::map<int, PositionedID>::iterator j = _idMap.find(it->second);
|
||||
if (j == _idMap.end()) {
|
||||
NodeIndexMap::const_iterator j = _indexMap.find(it->second);
|
||||
if (j == _indexMap.end()) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "bad groundnet, no node for index:" << it->first);
|
||||
continue;
|
||||
}
|
||||
|
||||
it->first->setPushBackPoint(j->second);
|
||||
|
||||
cache->setParkingPushBackRoute(it->first, j->second);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(PositionedID id, _unreferencedNodes) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "unreferenced groundnet node:" << id);
|
||||
BOOST_FOREACH(FGTaxiNodeRef node, _unreferencedNodes) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "unreferenced groundnet node:" << node->ident());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -124,14 +125,16 @@ void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts)
|
|||
|
||||
SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
|
||||
|
||||
PositionedID guid = flightgear::NavDataCache::instance()->insertParking(gateName + gateNumber, pos,
|
||||
_dynamics->parent()->guid(),
|
||||
heading, radius, type, airlineCodes);
|
||||
FGParkingRef parking(new FGParking(index,
|
||||
pos, heading, radius,
|
||||
gateName + gateNumber,
|
||||
type, airlineCodes));
|
||||
if (pushBackRoute > 0) {
|
||||
_parkingPushbacks[guid] = pushBackRoute;
|
||||
_parkingPushbacks[parking] = pushBackRoute;
|
||||
}
|
||||
|
||||
_idMap[index] = guid;
|
||||
_indexMap[index] = parking;
|
||||
_dynamics->getGroundNetwork()->addParking(parking);
|
||||
}
|
||||
|
||||
void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts)
|
||||
|
@ -168,15 +171,14 @@ void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts)
|
|||
}
|
||||
}
|
||||
|
||||
if (_idMap.find(index) != _idMap.end()) {
|
||||
if (_indexMap.find(index) != _indexMap.end()) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "duplicate ground-net index:" << index);
|
||||
}
|
||||
|
||||
SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
|
||||
PositionedID guid = flightgear::NavDataCache::instance()->insertTaxiNode(pos,
|
||||
_dynamics->parent()->guid(), holdPointType, onRunway);
|
||||
_idMap[index] = guid;
|
||||
_unreferencedNodes.insert(guid);
|
||||
FGTaxiNodeRef node(new FGTaxiNode(index, pos, onRunway, holdPointType));
|
||||
_indexMap[index] = node;
|
||||
_unreferencedNodes.insert(node);
|
||||
}
|
||||
|
||||
void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts)
|
||||
|
@ -201,16 +203,28 @@ void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts)
|
|||
return;
|
||||
}
|
||||
|
||||
_arcSet.insert(e);
|
||||
flightgear::NavDataCache::instance()->insertGroundnetEdge(_dynamics->parent()->guid(),
|
||||
_idMap[begin], _idMap[end]);
|
||||
|
||||
_unreferencedNodes.erase(_idMap[begin]);
|
||||
_unreferencedNodes.erase(_idMap[end]);
|
||||
|
||||
if (isPushBackRoute) {
|
||||
flightgear::NavDataCache::instance()->markGroundnetAsPushback(_idMap[end]);
|
||||
NodeIndexMap::const_iterator it;
|
||||
FGTaxiNodeRef fromNode, toNode;
|
||||
it = _indexMap.find(begin);
|
||||
if (it == _indexMap.end()) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", begin index unknown");
|
||||
return;
|
||||
} else {
|
||||
_unreferencedNodes.erase(it->second);
|
||||
fromNode = it->second;
|
||||
}
|
||||
|
||||
it = _indexMap.find(end);
|
||||
if (it == _indexMap.end()) {
|
||||
SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", end index unknown");
|
||||
return;
|
||||
} else {
|
||||
_unreferencedNodes.erase(it->second);
|
||||
toNode = it->second;
|
||||
}
|
||||
|
||||
_arcSet.insert(e);
|
||||
_dynamics->getGroundNetwork()->addSegment(fromNode, toNode);
|
||||
}
|
||||
|
||||
void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include "dynamics.hxx"
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Airports/parking.hxx>
|
||||
|
||||
class FGAirportDynamicsXMLLoader : public XMLVisitor {
|
||||
public:
|
||||
|
@ -43,19 +43,21 @@ private:
|
|||
FGAirportDynamics* _dynamics;
|
||||
std::string value;
|
||||
|
||||
// map from local (groundnet.xml) to global (nav-cache) IDs for nodes
|
||||
std::map<int, PositionedID> _idMap;
|
||||
// map from local (groundnet.xml) ids to parking instances
|
||||
typedef std::map<int, FGTaxiNodeRef> NodeIndexMap;
|
||||
NodeIndexMap _indexMap;
|
||||
|
||||
// data integrity - watch for unreferenced nodes and duplicated edges
|
||||
typedef std::pair<int, int> IntPair;
|
||||
std::set<IntPair> _arcSet;
|
||||
|
||||
std::set<PositionedID> _unreferencedNodes;
|
||||
std::set<FGTaxiNodeRef> _unreferencedNodes;
|
||||
|
||||
// map from allocated parking position to its local push-back node
|
||||
// used to defer binding the push-back node until we've processed
|
||||
// all nodes
|
||||
std::map<PositionedID, int> _parkingPushbacks;
|
||||
typedef std::map<FGParkingRef, int> ParkingPushbackIndex;
|
||||
ParkingPushbackIndex _parkingPushbacks;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
~ParkingAssignmentPrivate()
|
||||
{
|
||||
airport->getDynamics()->releaseParking(parking->guid());
|
||||
airport->getDynamics()->releaseParking(parking);
|
||||
}
|
||||
|
||||
void release()
|
||||
|
@ -81,8 +81,8 @@ public:
|
|||
}
|
||||
|
||||
unsigned int refCount;
|
||||
SGSharedPtr<FGParking> parking;
|
||||
SGSharedPtr<FGAirport> airport;
|
||||
FGParkingRef parking;
|
||||
FGAirportRef airport;
|
||||
};
|
||||
|
||||
ParkingAssignment::ParkingAssignment() :
|
||||
|
@ -179,28 +179,29 @@ FGParking* FGAirportDynamics::innerGetAvailableParking(double radius, const stri
|
|||
const string & airline,
|
||||
bool skipEmptyAirlineCode)
|
||||
{
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
BOOST_FOREACH(PositionedID pk, cache->findAirportParking(_ap->guid(), flType, radius)) {
|
||||
if (!isParkingAvailable(pk)) {
|
||||
continue;
|
||||
const FGParkingList& parkings(groundNetwork.allParkings());
|
||||
FGParkingList::const_iterator it;
|
||||
for (it = parkings.begin(); it != parkings.end(); ++it) {
|
||||
FGParkingRef parking = *it;
|
||||
if (!isParkingAvailable(parking)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skipEmptyAirlineCode && parking->getCodes().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!airline.empty() && !parking->getCodes().empty()) {
|
||||
if (parking->getCodes().find(airline, 0) == string::npos) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
setParkingAvailable(parking, false);
|
||||
return parking;
|
||||
}
|
||||
|
||||
FGParking* parking = getParking(pk);
|
||||
if (skipEmptyAirlineCode && parking->getCodes().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!airline.empty() && !parking->getCodes().empty()) {
|
||||
if (parking->getCodes().find(airline, 0) == string::npos) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
setParkingAvailable(pk, false);
|
||||
return parking;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const string & flType,
|
||||
|
@ -226,46 +227,34 @@ ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const st
|
|||
return result ? ParkingAssignment(result, _ap) : ParkingAssignment();
|
||||
}
|
||||
|
||||
FGParkingRef FGAirportDynamics::getParking(PositionedID id) const
|
||||
{
|
||||
return FGPositioned::loadById<FGParking>(id);
|
||||
}
|
||||
|
||||
string FGAirportDynamics::getParkingName(PositionedID id) const
|
||||
{
|
||||
FGParking* p = getParking(id);
|
||||
if (p) {
|
||||
return p->getName();
|
||||
}
|
||||
|
||||
return string();
|
||||
}
|
||||
|
||||
ParkingAssignment FGAirportDynamics::getParkingByName(const std::string& name) const
|
||||
{
|
||||
PositionedID guid = flightgear::NavDataCache::instance()->airportItemWithIdent(parent()->guid(), FGPositioned::PARKING, name);
|
||||
if (guid == 0) {
|
||||
return ParkingAssignment();
|
||||
}
|
||||
|
||||
return ParkingAssignment(getParking(guid), _ap);
|
||||
const FGParkingList& parkings(groundNetwork.allParkings());
|
||||
FGParkingList::const_iterator it;
|
||||
for (it = parkings.begin(); it != parkings.end(); ++it) {
|
||||
if ((*it)->name() == name) {
|
||||
return ParkingAssignment(*it, _ap);
|
||||
}
|
||||
}
|
||||
|
||||
return ParkingAssignment();
|
||||
}
|
||||
|
||||
void FGAirportDynamics::setParkingAvailable(PositionedID guid, bool available)
|
||||
void FGAirportDynamics::setParkingAvailable(FGParking* park, bool available)
|
||||
{
|
||||
if (available) {
|
||||
releaseParking(guid);
|
||||
releaseParking(park);
|
||||
} else {
|
||||
occupiedParkings.insert(guid);
|
||||
occupiedParkings.insert(park);
|
||||
}
|
||||
}
|
||||
|
||||
bool FGAirportDynamics::isParkingAvailable(PositionedID parking) const
|
||||
bool FGAirportDynamics::isParkingAvailable(FGParking* parking) const
|
||||
{
|
||||
return (occupiedParkings.find(parking) == occupiedParkings.end());
|
||||
}
|
||||
|
||||
void FGAirportDynamics::releaseParking(PositionedID id)
|
||||
void FGAirportDynamics::releaseParking(FGParking* id)
|
||||
{
|
||||
ParkingSet::iterator it = occupiedParkings.find(id);
|
||||
if (it == occupiedParkings.end()) {
|
||||
|
@ -275,6 +264,41 @@ void FGAirportDynamics::releaseParking(PositionedID id)
|
|||
occupiedParkings.erase(it);
|
||||
}
|
||||
|
||||
class GetParkingsPredicate
|
||||
{
|
||||
bool mustBeAvailable;
|
||||
std::string type;
|
||||
const FGAirportDynamics* dynamics;
|
||||
public:
|
||||
GetParkingsPredicate(bool b, const std::string& ty, const FGAirportDynamics* dyn) :
|
||||
mustBeAvailable(b),
|
||||
type(ty),
|
||||
dynamics(dyn)
|
||||
{}
|
||||
|
||||
bool operator()(const FGParkingRef& park) const
|
||||
{
|
||||
if (!type.empty() && (park->getType() != type))
|
||||
return true;
|
||||
|
||||
if (mustBeAvailable && !dynamics->isParkingAvailable(park)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
FGParkingList FGAirportDynamics::getParkings(bool onlyAvailable, const std::string &type) const
|
||||
{
|
||||
FGParkingList result(groundNetwork.allParkings());
|
||||
|
||||
GetParkingsPredicate pred(onlyAvailable, type, this);
|
||||
FGParkingList::iterator it = std::remove_if(result.begin(), result.end(), pred);
|
||||
result.erase(it, result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref)
|
||||
{
|
||||
rwyPrefs = ref;
|
||||
|
|
|
@ -58,10 +58,12 @@ class FGAirportDynamics {
|
|||
private:
|
||||
FGAirport* _ap;
|
||||
|
||||
typedef std::set<PositionedID> ParkingSet;
|
||||
typedef std::set<FGParkingRef> ParkingSet;
|
||||
// if a parking item is in this set, it is occupied
|
||||
ParkingSet occupiedParkings;
|
||||
|
||||
|
||||
|
||||
FGRunwayPreference rwyPrefs;
|
||||
FGStartupController startupController;
|
||||
FGGroundNetwork groundNetwork;
|
||||
|
@ -134,13 +136,14 @@ public:
|
|||
ParkingAssignment getAvailableParking(double radius, const std::string& fltype,
|
||||
const std::string& acType, const std::string& airline);
|
||||
|
||||
void setParkingAvailable(PositionedID guid, bool available);
|
||||
void setParkingAvailable(FGParking* park, bool available);
|
||||
|
||||
bool isParkingAvailable(PositionedID parking) const;
|
||||
bool isParkingAvailable(FGParking* parking) const;
|
||||
|
||||
FGParkingRef getParking(PositionedID i) const;
|
||||
void releaseParking(PositionedID id);
|
||||
std::string getParkingName(PositionedID i) const;
|
||||
FGParkingRef getParking(FGParking* i) const;
|
||||
void releaseParking(FGParking* id);
|
||||
|
||||
FGParkingList getParkings(bool onlyAvailable, const std::string& type) const;
|
||||
|
||||
/**
|
||||
* Find a parking gate index by name. Note names are often not unique
|
||||
|
|
|
@ -14,10 +14,12 @@ using namespace flightgear;
|
|||
* FGTaxiNode
|
||||
*************************************************************************/
|
||||
|
||||
FGTaxiNode::FGTaxiNode(PositionedID aGuid, const SGGeod& pos, bool aOnRunway, int aHoldType) :
|
||||
FGPositioned(aGuid, FGPositioned::PARKING, "", pos),
|
||||
FGTaxiNode::FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType) :
|
||||
FGPositioned(TRANSIENT_ID, FGPositioned::PARKING, "", pos),
|
||||
m_index(index),
|
||||
isOnRunway(aOnRunway),
|
||||
holdType(aHoldType)
|
||||
holdType(aHoldType),
|
||||
m_isPushback(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -45,16 +47,23 @@ double FGTaxiNode::getElevationFt()
|
|||
SGGeod newPos = pos;
|
||||
newPos.setElevationM(elevationEnd);
|
||||
// this will call modifyPosition to update mPosition
|
||||
NavDataCache* cache = NavDataCache::instance();
|
||||
NavDataCache::Transaction txn(cache);
|
||||
cache->updatePosition(guid(), newPos);
|
||||
txn.commit();
|
||||
modifyPosition(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
return pos.getElevationFt();
|
||||
}
|
||||
|
||||
int FGTaxiNode::getIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
void FGTaxiNode::setIsPushback()
|
||||
{
|
||||
m_isPushback = true;
|
||||
}
|
||||
|
||||
double FGTaxiNode::getElevationM()
|
||||
{
|
||||
return getElevationFt() * SG_FEET_TO_METER;
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
class FGTaxiNode : public FGPositioned
|
||||
{
|
||||
protected:
|
||||
const int m_index;
|
||||
|
||||
bool isOnRunway;
|
||||
int holdType;
|
||||
bool m_isPushback;
|
||||
|
||||
public:
|
||||
FGTaxiNode(PositionedID aGuid, const SGGeod& pos, bool aOnRunway, int aHoldType);
|
||||
FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType);
|
||||
virtual ~FGTaxiNode();
|
||||
|
||||
void setElevation(double val);
|
||||
|
@ -36,9 +39,13 @@ public:
|
|||
double getElevationM ();
|
||||
double getElevationFt();
|
||||
|
||||
PositionedID getIndex() const { return guid(); };
|
||||
int getIndex() const;
|
||||
|
||||
int getHoldPointType() const { return holdType; };
|
||||
bool getIsOnRunway() const { return isOnRunway; };
|
||||
bool isPushback() const { return m_isPushback; }
|
||||
|
||||
void setIsPushback();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,7 +65,7 @@ using flightgear::NavDataCache;
|
|||
* FGTaxiSegment
|
||||
**************************************************************************/
|
||||
|
||||
FGTaxiSegment::FGTaxiSegment(PositionedID aStart, PositionedID aEnd) :
|
||||
FGTaxiSegment::FGTaxiSegment(FGTaxiNode* aStart, FGTaxiNode* aEnd) :
|
||||
startNode(aStart),
|
||||
endNode(aEnd),
|
||||
isActive(0),
|
||||
|
@ -84,12 +84,12 @@ SGGeod FGTaxiSegment::getCenter() const
|
|||
|
||||
FGTaxiNodeRef FGTaxiSegment::getEnd() const
|
||||
{
|
||||
return FGPositioned::loadById<FGTaxiNode>(endNode);
|
||||
return const_cast<FGTaxiNode*>(endNode);
|
||||
}
|
||||
|
||||
FGTaxiNodeRef FGTaxiSegment::getStart() const
|
||||
{
|
||||
return FGPositioned::loadById<FGTaxiNode>(startNode);
|
||||
return const_cast<FGTaxiNode*>(startNode);
|
||||
}
|
||||
|
||||
double FGTaxiSegment::getLength() const
|
||||
|
@ -145,7 +145,7 @@ void FGTaxiSegment::unblock(time_t now)
|
|||
/***************************************************************************
|
||||
* FGTaxiRoute
|
||||
**************************************************************************/
|
||||
bool FGTaxiRoute::next(PositionedID *nde, int *rte)
|
||||
bool FGTaxiRoute::next(FGTaxiNodeRef& node, int *rte)
|
||||
{
|
||||
if (nodes.size() != (routes.size()) + 1) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size());
|
||||
|
@ -153,7 +153,7 @@ bool FGTaxiRoute::next(PositionedID *nde, int *rte)
|
|||
}
|
||||
if (currNode == nodes.end())
|
||||
return false;
|
||||
*nde = *(currNode);
|
||||
node = *(currNode);
|
||||
if (currNode != nodes.begin()) {
|
||||
*rte = *(currRoute);
|
||||
currRoute++;
|
||||
|
@ -191,63 +191,19 @@ FGGroundNetwork::FGGroundNetwork() :
|
|||
|
||||
FGGroundNetwork::~FGGroundNetwork()
|
||||
{
|
||||
// JMT 2012-09-8 - disabling the groundnet-caching as part of enabling the
|
||||
// navcache. The problem isn't the NavCache - it's that for the past few years,
|
||||
// we have not being running destructors on FGPositioned classes, and hence,
|
||||
// not running this code.
|
||||
// When I fix FGPositioned lifetimes (unloading-at-runtime support), this
|
||||
// will need to be re-visited so it can run safely during shutdown.
|
||||
#if 0
|
||||
saveElevationCache();
|
||||
#endif
|
||||
|
||||
BOOST_FOREACH(FGTaxiSegment* seg, segments) {
|
||||
delete seg;
|
||||
}
|
||||
}
|
||||
|
||||
void FGGroundNetwork::saveElevationCache()
|
||||
{
|
||||
#if 0
|
||||
bool saveData = false;
|
||||
ofstream cachefile;
|
||||
if (fgGetBool("/sim/ai/groundnet-cache")) {
|
||||
SGPath cacheData(globals->get_fg_home());
|
||||
cacheData.append("ai");
|
||||
string airport = parent->getId();
|
||||
|
||||
if ((airport) != "") {
|
||||
char buffer[128];
|
||||
::snprintf(buffer, 128, "%c/%c/%c/",
|
||||
airport[0], airport[1], airport[2]);
|
||||
cacheData.append(buffer);
|
||||
if (!cacheData.exists()) {
|
||||
cacheData.create_dir(0755);
|
||||
}
|
||||
cacheData.append(airport + "-groundnet-cache.txt");
|
||||
cachefile.open(cacheData.str().c_str());
|
||||
saveData = true;
|
||||
}
|
||||
}
|
||||
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
|
||||
for (IndexTaxiNodeMap::iterator node = nodes.begin();
|
||||
node != nodes.end(); node++) {
|
||||
if (saveData) {
|
||||
cachefile << node->second->getIndex () << " "
|
||||
<< node->second->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " "
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
if (saveData) {
|
||||
cachefile.close();
|
||||
}
|
||||
#endif
|
||||
// owning references to ground-net nodes will also drop
|
||||
}
|
||||
|
||||
void FGGroundNetwork::init(FGAirport* pr)
|
||||
{
|
||||
if (networkInitialized) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "duplicate ground-network init");
|
||||
FGATCController::init();
|
||||
//cerr << "FGground network already initialized" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -257,7 +213,6 @@ void FGGroundNetwork::init(FGAirport* pr)
|
|||
nextSave = 0;
|
||||
int index = 1;
|
||||
|
||||
loadSegments();
|
||||
|
||||
// establish pairing of segments
|
||||
BOOST_FOREACH(FGTaxiSegment* segment, segments) {
|
||||
|
@ -274,87 +229,53 @@ void FGGroundNetwork::init(FGAirport* pr)
|
|||
opp->oppositeDirection = segment;
|
||||
}
|
||||
}
|
||||
|
||||
if (fgGetBool("/sim/ai/groundnet-cache")) {
|
||||
parseCache();
|
||||
}
|
||||
|
||||
networkInitialized = true;
|
||||
}
|
||||
|
||||
void FGGroundNetwork::loadSegments()
|
||||
FGTaxiNodeRef FGGroundNetwork::findNearestNode(const SGGeod & aGeod) const
|
||||
{
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
// iterate over all ground-net nodes in this airport
|
||||
BOOST_FOREACH(PositionedID node, cache->groundNetNodes(parent->guid(), false)) {
|
||||
// find all segments leaving the node
|
||||
BOOST_FOREACH(PositionedID end, cache->groundNetEdgesFrom(node, false)) {
|
||||
segments.push_back(new FGTaxiSegment(node, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
double d = DBL_MAX;
|
||||
SGVec3d cartPos = SGVec3d::fromGeod(aGeod);
|
||||
FGTaxiNodeRef result;
|
||||
|
||||
void FGGroundNetwork::parseCache()
|
||||
{
|
||||
SGPath cacheData(globals->get_fg_home());
|
||||
cacheData.append("ai");
|
||||
string airport = parent->getId();
|
||||
|
||||
if (airport.empty()) {
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
char buffer[128];
|
||||
::snprintf(buffer, 128, "%c/%c/%c/",
|
||||
airport[0], airport[1], airport[2]);
|
||||
cacheData.append(buffer);
|
||||
if (!cacheData.exists()) {
|
||||
cacheData.create_dir(0755);
|
||||
}
|
||||
int index;
|
||||
double elev;
|
||||
cacheData.append(airport + "-groundnet-cache.txt");
|
||||
if (cacheData.exists()) {
|
||||
ifstream data(cacheData.c_str());
|
||||
string revisionStr;
|
||||
data >> revisionStr;
|
||||
if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
|
||||
cacheData.c_str() << " for Airport " << airport);
|
||||
} else {
|
||||
for (IndexTaxiNodeMap::iterator i = nodes.begin();
|
||||
i != nodes.end();
|
||||
i++) {
|
||||
i->second->setElevation(parent->elevation() * SG_FEET_TO_METER);
|
||||
data >> index >> elev;
|
||||
if (data.eof())
|
||||
break;
|
||||
if (index != i->second->getIndex()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Index read from ground network cache at airport " << airport << " does not match index in the network itself");
|
||||
} else {
|
||||
i->second->setElevation(elev);
|
||||
FGTaxiNodeVector::const_iterator it;
|
||||
for (it = m_nodes.begin(); it != m_nodes.end(); ++it) {
|
||||
double localDistanceSqr = distSqr(cartPos, (*it)->cart());
|
||||
if (localDistanceSqr < d) {
|
||||
d = localDistanceSqr;
|
||||
result = *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int FGGroundNetwork::findNearestNode(const SGGeod & aGeod) const
|
||||
FGTaxiNodeRef FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod, FGRunway* aRunway) const
|
||||
{
|
||||
const bool onRunway = false;
|
||||
return NavDataCache::instance()->findGroundNetNode(parent->guid(), aGeod, onRunway);
|
||||
SG_UNUSED(aRunway);
|
||||
|
||||
double d = DBL_MAX;
|
||||
SGVec3d cartPos = SGVec3d::fromGeod(aGeod);
|
||||
FGTaxiNodeRef result = 0;
|
||||
FGTaxiNodeVector::const_iterator it;
|
||||
for (it = m_nodes.begin(); it != m_nodes.end(); ++it) {
|
||||
if (!(*it)->getIsOnRunway())
|
||||
continue;
|
||||
|
||||
double localDistanceSqr = distSqr(cartPos, (*it)->cart());
|
||||
if (localDistanceSqr < d) {
|
||||
d = localDistanceSqr;
|
||||
result = *it;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod, FGRunway* aRunway) const
|
||||
const FGParkingList &FGGroundNetwork::allParkings() const
|
||||
{
|
||||
const bool onRunway = true;
|
||||
return NavDataCache::instance()->findGroundNetNode(parent->guid(), aGeod, onRunway, aRunway);
|
||||
}
|
||||
|
||||
FGTaxiNodeRef FGGroundNetwork::findNode(PositionedID idx) const
|
||||
{
|
||||
return FGPositioned::loadById<FGTaxiNode>(idx);
|
||||
return m_parkings;
|
||||
}
|
||||
|
||||
FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) const
|
||||
|
@ -367,7 +288,7 @@ FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) const
|
|||
}
|
||||
}
|
||||
|
||||
FGTaxiSegment* FGGroundNetwork::findSegment(PositionedID from, PositionedID to) const
|
||||
FGTaxiSegment* FGGroundNetwork::findSegment(const FGTaxiNode* from, const FGTaxiNode* to) const
|
||||
{
|
||||
if (from == 0) {
|
||||
return NULL;
|
||||
|
@ -405,41 +326,22 @@ public:
|
|||
FGTaxiNodeRef previousNode;
|
||||
};
|
||||
|
||||
FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID end,
|
||||
bool fullSearch)
|
||||
FGTaxiRoute FGGroundNetwork::findShortestRoute(FGTaxiNode* start, FGTaxiNode* end, bool fullSearch)
|
||||
{
|
||||
if (!start || !end) {
|
||||
throw sg_exception("Bad arguments to findShortestRoute");
|
||||
}
|
||||
//implements Dijkstra's algorithm to find shortest distance route from start to end
|
||||
//taken from http://en.wikipedia.org/wiki/Dijkstra's_algorithm
|
||||
FGTaxiNodeVector unvisited;
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
FGTaxiNodeVector unvisited(m_nodes);
|
||||
std::map<FGTaxiNode*, ShortestPathData> searchData;
|
||||
|
||||
BOOST_FOREACH(PositionedID n, cache->groundNetNodes(parent->guid(), !fullSearch)) {
|
||||
unvisited.push_back(findNode(n));
|
||||
}
|
||||
|
||||
FGTaxiNode *firstNode = findNode(start);
|
||||
if (!firstNode)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Error in ground network. Failed to find first waypoint: " << start
|
||||
<< " at " << ((parent) ? parent->getId() : "<unknown>"));
|
||||
return FGTaxiRoute();
|
||||
}
|
||||
searchData[firstNode].score = 0.0;
|
||||
|
||||
FGTaxiNode *lastNode = findNode(end);
|
||||
if (!lastNode)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Error in ground network. Failed to find last waypoint: " << end
|
||||
<< " at " << ((parent) ? parent->getId() : "<unknown>"));
|
||||
return FGTaxiRoute();
|
||||
}
|
||||
searchData[start].score = 0.0;
|
||||
|
||||
while (!unvisited.empty()) {
|
||||
FGTaxiNode *best = unvisited.front();
|
||||
BOOST_FOREACH(FGTaxiNode* i, unvisited) {
|
||||
// find lowest scored unvisited
|
||||
FGTaxiNodeRef best = unvisited.front();
|
||||
BOOST_FOREACH(FGTaxiNodeRef i, unvisited) {
|
||||
if (searchData[i].score < searchData[best].score) {
|
||||
best = i;
|
||||
}
|
||||
|
@ -450,22 +352,21 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID
|
|||
remove(unvisited.begin(), unvisited.end(), best);
|
||||
unvisited.erase(newend, unvisited.end());
|
||||
|
||||
if (best == lastNode) { // found route or best not connected
|
||||
if (best == end) { // found route or best not connected
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(PositionedID targetId, cache->groundNetEdgesFrom(best->guid(), !fullSearch)) {
|
||||
FGTaxiNodeRef tgt = FGPositioned::loadById<FGTaxiNode>(targetId);
|
||||
double edgeLength = dist(best->cart(), tgt->cart());
|
||||
double alt = searchData[best].score + edgeLength + edgePenalty(tgt);
|
||||
if (alt < searchData[tgt].score) { // Relax (u,v)
|
||||
searchData[tgt].score = alt;
|
||||
searchData[tgt].previousNode = best;
|
||||
BOOST_FOREACH(FGTaxiNodeRef target, segmentsFrom(best)) {
|
||||
double edgeLength = dist(best->cart(), target->cart());
|
||||
double alt = searchData[best].score + edgeLength + edgePenalty(target);
|
||||
if (alt < searchData[target].score) { // Relax (u,v)
|
||||
searchData[target].score = alt;
|
||||
searchData[target].previousNode = best;
|
||||
}
|
||||
} // of outgoing arcs/segments from current best node iteration
|
||||
} // of unvisited nodes remaining
|
||||
|
||||
if (searchData[lastNode].score == HUGE_VAL) {
|
||||
if (searchData[end].score == HUGE_VAL) {
|
||||
// no valid route found
|
||||
if (fullSearch) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
|
@ -477,13 +378,13 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID
|
|||
}
|
||||
|
||||
// assemble route from backtrace information
|
||||
PositionedIDVec nodes;
|
||||
FGTaxiNodeVector nodes;
|
||||
intVec routes;
|
||||
FGTaxiNode *bt = lastNode;
|
||||
FGTaxiNode *bt = end;
|
||||
|
||||
while (searchData[bt].previousNode != 0) {
|
||||
nodes.push_back(bt->guid());
|
||||
FGTaxiSegment *segment = findSegment(searchData[bt].previousNode->guid(), bt->guid());
|
||||
nodes.push_back(bt);
|
||||
FGTaxiSegment *segment = findSegment(searchData[bt].previousNode, bt);
|
||||
int idx = segment->getIndex();
|
||||
routes.push_back(idx);
|
||||
bt = searchData[bt].previousNode;
|
||||
|
@ -492,7 +393,7 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID
|
|||
nodes.push_back(start);
|
||||
reverse(nodes.begin(), nodes.end());
|
||||
reverse(routes.begin(), routes.end());
|
||||
return FGTaxiRoute(nodes, routes, searchData[lastNode].score, 0);
|
||||
return FGTaxiRoute(nodes, routes, searchData[end].score, 0);
|
||||
}
|
||||
|
||||
/* ATC Related Functions */
|
||||
|
@ -611,11 +512,6 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
|
|||
double heading, double speed, double alt,
|
||||
double dt)
|
||||
{
|
||||
time_t currentTime = time(NULL);
|
||||
if (nextSave < currentTime) {
|
||||
saveElevationCache();
|
||||
nextSave = currentTime + 100 + rand() % 200;
|
||||
}
|
||||
// Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
|
||||
// Transmit air-to-ground "Ready to taxi request:
|
||||
// Transmit ground to air approval / hold
|
||||
|
@ -688,6 +584,20 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
FGTaxiNodeRef FGGroundNetwork::findNodeByIndex(int index) const
|
||||
{
|
||||
FGTaxiNodeVector::const_iterator it;
|
||||
for (it = m_nodes.begin(); it != m_nodes.end(); ++it) {
|
||||
if ((*it)->getIndex() == index) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
return FGTaxiNodeRef();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Scan for a speed adjustment change. Find the nearest aircraft that is in front
|
||||
and adjust speed when we get too close. Only do this when current position and/or
|
||||
|
@ -984,6 +894,46 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
|
|||
//current->setState(0);
|
||||
}
|
||||
|
||||
void FGGroundNetwork::addSegment(const FGTaxiNodeRef &from, const FGTaxiNodeRef &to)
|
||||
{
|
||||
FGTaxiSegment* seg = new FGTaxiSegment(from, to);
|
||||
segments.push_back(seg);
|
||||
|
||||
FGTaxiNodeVector::iterator it = std::find(m_nodes.begin(), m_nodes.end(), from);
|
||||
if (it == m_nodes.end()) {
|
||||
m_nodes.push_back(from);
|
||||
}
|
||||
|
||||
it = std::find(m_nodes.begin(), m_nodes.end(), to);
|
||||
if (it == m_nodes.end()) {
|
||||
m_nodes.push_back(to);
|
||||
}
|
||||
}
|
||||
|
||||
void FGGroundNetwork::addParking(const FGParkingRef &park)
|
||||
{
|
||||
m_parkings.push_back(park);
|
||||
|
||||
|
||||
FGTaxiNodeVector::iterator it = std::find(m_nodes.begin(), m_nodes.end(), park);
|
||||
if (it == m_nodes.end()) {
|
||||
m_nodes.push_back(park);
|
||||
}
|
||||
}
|
||||
|
||||
FGTaxiNodeVector FGGroundNetwork::segmentsFrom(const FGTaxiNodeRef &from) const
|
||||
{
|
||||
FGTaxiNodeVector result;
|
||||
FGTaxiSegmentVector::const_iterator it;
|
||||
for (it = segments.begin(); it != segments.end(); ++it) {
|
||||
if ((*it)->getStart() == from) {
|
||||
result.push_back((*it)->getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether situations occur where the current aircraft is waiting for itself
|
||||
* due to higher order interactions.
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "parking.hxx"
|
||||
#include <ATC/trafficcontrol.hxx>
|
||||
|
||||
class FGAirportDynamicsXMLLoader;
|
||||
|
||||
class Block
|
||||
{
|
||||
private:
|
||||
|
@ -54,18 +56,20 @@ public:
|
|||
class FGTaxiSegment
|
||||
{
|
||||
private:
|
||||
const PositionedID startNode;
|
||||
const PositionedID endNode;
|
||||
// weak (non-owning) pointers deliberately here:
|
||||
// the ground-network owns the nodes
|
||||
const FGTaxiNode* startNode;
|
||||
const FGTaxiNode* endNode;
|
||||
|
||||
bool isActive;
|
||||
BlockList blockTimes;
|
||||
|
||||
int index;
|
||||
FGTaxiSegment *oppositeDirection;
|
||||
FGTaxiSegment *oppositeDirection; // also deliberatley weak
|
||||
|
||||
friend class FGGroundNetwork;
|
||||
public:
|
||||
FGTaxiSegment(PositionedID start, PositionedID end);
|
||||
FGTaxiSegment(FGTaxiNode* start, FGTaxiNode* end);
|
||||
|
||||
void setIndex (int val) {
|
||||
index = val;
|
||||
|
@ -107,10 +111,10 @@ public:
|
|||
class FGTaxiRoute
|
||||
{
|
||||
private:
|
||||
PositionedIDVec nodes;
|
||||
FGTaxiNodeVector nodes;
|
||||
intVec routes;
|
||||
double distance;
|
||||
PositionedIDVec::iterator currNode;
|
||||
FGTaxiNodeVector::iterator currNode;
|
||||
intVec::iterator currRoute;
|
||||
|
||||
public:
|
||||
|
@ -120,7 +124,7 @@ public:
|
|||
currRoute = routes.begin();
|
||||
};
|
||||
|
||||
FGTaxiRoute(const PositionedIDVec& nds, intVec rts, double dist, int dpth) {
|
||||
FGTaxiRoute(const FGTaxiNodeVector& nds, intVec rts, double dist, int dpth) {
|
||||
nodes = nds;
|
||||
routes = rts;
|
||||
distance = dist;
|
||||
|
@ -151,7 +155,7 @@ public:
|
|||
bool empty () {
|
||||
return nodes.empty();
|
||||
};
|
||||
bool next(PositionedID *nde, int *rte);
|
||||
bool next(FGTaxiNodeRef& nde, int *rte);
|
||||
|
||||
void first() {
|
||||
currNode = nodes.begin();
|
||||
|
@ -171,6 +175,8 @@ public:
|
|||
class FGGroundNetwork : public FGATCController
|
||||
{
|
||||
private:
|
||||
friend class FGAirportDynamicsXMLLoader;
|
||||
|
||||
bool hasNetwork;
|
||||
bool networkInitialized;
|
||||
time_t nextSave;
|
||||
|
@ -187,6 +193,10 @@ private:
|
|||
FGTowerController *towerController;
|
||||
FGAirport *parent;
|
||||
|
||||
FGParkingList m_parkings;
|
||||
FGTaxiNodeVector m_nodes;
|
||||
|
||||
FGTaxiNodeRef findNodeByIndex(int index) const;
|
||||
|
||||
//void printRoutingError(string);
|
||||
|
||||
|
@ -196,9 +206,11 @@ private:
|
|||
double heading, double speed, double alt);
|
||||
|
||||
|
||||
void parseCache();
|
||||
|
||||
void loadSegments();
|
||||
void addSegment(const FGTaxiNodeRef& from, const FGTaxiNodeRef& to);
|
||||
void addParking(const FGParkingRef& park);
|
||||
|
||||
FGTaxiNodeVector segmentsFrom(const FGTaxiNodeRef& from) const;
|
||||
|
||||
public:
|
||||
FGGroundNetwork();
|
||||
~FGGroundNetwork();
|
||||
|
@ -214,21 +226,22 @@ public:
|
|||
towerController = twrCtrlr;
|
||||
};
|
||||
|
||||
int findNearestNode(const SGGeod& aGeod) const;
|
||||
int findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL) const;
|
||||
FGTaxiNodeRef findNearestNode(const SGGeod& aGeod) const;
|
||||
FGTaxiNodeRef findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL) const;
|
||||
|
||||
FGTaxiSegment *findSegment(unsigned int idx) const;
|
||||
|
||||
const FGParkingList& allParkings() const;
|
||||
|
||||
FGTaxiNodeRef findNode(PositionedID idx) const;
|
||||
FGTaxiSegment *findSegment(unsigned idx) const;
|
||||
|
||||
/**
|
||||
* Find the taxiway segment joining two (ground-net) nodes. Returns
|
||||
* NULL if no such segment exists.
|
||||
* It is permitted to pass 0 for the 'to' ID, indicating that any
|
||||
* It is permitted to pass HULL for the 'to' indicating that any
|
||||
* segment originating at 'from' is acceptable.
|
||||
*/
|
||||
FGTaxiSegment* findSegment(PositionedID from, PositionedID to) const;
|
||||
FGTaxiSegment *findSegment(const FGTaxiNode* from, const FGTaxiNode* to) const;
|
||||
|
||||
FGTaxiRoute findShortestRoute(PositionedID start, PositionedID end, bool fullSearch=true);
|
||||
FGTaxiRoute findShortestRoute(FGTaxiNode* start, FGTaxiNode* end, bool fullSearch=true);
|
||||
|
||||
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
|
||||
double lat, double lon, double hdg, double spd, double alt,
|
||||
|
@ -245,7 +258,6 @@ public:
|
|||
virtual std::string getName();
|
||||
virtual void update(double dt);
|
||||
|
||||
void saveElevationCache();
|
||||
void addVersion(int v) {version = v; };
|
||||
};
|
||||
|
||||
|
|
|
@ -36,21 +36,26 @@
|
|||
* FGParking
|
||||
********************************************************************************/
|
||||
|
||||
FGParking::FGParking(PositionedID aGuid, const SGGeod& pos,
|
||||
FGParking::FGParking(int index,
|
||||
const SGGeod& pos,
|
||||
double aHeading, double aRadius,
|
||||
const std::string& name, const std::string& aType,
|
||||
const std::string& codes,
|
||||
PositionedID pushBackNode) :
|
||||
FGTaxiNode(aGuid, pos, false, 0),
|
||||
const std::string& name,
|
||||
const std::string& aType,
|
||||
const std::string& codes) :
|
||||
FGTaxiNode(index, pos, false, 0),
|
||||
heading(aHeading),
|
||||
radius(aRadius),
|
||||
parkingName(name),
|
||||
type(aType),
|
||||
airlineCodes(codes),
|
||||
pushBackPoint(pushBackNode)
|
||||
airlineCodes(codes)
|
||||
{
|
||||
}
|
||||
|
||||
FGParking::~FGParking()
|
||||
{
|
||||
}
|
||||
|
||||
void FGParking::setPushBackPoint(const FGTaxiNodeRef &node)
|
||||
{
|
||||
pushBackPoint = node;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <memory> // for std::auto_ptr
|
||||
|
||||
#include "gnnode.hxx"
|
||||
|
||||
#include <Airports/airports_fwd.hxx>
|
||||
|
||||
class FGParking : public FGTaxiNode
|
||||
{
|
||||
|
@ -46,15 +46,15 @@ private:
|
|||
const std::string parkingName;
|
||||
const std::string type;
|
||||
const std::string airlineCodes;
|
||||
const PositionedID pushBackPoint;
|
||||
FGTaxiNodeRef pushBackPoint;
|
||||
|
||||
SG_DISABLE_COPY(FGParking);
|
||||
public:
|
||||
FGParking(PositionedID aGuid, const SGGeod& pos,
|
||||
FGParking(int index,
|
||||
const SGGeod& pos,
|
||||
double heading, double radius,
|
||||
const std::string& name, const std::string& type,
|
||||
const std::string& codes,
|
||||
PositionedID pushBackNode);
|
||||
const std::string& codes);
|
||||
virtual ~FGParking();
|
||||
|
||||
double getHeading () const { return heading; };
|
||||
|
@ -67,7 +67,8 @@ public:
|
|||
// TODO do parkings have different name and ident?
|
||||
virtual const std::string& name() const { return parkingName; }
|
||||
|
||||
int getPushBackPoint () { return pushBackPoint; };
|
||||
void setPushBackPoint(const FGTaxiNodeRef& node);
|
||||
FGTaxiNodeRef getPushBackPoint () { return pushBackPoint; };
|
||||
|
||||
bool operator< (const FGParking &other) const {
|
||||
return radius < other.radius; };
|
||||
|
|
|
@ -49,25 +49,12 @@ void XMLLoader::load(FGAirportDynamics* d)
|
|||
return;
|
||||
}
|
||||
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
||||
//if (!cache->isCachedFileModified(path) || cache->isReadOnly()) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
|
||||
SG_LOG(SG_NAVAID, SG_INFO, "reading groundnet data from " << path);
|
||||
SGTimeStamp t;
|
||||
try {
|
||||
flightgear::NavDataCache::Transaction txn(cache);
|
||||
t.stamp();
|
||||
{
|
||||
// drop all current data
|
||||
cache->dropGroundnetFor(d->parent()->guid());
|
||||
|
||||
FGAirportDynamicsXMLLoader visitor(d);
|
||||
readXML(path.str(), visitor);
|
||||
} // ensure visitor is destroyed so its destructor runs
|
||||
cache->stampCacheFile(path);
|
||||
txn.commit();
|
||||
} catch (sg_exception& e) {
|
||||
SG_LOG(SG_NAVAID, SG_INFO, "parsing groundnet XML failed:" << e.getFormattedMessage());
|
||||
}
|
||||
|
|
|
@ -699,6 +699,7 @@ void LocationWidget::onLocationChanged()
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
m_ui->parkingCombo->clear();
|
||||
FGAirportDynamics* dynamics = apt->getDynamics();
|
||||
PositionedIDVec parkings = NavDataCache::instance()->airportItemsOfType(m_location->guid(),
|
||||
|
@ -717,6 +718,7 @@ void LocationWidget::onLocationChanged()
|
|||
m_ui->airportDiagram->addParking(park);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (m_locationIsLatLon) {
|
||||
m_ui->stack->setCurrentIndex(1);
|
||||
|
|
|
@ -1410,12 +1410,6 @@ do_set_scenery_paths(const SGPropertyNode* arg)
|
|||
globals->append_fg_scenery(root.str());
|
||||
}
|
||||
|
||||
// might need to drop ground-nets from the DB. Also need to drop
|
||||
// them from memory, but this is tricky since FGAirportDynamics holds
|
||||
// an instance directly, and AI code may have pointers to ground-net
|
||||
// nodes. For now we'll leave-in memory versions untouched.
|
||||
flightgear::NavDataCache::instance()->dropGroundnetsIfRequired();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -616,11 +616,6 @@ fgInitNav ()
|
|||
}
|
||||
}
|
||||
|
||||
// depend on when the NavCache was initialised, scenery paths may not
|
||||
// have been setup. This is a safe place to consistently check the value,
|
||||
// and drop the ground-nets if something has changed
|
||||
cache->dropGroundnetsIfRequired();
|
||||
|
||||
FGTACANList *channellist = new FGTACANList;
|
||||
globals->set_channellist( channellist );
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par
|
|||
// The parking will be released after this function returns.
|
||||
// As a temporary measure, I'll try to reserve the parking via the atc_manager, which should work, because it uses the same
|
||||
// mechanism as the AI traffic code.
|
||||
dcs->setParkingAvailable(pka.parking()->guid(), false);
|
||||
dcs->setParkingAvailable(pka.parking(), false);
|
||||
fgApplyStartOffset(pka.parking()->geod(), pka.parking()->getHeading());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef FG_NAVCACHE_SCHEMA_HXX
|
||||
#define FG_NAVCACHE_SCHEMA_HXX
|
||||
|
||||
const int SCHEMA_VERSION = 14;
|
||||
const int SCHEMA_VERSION = 15;
|
||||
|
||||
#define SCHEMA_SQL \
|
||||
"CREATE TABLE properties (key VARCHAR, value VARCHAR);" \
|
||||
|
@ -31,14 +31,7 @@ const int SCHEMA_VERSION = 14;
|
|||
"CREATE INDEX airway_ident ON airway(ident);" \
|
||||
\
|
||||
"CREATE TABLE airway_edge (network INT,airway INT64,a INT64,b INT64);" \
|
||||
"CREATE INDEX airway_edge_from ON airway_edge(a);" \
|
||||
\
|
||||
"CREATE TABLE taxi_node (hold_type INT,on_runway BOOL,pushback BOOL);" \
|
||||
"CREATE TABLE parking (heading FLOAT,radius INT,gate_type VARCHAR," \
|
||||
"airlines VARCHAR,pushback INT64);" \
|
||||
"CREATE TABLE groundnet_edge (airport INT64,a INT64,b INT64);" \
|
||||
"CREATE INDEX groundnet_edge_airport ON groundnet_edge(airport);" \
|
||||
"CREATE INDEX groundnet_edge_from ON groundnet_edge(a);"
|
||||
"CREATE INDEX airway_edge_from ON airway_edge(a);"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -600,47 +600,6 @@ public:
|
|||
isPosInAirway = prepare("SELECT rowid FROM airway_edge WHERE network=?1 AND a=?2");
|
||||
|
||||
airwayEdgesFrom = prepare("SELECT airway, b FROM airway_edge WHERE network=?1 AND a=?2");
|
||||
|
||||
// parking / taxi-node graph
|
||||
insertTaxiNode = prepare("INSERT INTO taxi_node (rowid, hold_type, on_runway, pushback) VALUES(?1, ?2, ?3, 0)");
|
||||
insertParkingPos = prepare("INSERT INTO parking (rowid, heading, radius, gate_type, airlines) "
|
||||
"VALUES (?1, ?2, ?3, ?4, ?5)");
|
||||
setParkingPushBack = prepare("UPDATE parking SET pushback=?2 WHERE rowid=?1");
|
||||
|
||||
loadTaxiNodeStmt = prepare("SELECT hold_type, on_runway FROM taxi_node WHERE rowid=?1");
|
||||
loadParkingPos = prepare("SELECT heading, radius, gate_type, airlines, pushback FROM parking WHERE rowid=?1");
|
||||
taxiEdgesFrom = prepare("SELECT b FROM groundnet_edge WHERE a=?1");
|
||||
pushbackEdgesFrom = prepare("SELECT b FROM groundnet_edge, taxi_node WHERE "
|
||||
"a=?1 AND groundnet_edge.b = taxi_node.rowid AND pushback=1");
|
||||
|
||||
insertTaxiEdge = prepare("INSERT INTO groundnet_edge (airport, a,b) VALUES(?1, ?2, ?3)");
|
||||
|
||||
markTaxiNodeAsPushback = prepare("UPDATE taxi_node SET pushback=1 WHERE rowid=?1");
|
||||
airportTaxiNodes = prepare("SELECT rowid FROM positioned WHERE (type=?2 OR type=?3) AND airport=?1");
|
||||
sqlite3_bind_int(airportTaxiNodes, 2, FGPositioned::PARKING);
|
||||
sqlite3_bind_int(airportTaxiNodes, 3, FGPositioned::TAXI_NODE);
|
||||
|
||||
airportPushbackNodes = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE "\
|
||||
"airport=?1 AND positioned.rowid=taxi_node.rowid AND pushback=1 "
|
||||
"AND (type=?2 OR type=?3)");
|
||||
sqlite3_bind_int(airportPushbackNodes, 2, FGPositioned::PARKING);
|
||||
sqlite3_bind_int(airportPushbackNodes, 3, FGPositioned::TAXI_NODE);
|
||||
|
||||
findNearestTaxiNode = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE "
|
||||
"positioned.rowid = taxi_node.rowid AND airport=?1 "
|
||||
"ORDER BY distanceCartSqr(cart_x, cart_y, cart_z, ?2, ?3, ?4) "
|
||||
"LIMIT 1");
|
||||
|
||||
findNearestRunwayTaxiNode = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE "
|
||||
"positioned.rowid = taxi_node.rowid AND airport=?1 "
|
||||
"AND on_runway=1 "
|
||||
"ORDER BY distanceCartSqr(cart_x, cart_y, cart_z, ?2, ?3, ?4) ");
|
||||
|
||||
findAirportParking = prepare("SELECT positioned.rowid FROM positioned, parking WHERE "
|
||||
"airport=?1 AND type=?4 AND "
|
||||
"radius >= ?2 AND gate_type = ?3 AND "
|
||||
"parking.rowid=positioned.rowid");
|
||||
sqlite3_bind_int(findAirportParking, 4, FGPositioned::PARKING);
|
||||
}
|
||||
|
||||
void writeIntProperty(const string& key, int value)
|
||||
|
@ -758,36 +717,6 @@ public:
|
|||
return n;
|
||||
}
|
||||
|
||||
FGPositioned* loadParking(sqlite3_int64 rowId,
|
||||
const string& name, const SGGeod& pos,
|
||||
PositionedID airport)
|
||||
{
|
||||
sqlite3_bind_int64(loadParkingPos, 1, rowId);
|
||||
execSelect1(loadParkingPos);
|
||||
|
||||
double heading = sqlite3_column_double(loadParkingPos, 0);
|
||||
int radius = sqlite3_column_int(loadParkingPos, 1);
|
||||
string aircraftType((char*) sqlite3_column_text(loadParkingPos, 2));
|
||||
string airlines((char*) sqlite3_column_text(loadParkingPos, 3));
|
||||
PositionedID pushBack = sqlite3_column_int64(loadParkingPos, 4);
|
||||
reset(loadParkingPos);
|
||||
|
||||
return new FGParking(rowId, pos, heading, radius, name, aircraftType, airlines, pushBack);
|
||||
}
|
||||
|
||||
FGPositioned* loadTaxiNode(sqlite3_int64 rowId, const SGGeod& pos,
|
||||
PositionedID airport)
|
||||
{
|
||||
sqlite3_bind_int64(loadTaxiNodeStmt, 1, rowId);
|
||||
execSelect1(loadTaxiNodeStmt);
|
||||
|
||||
int hold_type = sqlite3_column_int(loadTaxiNodeStmt, 0);
|
||||
bool onRunway = sqlite3_column_int(loadTaxiNodeStmt, 1);
|
||||
reset(loadTaxiNodeStmt);
|
||||
|
||||
return new FGTaxiNode(rowId, pos, onRunway, hold_type);
|
||||
}
|
||||
|
||||
PositionedID insertPositioned(FGPositioned::Type ty, const string& ident,
|
||||
const string& name, const SGGeod& pos, PositionedID apt,
|
||||
bool spatialIndex)
|
||||
|
@ -949,12 +878,6 @@ public:
|
|||
sqlite3_stmt_ptr findAirway, insertAirwayEdge, isPosInAirway, airwayEdgesFrom,
|
||||
insertAirway;
|
||||
|
||||
// groundnet (parking, taxi node graph)
|
||||
sqlite3_stmt_ptr loadTaxiNodeStmt, loadParkingPos, insertTaxiNode, insertParkingPos;
|
||||
sqlite3_stmt_ptr taxiEdgesFrom, pushbackEdgesFrom, insertTaxiEdge, markTaxiNodeAsPushback,
|
||||
airportTaxiNodes, airportPushbackNodes, findNearestTaxiNode, findAirportParking,
|
||||
setParkingPushBack, findNearestRunwayTaxiNode;
|
||||
|
||||
// since there's many permutations of ident/name queries, we create
|
||||
// them programtically, but cache the exact query by its raw SQL once
|
||||
// used.
|
||||
|
@ -1043,12 +966,6 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid,
|
|||
case FGPositioned::FREQ_UNICOM:
|
||||
return loadComm(rowid, ty, ident, name, pos, aptId);
|
||||
|
||||
case FGPositioned::TAXI_NODE:
|
||||
return loadTaxiNode(rowid, pos, aptId);
|
||||
|
||||
case FGPositioned::PARKING:
|
||||
return loadParking(rowid, ident, pos, aptId);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1200,19 +1117,6 @@ bool NavDataCache::isRebuildRequired()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NavDataCache::dropGroundnetsIfRequired()
|
||||
{
|
||||
string sceneryPaths = simgear::strutils::join(globals->get_fg_scenery(), ";");
|
||||
if (readStringProperty("scenery_paths") != sceneryPaths) {
|
||||
SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: scenery paths changed, dropping ground nets");
|
||||
dropAllGroundnets();
|
||||
writeStringProperty("scenery_paths", sceneryPaths);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NavDataCache::RebuildPhase NavDataCache::rebuild()
|
||||
{
|
||||
if (!d->rebuilder.get()) {
|
||||
|
@ -2081,162 +1985,6 @@ PositionedID NavDataCache::findNavaidForRunway(PositionedID runway, FGPositioned
|
|||
d->reset(d->findNavaidForRunway);
|
||||
return result;
|
||||
}
|
||||
|
||||
PositionedID
|
||||
NavDataCache::insertParking(const std::string& name, const SGGeod& aPos,
|
||||
PositionedID aAirport,
|
||||
double aHeading, int aRadius, const std::string& aAircraftType,
|
||||
const std::string& aAirlines)
|
||||
{
|
||||
sqlite3_int64 rowId = d->insertPositioned(FGPositioned::PARKING, name, "", aPos, aAirport, false);
|
||||
|
||||
// we need to insert a row into the taxi_node table, otherwise we can't maintain
|
||||
// the appropriate pushback flag.
|
||||
sqlite3_bind_int64(d->insertTaxiNode, 1, rowId);
|
||||
sqlite3_bind_int(d->insertTaxiNode, 2, 0);
|
||||
sqlite3_bind_int(d->insertTaxiNode, 3, 0);
|
||||
d->execInsert(d->insertTaxiNode);
|
||||
|
||||
sqlite3_bind_int64(d->insertParkingPos, 1, rowId);
|
||||
sqlite3_bind_double(d->insertParkingPos, 2, aHeading);
|
||||
sqlite3_bind_int(d->insertParkingPos, 3, aRadius);
|
||||
sqlite_bind_stdstring(d->insertParkingPos, 4, aAircraftType);
|
||||
sqlite_bind_stdstring(d->insertParkingPos, 5, aAirlines);
|
||||
return d->execInsert(d->insertParkingPos);
|
||||
}
|
||||
|
||||
void NavDataCache::setParkingPushBackRoute(PositionedID parking, PositionedID pushBackNode)
|
||||
{
|
||||
sqlite3_bind_int64(d->setParkingPushBack, 1, parking);
|
||||
sqlite3_bind_int64(d->setParkingPushBack, 2, pushBackNode);
|
||||
d->execUpdate(d->setParkingPushBack);
|
||||
}
|
||||
|
||||
PositionedID
|
||||
NavDataCache::insertTaxiNode(const SGGeod& aPos, PositionedID aAirport, int aHoldType, bool aOnRunway)
|
||||
{
|
||||
sqlite3_int64 rowId = d->insertPositioned(FGPositioned::TAXI_NODE, string(), string(), aPos, aAirport, false);
|
||||
sqlite3_bind_int64(d->insertTaxiNode, 1, rowId);
|
||||
sqlite3_bind_int(d->insertTaxiNode, 2, aHoldType);
|
||||
sqlite3_bind_int(d->insertTaxiNode, 3, aOnRunway);
|
||||
return d->execInsert(d->insertTaxiNode);
|
||||
}
|
||||
|
||||
void NavDataCache::insertGroundnetEdge(PositionedID aAirport, PositionedID from, PositionedID to)
|
||||
{
|
||||
sqlite3_bind_int64(d->insertTaxiEdge, 1, aAirport);
|
||||
sqlite3_bind_int64(d->insertTaxiEdge, 2, from);
|
||||
sqlite3_bind_int64(d->insertTaxiEdge, 3, to);
|
||||
d->execInsert(d->insertTaxiEdge);
|
||||
}
|
||||
|
||||
PositionedIDVec NavDataCache::groundNetNodes(PositionedID aAirport, bool onlyPushback)
|
||||
{
|
||||
sqlite3_stmt_ptr q = onlyPushback ? d->airportPushbackNodes : d->airportTaxiNodes;
|
||||
sqlite3_bind_int64(q, 1, aAirport);
|
||||
return d->selectIds(q);
|
||||
}
|
||||
|
||||
void NavDataCache::markGroundnetAsPushback(PositionedID nodeId)
|
||||
{
|
||||
sqlite3_bind_int64(d->markTaxiNodeAsPushback, 1, nodeId);
|
||||
d->execUpdate(d->markTaxiNodeAsPushback);
|
||||
}
|
||||
|
||||
static double headingDifferenceDeg(double crs1, double crs2)
|
||||
{
|
||||
double diff = crs2 - crs1;
|
||||
SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
|
||||
return diff;
|
||||
}
|
||||
|
||||
PositionedID NavDataCache::findGroundNetNode(PositionedID airport, const SGGeod& aPos,
|
||||
bool onRunway, FGRunway* aRunway)
|
||||
{
|
||||
sqlite3_stmt_ptr q = onRunway ? d->findNearestRunwayTaxiNode : d->findNearestTaxiNode;
|
||||
sqlite3_bind_int64(q, 1, airport);
|
||||
|
||||
SGVec3d cartPos(SGVec3d::fromGeod(aPos));
|
||||
sqlite3_bind_double(q, 2, cartPos.x());
|
||||
sqlite3_bind_double(q, 3, cartPos.y());
|
||||
sqlite3_bind_double(q, 4, cartPos.z());
|
||||
|
||||
PositionedID result = 0;
|
||||
while (d->execSelect(q)) {
|
||||
PositionedID id = sqlite3_column_int64(q, 0);
|
||||
if (!aRunway) {
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
|
||||
// ensure found node lies on the runway
|
||||
FGPositionedRef node = loadById(id);
|
||||
double course = SGGeodesy::courseDeg(node->geod(), aRunway->end());
|
||||
if (fabs(headingDifferenceDeg(course, aRunway->headingDeg())) < 3.0 ) {
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d->reset(q);
|
||||
return result;
|
||||
}
|
||||
|
||||
PositionedIDVec NavDataCache::groundNetEdgesFrom(PositionedID pos, bool onlyPushback)
|
||||
{
|
||||
sqlite3_stmt_ptr q = onlyPushback ? d->pushbackEdgesFrom : d->taxiEdgesFrom;
|
||||
sqlite3_bind_int64(q, 1, pos);
|
||||
return d->selectIds(q);
|
||||
}
|
||||
|
||||
PositionedIDVec NavDataCache::findAirportParking(PositionedID airport, const std::string& flightType,
|
||||
int radius)
|
||||
{
|
||||
sqlite3_bind_int64(d->findAirportParking, 1, airport);
|
||||
sqlite3_bind_int(d->findAirportParking, 2, radius);
|
||||
sqlite_bind_stdstring(d->findAirportParking, 3, flightType);
|
||||
|
||||
return d->selectIds(d->findAirportParking);
|
||||
}
|
||||
|
||||
void NavDataCache::dropGroundnetFor(PositionedID aAirport)
|
||||
{
|
||||
sqlite3_stmt_ptr q = d->prepare("DELETE FROM parking WHERE rowid IN (SELECT rowid FROM positioned WHERE type=?1 AND airport=?2)");
|
||||
sqlite3_bind_int(q, 1, FGPositioned::PARKING);
|
||||
sqlite3_bind_int64(q, 2, aAirport);
|
||||
d->execUpdate(q);
|
||||
|
||||
q = d->prepare("DELETE FROM taxi_node WHERE rowid IN (SELECT rowid FROM positioned WHERE (type=?1 OR type=?2) AND airport=?3)");
|
||||
sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE);
|
||||
sqlite3_bind_int(q, 2, FGPositioned::PARKING);
|
||||
sqlite3_bind_int64(q, 3, aAirport);
|
||||
d->execUpdate(q);
|
||||
|
||||
q = d->prepare("DELETE FROM positioned WHERE (type=?1 OR type=?2) AND airport=?3");
|
||||
sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE);
|
||||
sqlite3_bind_int(q, 2, FGPositioned::PARKING);
|
||||
sqlite3_bind_int64(q, 3, aAirport);
|
||||
d->execUpdate(q);
|
||||
|
||||
q = d->prepare("DELETE FROM groundnet_edge WHERE airport=?1");
|
||||
sqlite3_bind_int64(q, 1, aAirport);
|
||||
d->execUpdate(q);
|
||||
}
|
||||
|
||||
void NavDataCache::dropAllGroundnets()
|
||||
{
|
||||
SG_LOG(SG_NAVCACHE, SG_INFO, "dropping ground-net data");
|
||||
beginTransaction();
|
||||
d->runSQL("DELETE FROM groundnet_edge");
|
||||
d->runSQL("DELETE FROM parking");
|
||||
d->runSQL("DELETE FROM taxi_node");
|
||||
|
||||
sqlite3_stmt_ptr q = d->prepare("DELETE FROM positioned WHERE (type=?1 OR type=?2)");
|
||||
sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE);
|
||||
sqlite3_bind_int(q, 2, FGPositioned::PARKING);
|
||||
d->execUpdate(q);
|
||||
commitTransaction();
|
||||
}
|
||||
|
||||
bool NavDataCache::isReadOnly() const
|
||||
{
|
||||
|
|
|
@ -68,13 +68,7 @@ public:
|
|||
* This can happen is the cache file is missing or damaged, or one of the
|
||||
** global input files is changed.
|
||||
*/
|
||||
bool isRebuildRequired();
|
||||
|
||||
/**
|
||||
* check if cached scenery paths have changed, and if so, drop scenery-
|
||||
* dependant data such as ground-nets.
|
||||
*/
|
||||
bool dropGroundnetsIfRequired();
|
||||
bool isRebuildRequired();
|
||||
|
||||
enum RebuildPhase
|
||||
{
|
||||
|
@ -91,8 +85,8 @@ public:
|
|||
*/
|
||||
RebuildPhase rebuild();
|
||||
|
||||
unsigned int rebuildPhaseCompletionPercentage() const;
|
||||
void setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent = 0);
|
||||
unsigned int rebuildPhaseCompletionPercentage() const;
|
||||
void setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent = 0);
|
||||
|
||||
bool isCachedFileModified(const SGPath& path) const;
|
||||
void stampCacheFile(const SGPath& path);
|
||||
|
@ -140,27 +134,6 @@ public:
|
|||
PositionedID createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos);
|
||||
|
||||
bool removePOI(FGPositioned::Type ty, const std::string& aIdent);
|
||||
|
||||
void dropGroundnetFor(PositionedID aAirport);
|
||||
|
||||
/**
|
||||
* Remove all ground-nets globally from the cache.
|
||||
* This includes parking and taxi-nodes and edges between them. It's useful
|
||||
* when scenery paths change, since the ground-nets depend on the scenery.
|
||||
* Using this we can avoid havind to rebuild the entire cache.
|
||||
*/
|
||||
void dropAllGroundnets();
|
||||
|
||||
PositionedID insertParking(const std::string& name, const SGGeod& aPos,
|
||||
PositionedID aAirport,
|
||||
double aHeading, int aRadius, const std::string& aAircraftType,
|
||||
const std::string& aAirlines);
|
||||
|
||||
void setParkingPushBackRoute(PositionedID parking, PositionedID pushBackNode);
|
||||
|
||||
PositionedID insertTaxiNode(const SGGeod& aPos, PositionedID aAirport, int aHoldType, bool aOnRunway);
|
||||
|
||||
void insertGroundnetEdge(PositionedID aAirport, PositionedID from, PositionedID to);
|
||||
|
||||
/// update the metar flag associated with an airport
|
||||
void setAirportMetar(const std::string& icao, bool hasMetar);
|
||||
|
@ -269,18 +242,6 @@ public:
|
|||
*/
|
||||
AirwayEdgeVec airwayEdgesFrom(int network, PositionedID pos);
|
||||
|
||||
// ground-network
|
||||
PositionedIDVec groundNetNodes(PositionedID aAirport, bool onlyPushback);
|
||||
void markGroundnetAsPushback(PositionedID nodeId);
|
||||
|
||||
PositionedID findGroundNetNode(PositionedID airport, const SGGeod& aPos,
|
||||
bool onRunway, FGRunway* aRunway = NULL);
|
||||
PositionedIDVec groundNetEdgesFrom(PositionedID pos, bool onlyPushback);
|
||||
|
||||
PositionedIDVec findAirportParking(PositionedID airport, const std::string& flightType,
|
||||
int radius);
|
||||
|
||||
|
||||
class Transaction
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -64,6 +64,7 @@ static bool validateFilter(FGPositioned::Filter* filter)
|
|||
return true;
|
||||
}
|
||||
|
||||
const PositionedID FGPositioned::TRANSIENT_ID = -2;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -82,7 +83,6 @@ FGPositioned::FGPositioned( PositionedID aGuid,
|
|||
|
||||
FGPositioned::~FGPositioned()
|
||||
{
|
||||
// std::cout << "destroying:" << mIdent << "/" << nameForType(mType) << std::endl;
|
||||
}
|
||||
|
||||
FGPositioned*
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace flightgear { class NavDataCache; }
|
|||
class FGPositioned : public SGReferenced
|
||||
{
|
||||
public:
|
||||
static const PositionedID TRANSIENT_ID;
|
||||
|
||||
typedef enum {
|
||||
INVALID = 0,
|
||||
|
|
|
@ -1352,20 +1352,10 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args)
|
|||
}
|
||||
|
||||
FGAirportDynamics* dynamics = apt->getDynamics();
|
||||
PositionedIDVec parkings = flightgear::NavDataCache::instance()->airportItemsOfType(apt->guid(),
|
||||
FGPositioned::PARKING);
|
||||
|
||||
BOOST_FOREACH(PositionedID parking, parkings) {
|
||||
// filter out based on availability and type
|
||||
if (onlyAvailable && !dynamics->isParkingAvailable(parking)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FGParking* park = dynamics->getParking(parking);
|
||||
if (!type.empty() && (park->getType() != type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FGParkingList parkings = dynamics->getParkings(onlyAvailable, type);
|
||||
FGParkingList::const_iterator it;
|
||||
for (it = parkings.begin(); it != parkings.end(); ++it) {
|
||||
FGParkingRef park = *it;
|
||||
const SGGeod& parkLoc = park->geod();
|
||||
naRef ph = naNewHash(c);
|
||||
hashset(c, ph, "name", stringToNasal(c, park->getName()));
|
||||
|
|
|
@ -208,27 +208,8 @@ 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();
|
||||
PositionedIDVec parkings =
|
||||
flightgear::NavDataCache::instance()
|
||||
->airportItemsOfType(apt.guid(), FGPositioned::PARKING);
|
||||
|
||||
FGParkingList ret;
|
||||
BOOST_FOREACH(PositionedID parking, parkings)
|
||||
{
|
||||
// filter out based on availability and type
|
||||
if( only_available && !dynamics->isParkingAvailable(parking) )
|
||||
continue;
|
||||
|
||||
FGParking* park = dynamics->getParking(parking);
|
||||
if( !type.empty() && (park->getType() != type) )
|
||||
continue;
|
||||
|
||||
ret.push_back(park);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return dynamics->getParkings(only_available, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue