1
0
Fork 0

AI Update:

- Ground network slow-down finally works as expected
   (although occasionally causing a traffic jam)
 - Hold position instruction now really sets speed to zero, in addition
   it actually works now for crossing and two-way traffic
 - Attempt to limit execution time of ground network trace algorithm
   to make performance acceptable at high-density networks
 - Removed remaining terminal messages
 - Various minor tweaks and clean-ups
This commit is contained in:
durk 2006-11-11 10:52:05 +00:00
parent bb7c889bbb
commit 33037b2139
11 changed files with 329 additions and 122 deletions

View file

@ -1034,19 +1034,20 @@ void FGAIAircraft::announcePositionToController()
callsign += "Heavy"; callsign += "Heavy";
switch (leg) { switch (leg) {
case 3: case 3:
cerr << callsign << " ready to taxi to runway " << fp->getRunway() << endl; //cerr << callsign << " ready to taxi to runway " << fp->getRunway() << endl;
break; break;
case 4: case 4:
cerr << callsign << " at runway " << fp->getRunway() << "Ready for take-off. " //cerr << callsign << " at runway " << fp->getRunway() << "Ready for take-off. "
<< trafficRef->getFlightRules() << " to " << trafficRef->getArrivalAirport()->getId() // << trafficRef->getFlightRules() << " to " << trafficRef->getArrivalAirport()->getId()
<< "(" << trafficRef->getArrivalAirport()->getName() << ")."<< endl; // << "(" << trafficRef->getArrivalAirport()->getName() << ")."<< endl;
break;
} }
} }
prevController = controller; prevController = controller;
if (controller) { if (controller) {
controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex, controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex,
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft, _getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
trafficRef->getRadius(), leg); trafficRef->getRadius(), leg, trafficRef->getCallSign());
} }
} }
} }
@ -1061,20 +1062,22 @@ void FGAIAircraft::processATC(FGATCInstruction instruction)
// Hold Position // Hold Position
if (instruction.getHoldPosition ()) { if (instruction.getHoldPosition ()) {
if (!holdPos) { if (!holdPos) {
if (trafficRef) //if (trafficRef)
cerr << trafficRef->getCallSign() << "Holding Position " << endl; //cerr << trafficRef->getCallSign() << "Holding Position " << endl;
holdPos = true; holdPos = true;
} }
AccelTo(0.25); AccelTo(0.0);
} else { } else {
if (holdPos) { if (holdPos) {
if (trafficRef) //if (trafficRef)
cerr << trafficRef->getCallSign() << " Resuming Taxi " << endl; // cerr << trafficRef->getCallSign() << " Resuming Taxi " << endl;
holdPos = false; holdPos = false;
} }
// Change speed Instruction. This can only be excecuted when there is no // Change speed Instruction. This can only be excecuted when there is no
// Hold position instruction. // Hold position instruction.
if (instruction.getChangeSpeed ()) { if (instruction.getChangeSpeed ()) {
// if (trafficRef)
//cerr << trafficRef->getCallSign() << " Changing Speed " << endl;
AccelTo(instruction.getSpeed()); AccelTo(instruction.getSpeed());
}else { }else {
if (fp) AccelTo(fp->getPreviousWaypoint()->speed); if (fp) AccelTo(fp->getPreviousWaypoint()->speed);

View file

@ -115,11 +115,12 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
radius, fltType, radius, fltType,
aircraftType, airline))) aircraftType, airline)))
{ {
SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " << SG_LOG(SG_INPUT, SG_ALERT, "Could not find parking for a " <<
aircraftType << aircraftType <<
" of flight type " << fltType << " of flight type " << fltType <<
" of airline " << airline << " of airline " << airline <<
" at airport " << dep->getId()); " at airport " << dep->getId());
//exit(1);
} }
} }
else else

View file

@ -161,11 +161,19 @@ bool FGAirportDynamics::getAvailableParking(double *lat, double *lon, double *he
continue; continue;
} }
else // Airline code doesn't match else // Airline code doesn't match
{
//cerr << "Code = " << airline << ": Codes " << i->getCodes();
if (i->getCodes().find(airline, 0) == string::npos) if (i->getCodes().find(airline, 0) == string::npos)
{ {
available = false; available = false;
//cerr << "Unavailable" << endl;
continue; continue;
} }
else
{
//cerr << "Available" << endl;
}
}
// Type doesn't match // Type doesn't match
if (i->getType() != flType) if (i->getType() != flType)
{ {

View file

@ -41,6 +41,7 @@
//#include <Main/fg_props.hxx> //#include <Main/fg_props.hxx>
//#include <Airports/runways.hxx> //#include <Airports/runways.hxx>
#include <AIModel/AIFlightPlan.hxx> #include <AIModel/AIFlightPlan.hxx>
//#include STL_STRING //#include STL_STRING
@ -58,6 +59,14 @@ FGTaxiNode::FGTaxiNode()
{ {
} }
void FGTaxiNode::sortEndSegments(bool byLength)
{
if (byLength)
sort(next.begin(), next.end(), sortByLength);
else
sort(next.begin(), next.end(), sortByHeadingDiff);
}
bool compare_nodes(FGTaxiNode *a, FGTaxiNode *b) { bool compare_nodes(FGTaxiNode *a, FGTaxiNode *b) {
return (*a) < (*b); return (*a) < (*b);
@ -69,6 +78,7 @@ return (*a) < (*b);
FGTaxiSegment::FGTaxiSegment() FGTaxiSegment::FGTaxiSegment()
{ {
oppositeDirection = 0; oppositeDirection = 0;
isActive = true;
} }
void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes) void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
@ -100,11 +110,13 @@ void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
} }
} }
// There is probably a computationally cheaper way of // There is probably a computationally cheaper way of
// doing this. // doing this.
void FGTaxiSegment::setTrackDistance() void FGTaxiSegment::setTrackDistance()
{ {
double course; //double course;
SGWayPoint first (start->getLongitude(), SGWayPoint first (start->getLongitude(),
start->getLatitude(), start->getLatitude(),
0); 0);
@ -114,10 +126,26 @@ void FGTaxiSegment::setTrackDistance()
first.CourseAndDistance(second, &course, &length); first.CourseAndDistance(second, &course, &length);
} }
void FGTaxiSegment::setCourseDiff(double crse)
{
headingDiff = fabs(course-crse);
if (headingDiff > 180)
headingDiff = fabs(headingDiff - 360);
}
bool compare_segments(FGTaxiSegment *a, FGTaxiSegment *b) { bool compare_segments(FGTaxiSegment *a, FGTaxiSegment *b) {
return (*a) < (*b); return (*a) < (*b);
} }
bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b) {
return a->hasSmallerHeadingDiff(*b);
}
bool sortByLength(FGTaxiSegment *a, FGTaxiSegment *b) {
return a->getLength() > b->getLength();
}
/*************************************************************************** /***************************************************************************
* FGTaxiRoute * FGTaxiRoute
**************************************************************************/ **************************************************************************/
@ -204,6 +232,8 @@ FGGroundNetwork::FGGroundNetwork()
foundRoute = false; foundRoute = false;
totalDistance = 0; totalDistance = 0;
maxDistance = 0; maxDistance = 0;
maxDepth = 1000;
count = 0;
currTraffic = activeTraffic.begin(); currTraffic = activeTraffic.begin();
} }
@ -271,6 +301,7 @@ void FGGroundNetwork::init()
i++; i++;
index++; index++;
} }
i = segments.begin(); i = segments.begin();
while(i != segments.end()) { while(i != segments.end()) {
FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute(); FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute();
@ -283,17 +314,21 @@ void FGGroundNetwork::init()
int start2 = (*j)->getStart()->getIndex(); int start2 = (*j)->getStart()->getIndex();
int end2 = (*j)->getEnd()->getIndex(); int end2 = (*j)->getEnd()->getIndex();
int oppIndex = (*j)->getIndex(); int oppIndex = (*j)->getIndex();
// cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") " //cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
// << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl; // << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl;
(*i)->setOpposite(*j);
break; break;
} }
j++; j++;
} }
i++; i++;
} }
//cerr << "Done initializing ground network" << endl;
//exit(1); //exit(1);
} }
int FGGroundNetwork::findNearestNode(double lat, double lon) int FGGroundNetwork::findNearestNode(double lat, double lon)
{ {
double minDist = HUGE_VAL; double minDist = HUGE_VAL;
@ -359,6 +394,8 @@ FGTaxiSegment *FGGroundNetwork::findSegment(int idx)
FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end) FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
{ {
double course;
double length;
foundRoute = false; foundRoute = false;
totalDistance = 0; totalDistance = 0;
FGTaxiNode *firstNode = findNode(start); FGTaxiNode *firstNode = findNode(start);
@ -368,14 +405,41 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
routes.clear(); routes.clear();
nodesStack.clear(); nodesStack.clear();
routesStack.clear(); routesStack.clear();
//cerr << "Begin of Trace " << endl; // calculate distance and heading "as the crow flies" between starn and end points"
SGWayPoint first(firstNode->getLongitude(),
firstNode->getLatitude(),
0);
destination = SGWayPoint(lastNode->getLongitude(),
lastNode->getLatitude(),
0);
first.CourseAndDistance(destination, &course, &length);
for (FGTaxiSegmentVectorIterator
itr = segments.begin();
itr != segments.end(); itr++)
{
(*itr)->setCourseDiff(course);
}
//FGTaxiNodeVectorIterator nde = nodes.begin();
//while (nde != nodes.end()) {
// (*nde)->sortEndSegments();
// nde++;
//}
maxDepth = 1000;
//do
// {
// cerr << "Begin of Trace " << start << " to "<< end << " maximum depth = " << maxDepth << endl;
trace(firstNode, end, 0, 0); trace(firstNode, end, 0, 0);
// maxDepth--;
// }
//while ((routes.size() != 0) && (maxDepth > 0));
//cerr << "End of Trace" << endl; //cerr << "End of Trace" << endl;
FGTaxiRoute empty; FGTaxiRoute empty;
if (!foundRoute) if (!foundRoute)
{ {
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find route from waypoint " << start << " to " << end ); SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find route from waypoint " << start << " to " << end << " at " <<
parent->getId());
exit(1); exit(1);
} }
sort(routes.begin(), routes.end()); sort(routes.begin(), routes.end());
@ -385,7 +449,19 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
// } // }
if (routes.begin() != routes.end()) if (routes.begin() != routes.end())
{
// if ((routes.begin()->getDepth() < 0.5 * maxDepth) && (maxDepth > 1))
// {
// maxDepth--;
// cerr << "Max search depth decreased to : " << maxDepth;
// }
// else
// {
// maxDepth++;
// cerr << "Max search depth increased to : " << maxDepth;
// }
return *(routes.begin()); return *(routes.begin());
}
else else
return empty; return empty;
} }
@ -401,23 +477,25 @@ void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double dis
} }
nodesStack.push_back(currNode->getIndex()); nodesStack.push_back(currNode->getIndex());
totalDistance += distance; totalDistance += distance;
//cerr << "Starting trace " << depth << " total distance: " << totalDistance<< " " //cerr << "Starting trace " << currNode->getIndex() << " " << "total distance: " << totalDistance << endl;
// << currNode->getIndex() << endl; // << currNode->getIndex() << endl;
// If the current route matches the required end point we found a valid route // If the current route matches the required end point we found a valid route
// So we can add this to the routing table // So we can add this to the routing table
if (currNode->getIndex() == end) if (currNode->getIndex() == end)
{ {
//cerr << "Found route : " << totalDistance << "" << " " << *(nodesStack.end()-1) << endl; maxDepth = depth;
routes.push_back(FGTaxiRoute(nodesStack,routesStack,totalDistance)); //cerr << "Found route : " << totalDistance << "" << " " << *(nodesStack.end()-1) << " Depth = " << depth << endl;
routes.push_back(FGTaxiRoute(nodesStack,routesStack,totalDistance, depth));
if (nodesStack.empty() || routesStack.empty()) if (nodesStack.empty() || routesStack.empty())
{ {
printRoutingError(string("while finishing route")); printRoutingError(string("while finishing route"));
} }
nodesStack.pop_back(); nodesStack.pop_back();
routesStack.pop_back(); routesStack.pop_back();
if (!(foundRoute)) if (!(foundRoute)) {
maxDistance = totalDistance; maxDistance = totalDistance;
}
else else
if (totalDistance < maxDistance) if (totalDistance < maxDistance)
maxDistance = totalDistance; maxDistance = totalDistance;
@ -451,10 +529,22 @@ void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double dis
totalDistance -= distance; totalDistance -= distance;
return; return;
} }
if (depth >= maxDepth) {
count++;
if (!(count % 100000)) {
maxDepth--; // Gradually decrease maxdepth, to prevent "eternal searches"
//cerr << "Reducing maxdepth to " << maxDepth << endl;
}
nodesStack.pop_back();
routesStack.pop_back();
totalDistance -= distance;
return;
}
// If the total distance from start to the current waypoint // If the total distance from start to the current waypoint
// is longer than that of a route we can also stop this trace // is longer than that of a route we can also stop this trace
// and go back one level. // and go back one level.
if ((totalDistance > maxDistance) && foundRoute) if ((totalDistance > maxDistance) && foundRoute)
//if (foundRoute)
{ {
//cerr << "Stopping rediculously long trace: " << totalDistance << endl; //cerr << "Stopping rediculously long trace: " << totalDistance << endl;
if (nodesStack.empty() || routesStack.empty()) if (nodesStack.empty() || routesStack.empty())
@ -471,7 +561,36 @@ void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double dis
//cerr << "2" << endl; //cerr << "2" << endl;
if (currNode->getBeginRoute() != currNode->getEndRoute()) if (currNode->getBeginRoute() != currNode->getEndRoute())
{ {
double course, length;
//cerr << "3" << endl; //cerr << "3" << endl;
// calculate distance and heading "as the crow flies" between starn and end points"
SGWayPoint first(currNode->getLongitude(),
currNode->getLatitude(),
0);
//SGWayPoint second (lastNode->getLongitude(),
// lastNode->getLatitude(),
// 0);
first.CourseAndDistance(destination, &course, &length);
//for (FGTaxiSegmentVectorIterator
// itr = segments.begin();
// itr != segments.end(); itr++)
// {
// (*itr)->setCourseDiff(course);
// }
//FGTaxiNodeVectorIterator nde = nodes.begin();
//while (nde != nodes.end()) {
//(*nde)->sortEndSegments();
//nde++;
for (FGTaxiSegmentVectorIterator
i = currNode->getBeginRoute();
i != currNode->getEndRoute();
i++)
{
(*i)->setCourseDiff(course);
}
currNode->sortEndSegments(foundRoute);
for (FGTaxiSegmentVectorIterator for (FGTaxiSegmentVectorIterator
i = currNode->getBeginRoute(); i = currNode->getBeginRoute();
i != currNode->getEndRoute(); i != currNode->getEndRoute();
@ -529,7 +648,8 @@ void FGGroundNetwork::printRoutingError(string mess)
void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition, void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
double lat, double lon, double heading, double lat, double lon, double heading,
double speed, double alt, double radius, int leg) double speed, double alt, double radius, int leg,
string callsign)
{ {
TrafficVectorIterator i = activeTraffic.begin(); TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id alread has an entry // Search search if the current id alread has an entry
@ -550,6 +670,7 @@ void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, in
rec.setPositionAndIntentions(currentPosition, intendedRoute); rec.setPositionAndIntentions(currentPosition, intendedRoute);
rec.setPositionAndHeading(lat, lon, heading, speed, alt); rec.setPositionAndHeading(lat, lon, heading, speed, alt);
rec.setRadius(radius); // only need to do this when creating the record. rec.setRadius(radius); // only need to do this when creating the record.
rec.setCallSign(callsign);
activeTraffic.push_back(rec); activeTraffic.push_back(rec);
} else { } else {
i->setPositionAndIntentions(currentPosition, intendedRoute); i->setPositionAndIntentions(currentPosition, intendedRoute);
@ -625,6 +746,7 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
TrafficVectorIterator current, closest; TrafficVectorIterator current, closest;
TrafficVectorIterator i = activeTraffic.begin(); TrafficVectorIterator i = activeTraffic.begin();
bool otherReasonToSlowDown = false; bool otherReasonToSlowDown = false;
bool previousInstruction;
if (activeTraffic.size()) if (activeTraffic.size())
{ {
//while ((i->getId() != id) && (i != activeTraffic.end())) //while ((i->getId() != id) && (i != activeTraffic.end()))
@ -643,6 +765,7 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment"); SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
} }
current = i; current = i;
previousInstruction = current->getSpeedAdjustment();
double mindist = HUGE; double mindist = HUGE;
if (activeTraffic.size()) if (activeTraffic.size())
{ {
@ -726,66 +849,28 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
//cerr << "Distance : " << dist << " bearing : " << bearing << " heading : " << heading //cerr << "Distance : " << dist << " bearing : " << bearing << " heading : " << heading
// << " course : " << course << endl; // << " course : " << course << endl;
current->clearSpeedAdjustment(); current->clearSpeedAdjustment();
// Only clear the heading adjustment at positive speeds, otherwise the waypoint following
// code wreaks havoc
if (speed > 0.2)
current->clearHeadingAdjustment();
// All clear
if (mindist > 100)
{
//current->clearSpeedAdjustment();
//current->clearHeadingAdjustment();
}
else
{
if (current->checkPositionAndIntentions(*closest) || otherReasonToSlowDown)
{
double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius());
if (mindist < 2*maxAllowableDistance)
{
if (current->getId() == closest->getWaitsForId()) if (current->getId() == closest->getWaitsForId())
return; return;
else else
current->setWaitsForId(closest->getId()); current->setWaitsForId(closest->getId());
// Getting close: Slow down to a bit less than the other aircraft
double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius());
if (mindist > maxAllowableDistance)
{
if (current->checkPositionAndIntentions(*closest) || otherReasonToSlowDown)
{
// Adjust speed, but don't let it drop to below 1 knots
//if (fabs(speed) > 1)
if (!(current->hasHeadingAdjustment()))
{
if (closest != current) if (closest != current)
current->setSpeedAdjustment(closest->getSpeed()* (mindist/100)); current->setSpeedAdjustment(closest->getSpeed()* (mindist/100));
else else
current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
//cerr << "Adjusting speed to " << closest->getSpeed() * (mindist / 100) << " " if (mindist < maxAllowableDistance)
// << "Bearing = " << minbearing << " Distance = " << mindist
// << " Latitude = " <<lat << " longitude = " << lon << endl;
//<< " Latitude = " <<closest->getLatitude()
//<< " longitude = " << closest->getLongitude()
// << endl;
}
else
{ {
double newSpeed = (maxAllowableDistance-mindist); //double newSpeed = (maxAllowableDistance-mindist);
current->setSpeedAdjustment(newSpeed); //current->setSpeedAdjustment(newSpeed);
} //if (mindist < 0.5* maxAllowableDistance)
} // {
} current->setSpeedAdjustment(0);
else // }
{
if (!(current->hasHeadingAdjustment()))
{
double newSpeed;
if (mindist > 10) {
// newSpeed = 0.01;
// current->setSpeedAdjustment(newSpeed);
} else {
newSpeed = -1 * (maxAllowableDistance-mindist);
current->setSpeedAdjustment(newSpeed);
current->setHeadingAdjustment(heading);
}
} }
} }
} }
@ -850,10 +935,12 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
i->getAltitude ()); i->getAltitude ());
//other.CourseAndDistance(curr, &course, &dist); //other.CourseAndDistance(curr, &course, &dist);
bool needsToWait; bool needsToWait;
bool opposing;
if (current->isOpposing(this, *i, node)) if (current->isOpposing(this, *i, node))
{ {
needsToWait = true; needsToWait = true;
//cerr << "Hold check 2 : " << id << " has opposing segment " << endl; opposing = true;
//cerr << "Hold check 2 : " << node << " has opposing segment " << endl;
// issue a "Hold Position" as soon as we're close to the offending node // issue a "Hold Position" as soon as we're close to the offending node
// For now, I'm doing this as long as the other aircraft doesn't // For now, I'm doing this as long as the other aircraft doesn't
// have a hold instruction as soon as we're within a reasonable // have a hold instruction as soon as we're within a reasonable
@ -864,8 +951,9 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
} }
else else
{ {
opposing = false;
other.CourseAndDistance(nodePos, &course, &dist); other.CourseAndDistance(nodePos, &course, &dist);
if (dist > 2.0*i->getRadius()) if (dist > 200) // 2.0*i->getRadius())
{ {
needsToWait = false; needsToWait = false;
//cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue " //cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue "
@ -874,21 +962,32 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
else else
{ {
needsToWait = true; needsToWait = true;
//cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " nm" << endl; //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
} }
} }
curr.CourseAndDistance(nodePos, &course, &dist); curr.CourseAndDistance(nodePos, &course, &dist);
if (!(i->hasHoldPosition())) if (!(i->hasHoldPosition()))
{ {
if ((dist < 2.5*current->getRadius()) && if ((dist < 200) && //2.5*current->getRadius()) &&
(needsToWait) && (needsToWait) &&
(!(current->getId() == i->getWaitsForId())) && (i->onRoute(this, *current)) &&
(!(current->getSpeedAdjustment()))) //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
(!(current->getId() == i->getWaitsForId())))
//(!(i->getSpeedAdjustment()))) // &&
//(!(current->getSpeedAdjustment())))
{ {
current->setHoldPosition(true); current->setHoldPosition(true);
//cerr << "Hold check 5: " << id <<" Setting Hold Position: distance to node : " << dist << " nm"<< endl; //cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
// << dist << " meters. Waiting for " << i->getCallSign();
//if (opposing)
//cerr <<" [opposing] " << endl;
//else
// cerr << "[non-opposing] " << endl;
//if (i->hasSpeefAdjustment())
// {
// cerr << " (which in turn waits for ) " << i->
} }
else else
{ {

View file

@ -25,6 +25,7 @@
#define _GROUNDNETWORK_HXX_ #define _GROUNDNETWORK_HXX_
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/route/waypoint.hxx>
#include STL_STRING #include STL_STRING
@ -33,7 +34,6 @@
SG_USING_STD(string); SG_USING_STD(string);
SG_USING_STD(vector); SG_USING_STD(vector);
#include "parking.hxx" #include "parking.hxx"
#include "trafficcontrol.hxx" #include "trafficcontrol.hxx"
@ -41,6 +41,7 @@ SG_USING_STD(vector);
class FGTaxiSegment; // forward reference class FGTaxiSegment; // forward reference
class FGAIFlightPlan; // forward reference class FGAIFlightPlan; // forward reference
class FGAirport; // forward reference
typedef vector<FGTaxiSegment*> FGTaxiSegmentVector; typedef vector<FGTaxiSegment*> FGTaxiSegmentVector;
typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator; typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator;
@ -78,6 +79,8 @@ public:
FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); }; FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); };
FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); }; FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); };
bool operator<(const FGTaxiNode &other) const { return index < other.index; }; bool operator<(const FGTaxiNode &other) const { return index < other.index; };
void sortEndSegments(bool);
}; };
typedef vector<FGTaxiNode*> FGTaxiNodeVector; typedef vector<FGTaxiNode*> FGTaxiNodeVector;
@ -92,11 +95,16 @@ private:
int startNode; int startNode;
int endNode; int endNode;
double length; double length;
double course;
double headingDiff;
bool isActive;
FGTaxiNode *start; FGTaxiNode *start;
FGTaxiNode *end; FGTaxiNode *end;
int index; int index;
FGTaxiSegment *oppositeDirection; FGTaxiSegment *oppositeDirection;
public: public:
FGTaxiSegment(); FGTaxiSegment();
//FGTaxiSegment(FGTaxiNode *, FGTaxiNode *, int); //FGTaxiSegment(FGTaxiNode *, FGTaxiNode *, int);
@ -119,15 +127,22 @@ public:
FGTaxiSegment *getAddress() { return this;}; FGTaxiSegment *getAddress() { return this;};
bool operator<(const FGTaxiSegment &other) const { return index < other.index; }; bool operator<(const FGTaxiSegment &other) const { return index < other.index; };
bool hasSmallerHeadingDiff (const FGTaxiSegment &other) const { return headingDiff < other.headingDiff; };
FGTaxiSegment *opposite() { return oppositeDirection; }; FGTaxiSegment *opposite() { return oppositeDirection; };
void setCourseDiff(double crse);
}; };
typedef vector<int> intVec; typedef vector<int> intVec;
typedef vector<int>::iterator intVecIterator; typedef vector<int>::iterator intVecIterator;
/*************************************************************************************** /***************************************************************************************
* class FGTaxiRoute * class FGTaxiRoute
**************************************************************************************/ **************************************************************************************/
@ -137,16 +152,18 @@ private:
intVec nodes; intVec nodes;
intVec routes; intVec routes;
double distance; double distance;
int depth;
intVecIterator currNode; intVecIterator currNode;
intVecIterator currRoute; intVecIterator currRoute;
public: public:
FGTaxiRoute() { distance = 0; currNode = nodes.begin(); currRoute = routes.begin();}; FGTaxiRoute() { distance = 0; currNode = nodes.begin(); currRoute = routes.begin();};
FGTaxiRoute(intVec nds, intVec rts, double dist) { FGTaxiRoute(intVec nds, intVec rts, double dist, int dpth) {
nodes = nds; nodes = nds;
routes = rts; routes = rts;
distance = dist; distance = dist;
currNode = nodes.begin(); currNode = nodes.begin();
depth = dpth;
}; };
bool operator< (const FGTaxiRoute &other) const {return distance < other.distance; }; bool operator< (const FGTaxiRoute &other) const {return distance < other.distance; };
bool empty () { return nodes.begin() == nodes.end(); }; bool empty () { return nodes.begin() == nodes.end(); };
@ -156,12 +173,14 @@ public:
void first() { currNode = nodes.begin(); currRoute = routes.begin(); }; void first() { currNode = nodes.begin(); currRoute = routes.begin(); };
int size() { return nodes.size(); }; int size() { return nodes.size(); };
int getDepth() { return depth; };
}; };
typedef vector<FGTaxiRoute> TaxiRouteVector; typedef vector<FGTaxiRoute> TaxiRouteVector;
typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator; typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator;
bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b);
bool sortByLength (FGTaxiSegment *a, FGTaxiSegment *b);
/************************************************************************************** /**************************************************************************************
@ -171,6 +190,8 @@ class FGGroundNetwork : public FGATCController
{ {
private: private:
bool hasNetwork; bool hasNetwork;
int maxDepth;
int count;
FGTaxiNodeVector nodes; FGTaxiNodeVector nodes;
FGTaxiSegmentVector segments; FGTaxiSegmentVector segments;
//intVec route; //intVec route;
@ -179,10 +200,13 @@ private:
TaxiRouteVector routes; TaxiRouteVector routes;
TrafficVector activeTraffic; TrafficVector activeTraffic;
TrafficVectorIterator currTraffic; TrafficVectorIterator currTraffic;
SGWayPoint destination;
bool foundRoute; bool foundRoute;
double totalDistance, maxDistance; double totalDistance, maxDistance;
FGTowerController *towerController; FGTowerController *towerController;
FGAirport *parent;
void printRoutingError(string); void printRoutingError(string);
@ -208,8 +232,11 @@ public:
FGTaxiRoute findShortestRoute(int start, int end); FGTaxiRoute findShortestRoute(int start, int end);
void trace(FGTaxiNode *, int, int, double dist); void trace(FGTaxiNode *, int, int, double dist);
void setParent(FGAirport *par) { parent = par; };
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon, double hdg, double spd, double alt, double radius, int leg); double lat, double lon, double hdg, double spd, double alt,
double radius, int leg, string callsign);
virtual void signOff(int id); virtual void signOff(int id);
virtual void update(int id, double lat, double lon, double heading, double speed, double alt, double dt); virtual void update(int id, double lat, double lon, double heading, double speed, double alt, double dt);
virtual bool hasInstruction(int id); virtual bool hasInstruction(int id);

View file

@ -255,12 +255,12 @@ void RunwayGroup::setActive(const string &aptId,
//cerr << "Crosswnd : " << crossWind << endl; //cerr << "Crosswnd : " << crossWind << endl;
if ((tailWind > maxTail) || (crossWind > maxCross)) if ((tailWind > maxTail) || (crossWind > maxCross))
{ {
//cerr << "Invalid : "; //cerr << "Invalid : " << endl;
validSelection = false; validSelection = false;
} }
else else
{ {
//cerr << "Valid : "; //cerr << "Valid : " << endl;;
} }
}else { }else {
SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId ); SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
@ -269,19 +269,19 @@ void RunwayGroup::setActive(const string &aptId,
} }
if (validSelection) if (validSelection)
{ {
//cerr << "Valid : "; //cerr << "Valid selection : " << i << endl;;
foundValidSelection = true; foundValidSelection = true;
for (stringVecIterator it = currentlyActive->begin(); for (stringVecIterator it = currentlyActive->begin();
it != currentlyActive->end(); it++) it != currentlyActive->end(); it++)
{ {
if ((*it) == name) if ((*it) == name)
match++; match++;
}
if (match >= bestMatch) { if (match >= bestMatch) {
bestMatch = match; bestMatch = match;
bestChoice = i; bestChoice = i;
} }
} }
}
//cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl; //cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
} }
if (foundValidSelection) if (foundValidSelection)

View file

@ -108,7 +108,9 @@ FGAirportDynamics * FGAirport::getDynamics()
if (parkpath.exists()) { if (parkpath.exists()) {
try { try {
readXML(parkpath.str(),*dynamics); readXML(parkpath.str(),*dynamics);
//cerr << "Initializing " << getId() << endl;
dynamics->init(); dynamics->init();
dynamics->getGroundNetwork()->setParent(this);
} catch (const sg_exception &e) { } catch (const sg_exception &e) {
//cerr << "unable to read " << parkpath.str() << endl; //cerr << "unable to read " << parkpath.str() << endl;
} }

View file

@ -54,11 +54,11 @@ void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
//cerr << "setting intentions "; //cerr << "setting intentions ";
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
int val = route->getRouteIndex(i); int val = route->getRouteIndex(i);
//cerr << val<< " ";
if ((val) && (val != pos)) if ((val) && (val != pos))
{ {
intentions.push_back(val); intentions.push_back(val);
//cerr << val<< " "; //cerr << "[set] ";
} }
} }
//cerr << endl; //cerr << endl;
@ -76,7 +76,7 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other)
//cerr << "Start check 1" << endl; //cerr << "Start check 1" << endl;
if (currentPos == other.currentPos) if (currentPos == other.currentPos)
{ {
//cerr << "Check Position and intentions: current matches" << endl; //cerr << callsign << ": Check Position and intentions: we are on the same taxiway" << other.callsign << "Index = " << currentPos << endl;
result = true; result = true;
} }
// else if (other.intentions.size()) // else if (other.intentions.size())
@ -100,7 +100,7 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other)
i++; i++;
} }
if (i != intentions.end()) { if (i != intentions.end()) {
//cerr << "Check Position and intentions: .other.current matches" << endl; //cerr << callsign << ": Check Position and intentions: .other.current matches" << other.callsign << "Index = " << (*i) << endl;
result = true; result = true;
} }
} }
@ -178,6 +178,45 @@ int FGTrafficRecord::crosses(FGGroundNetwork *net, FGTrafficRecord &other)
return -1; return -1;
} }
bool FGTrafficRecord::onRoute(FGGroundNetwork *net, FGTrafficRecord &other)
{
int node = -1, othernode = -1;
if (currentPos >0)
node = net->findSegment(currentPos)->getEnd()->getIndex();
if (other.currentPos > 0)
othernode = net->findSegment(other.currentPos)->getEnd()->getIndex();
if ((node == othernode) && (node != -1))
return true;
if (other.intentions.size())
{
for (intVecIterator i = other.intentions.begin(); i != other.intentions.end(); i++)
{
if (*i > 0)
{
othernode = net->findSegment(*i)->getEnd()->getIndex();
if ((node == othernode) && (node > -1))
return true;
}
}
}
//if (other.currentPos > 0)
// othernode = net->findSegment(other.currentPos)->getEnd()->getIndex();
//if (intentions.size())
// {
// for (intVecIterator i = intentions.begin(); i != intentions.end(); i++)
// {
// if (*i > 0)
// {
// node = net->findSegment(*i)->getEnd()->getIndex();
// if ((node == othernode) && (node > -1))
// return true;
// }
// }
// }
return false;
}
bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other, int node) bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other, int node)
{ {
// Check if current segment is the reverse segment for the other aircraft // Check if current segment is the reverse segment for the other aircraft
@ -193,6 +232,19 @@ bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other,
for (intVecIterator i = intentions.begin(); i != intentions.end(); i++) for (intVecIterator i = intentions.begin(); i != intentions.end(); i++)
{ {
if (opp = net->findSegment(other.currentPos)->opposite())
{
if ((*i) > 0)
if (opp->getIndex() == net->findSegment(*i)->getIndex())
{
if (net->findSegment(*i)->getStart()->getIndex() == node) {
{
//cerr << "Found the node " << node << endl;
return true;
}
}
}
}
if (other.intentions.size()) if (other.intentions.size())
{ {
for (intVecIterator j = other.intentions.begin(); j != other.intentions.end(); j++) for (intVecIterator j = other.intentions.begin(); j != other.intentions.end(); j++)
@ -204,12 +256,12 @@ bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other,
if (opp->getIndex() == if (opp->getIndex() ==
net->findSegment(*j)->getIndex()) net->findSegment(*j)->getIndex())
{ {
// cerr << "Nodes " << net->findSegment(*i)->getIndex() //cerr << "Nodes " << net->findSegment(*i)->getIndex()
// << " and " << net->findSegment(*j)->getIndex() // << " and " << net->findSegment(*j)->getIndex()
// << " are opposites " << endl; // << " are opposites " << endl;
if (net->findSegment(*i)->getStart()->getIndex() == node) { if (net->findSegment(*i)->getStart()->getIndex() == node) {
{ {
//cerr << "Found the node" << endl; //cerr << "Found the node " << node << endl;
return true; return true;
} }
} }
@ -273,7 +325,8 @@ FGTowerController::FGTowerController() :
// //
void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition, void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
double lat, double lon, double heading, double lat, double lon, double heading,
double speed, double alt, double radius, int leg) double speed, double alt, double radius, int leg,
string callsign)
{ {
TrafficVectorIterator i = activeTraffic.begin(); TrafficVectorIterator i = activeTraffic.begin();
// Search whether the current id alread has an entry // Search whether the current id alread has an entry
@ -295,6 +348,7 @@ void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute,
rec.setPositionAndHeading(lat, lon, heading, speed, alt); rec.setPositionAndHeading(lat, lon, heading, speed, alt);
rec.setRunway(intendedRoute->getRunway()); rec.setRunway(intendedRoute->getRunway());
rec.setLeg(leg); rec.setLeg(leg);
rec.setCallSign(callsign);
activeTraffic.push_back(rec); activeTraffic.push_back(rec);
} else { } else {
i->setPositionAndHeading(lat, lon, heading, speed, alt); i->setPositionAndHeading(lat, lon, heading, speed, alt);

View file

@ -101,7 +101,8 @@ public:
virtual ~FGATCController() {}; virtual ~FGATCController() {};
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon, double lat, double lon,
double hdg, double spd, double alt, double radius, int leg) = 0; double hdg, double spd, double alt, double radius, int leg,
string callsign) = 0;
virtual void signOff(int id) = 0; virtual void signOff(int id) = 0;
virtual void update(int id, double lat, double lon, virtual void update(int id, double lat, double lon,
double heading, double speed, double alt, double dt) = 0; double heading, double speed, double alt, double dt) = 0;
@ -126,6 +127,7 @@ private:
FGATCInstruction instruction; FGATCInstruction instruction;
double latitude, longitude, heading, speed, altitude, radius; double latitude, longitude, heading, speed, altitude, radius;
string runway; string runway;
string callsign;
public: public:
@ -144,6 +146,8 @@ public:
int crosses (FGGroundNetwork *, FGTrafficRecord &other); int crosses (FGGroundNetwork *, FGTrafficRecord &other);
bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node); bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node);
bool onRoute(FGGroundNetwork *, FGTrafficRecord &other);
bool getSpeedAdjustment() { return instruction.getChangeSpeed(); }; bool getSpeedAdjustment() { return instruction.getChangeSpeed(); };
double getLatitude () { return latitude ; }; double getLatitude () { return latitude ; };
@ -167,6 +171,8 @@ public:
void setWaitsForId(int id) { waitsForId = id; }; void setWaitsForId(int id) { waitsForId = id; };
string getRunway() { return runway; }; string getRunway() { return runway; };
void setCallSign(string clsgn) { callsign = clsgn; };
string getCallSign() { return callsign; };
}; };
@ -206,7 +212,8 @@ public:
virtual ~FGTowerController() {}; virtual ~FGTowerController() {};
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon, double lat, double lon,
double hdg, double spd, double alt, double radius, int leg); double hdg, double spd, double alt, double radius, int leg,
string callsign);
virtual void signOff(int id); virtual void signOff(int id);
virtual void update(int id, double lat, double lon, virtual void update(int id, double lat, double lon,
double heading, double speed, double alt, double dt); double heading, double speed, double alt, double dt);

View file

@ -77,6 +77,7 @@ SG_USING_STD(sort);
FGTrafficManager::FGTrafficManager() FGTrafficManager::FGTrafficManager()
{ {
score = 0; score = 0;
runCount = 0;
} }
FGTrafficManager:: ~FGTrafficManager() FGTrafficManager:: ~FGTrafficManager()
@ -121,6 +122,11 @@ void FGTrafficManager::init()
void FGTrafficManager::update(double something) void FGTrafficManager::update(double something)
{ {
if (runCount < 1000)
{
runCount++;
return;
}
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if (scheduledAircraft.size() == 0) if (scheduledAircraft.size() == 0)
return; return;

View file

@ -49,7 +49,7 @@ private:
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime, port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
repeat, acType, airline, m_class, flighttype; repeat, acType, airline, m_class, flighttype;
int cruiseAlt; int cruiseAlt;
int score; int score, runCount;
double radius, offset; double radius, offset;
bool heavy; bool heavy;