- Fixed a bug in AI aircraft ground steering code: When aircraft were not moving, the value of headingchangeRate kept increasing to insane levels. Although this was clamped to a maximum of 30 degrees per second, the initial rate could still push the aircraft in the wrong direction. In practice, this bug would be visible when an AI aicraft would be pushed back, when it tended to veer to the right.
- Make sure that the aircraft slows down well ahead of the pushback point. This change ensures that the AC will actually reach the pushback point. It also ensures a slightly tighter steering range.
- AI ground steering rate is tuned to 30 degrees per second at a nominal taxispeed of 15. I now modulate the heading adjustment rate by manipulating the adjustment using a non-linear function (the sqrt). This allows for a slightly tighter turn radius at speeds < 15 and slightly looser turns at speeds > 15.
- The AI Flightplan generation code can return false. This can be used to determine whether any additional AI aircraft may be created. Currently, the function returns false when no more parkings are available. This should limit the build-up of huge AIAircraft tower stacks.
- The ground network can now graphically display all aircraft actitivy on the ground network by using a virtual marker system.
-// FGAIAircraft - FGAIBase-derived class creates an AI airplane
+// // FGAIAircraft - FGAIBase-derived class creates an AI airplane
//
// Written by David Culp, started October 2003.
//
if (! leadPointReached(curr)) {
controlHeading(curr);
controlSpeed(curr, next);
+ if (speed < 0) {
+ cerr << getCallSign()
+ << ": verifying lead distance to waypoint : "
+ << fp->getCurrentWaypoint()->name << " "
+ << fp->getLeadDistance() << ". Distance to go "
+ << (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr))
+ << ". Target speed = "
+ << tgt_speed
+ << ". Current speed = "
+ << speed
+ << ". Minimum Bearing " << minBearing
+ << endl;
+ }
} else {
if (curr->finished) //end of the flight plan
{
//cerr << "2" << endl;
double lead_dist = fp->getLeadDistance();
// experimental: Use fabs, because speed can be negative (I hope) during push_back.
-
+ if ((dist_to_go < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->name == string("PushBackPoint")) {
+ tgt_speed = -(dist_to_go / 10.0);
+ if (tgt_speed > -0.5) {
+ tgt_speed = -0.5;
+ }
+ if (fp->getPreviousWaypoint()->speed < tgt_speed) {
+ fp->getPreviousWaypoint()->speed = tgt_speed;
+ }
+ }
if (lead_dist < fabs(2*speed)) {
//don't skip over the waypoint
lead_dist = fabs(2*speed);
bank_sense = 1.0;
}
//if (trafficRef)
- //cerr << trafficRef->getCallSign() << " Heading "
- // << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
+ // cerr << trafficRef->getCallSign() << " Heading "
+ // << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
//if (headingDiff > 60) {
groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
//groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180);
//}
if (sign(groundTargetSpeed) != sign(tgt_speed))
groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
-
- if (headingDiff > 30.0) {
- // invert if pushed backward
- headingChangeRate += 10.0 * dt * sign(roll);
-
- // Clamp the maximum steering rate to 30 degrees per second,
- // But only do this when the heading error is decreasing.
- if ((headingDiff < headingError)) {
- if (headingChangeRate > 30)
- headingChangeRate = 30;
- else if (headingChangeRate < -30)
- headingChangeRate = -30;
+
+ // Only update the target values when we're not moving because otherwise we might introduce an enormous target change rate while waiting a the gate, or holding.
+ if (speed != 0) {
+ if (headingDiff > 30.0) {
+ // invert if pushed backward
+ headingChangeRate += 10.0 * dt * sign(roll);
+
+ // Clamp the maximum steering rate to 30 degrees per second,
+ // But only do this when the heading error is decreasing.
+ if ((headingDiff < headingError)) {
+ if (headingChangeRate > 30)
+ headingChangeRate = 30;
+ else if (headingChangeRate < -30)
+ headingChangeRate = -30;
+ }
+ } else {
+ if (speed != 0) {
+ if (fabs(headingChangeRate) > headingDiff)
+ headingChangeRate = headingDiff*sign(roll);
+ else
+ headingChangeRate += dt * sign(roll);
+ }
}
- } else {
- if (fabs(headingChangeRate) > headingDiff)
- headingChangeRate = headingDiff*sign(roll);
- else
- headingChangeRate += dt * sign(roll);
}
-
- hdg += headingChangeRate * dt * (fabs(speed) / 15);
+ if (trafficRef)
+ cerr << trafficRef->getCallSign() << " Heading "
+ << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << "Heading change rate : " << headingChangeRate << " bacnk sence " << bank_sense << endl;
+ hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15);
headingError = headingDiff;
} else {
if (fabs(speed) > 1.0) {
-// FGAIFlightPlan - class for loading and storing AI flight plans
+// // FGAIFlightPlan - class for loading and storing AI flight plans
// Written by David Culp, started May 2004
// - davidculp2@comcast.net
//
{
sid = 0;
wpt_iterator = waypoints.begin();
+ isValid = true;
}
FGAIFlightPlan::FGAIFlightPlan(const string& filename)
}
wpt_iterator = waypoints.begin();
+ isValid = true;
//cout << waypoints.size() << " waypoints read." << endl;
}
path.append( p );
SGPropertyNode root;
-
+ isValid = true;
// This is a bit of a hack:
// Normally the value of course will be used to evaluate whether
// or not a waypoint will be used for midair initialization of
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
wpt_iterator = waypoints.begin();
bool dist = 0;
- create(ac, dep,arr, leg, alt, speed, lat, lon,
+ isValid = create(ac, dep,arr, leg, alt, speed, lat, lon,
firstLeg, radius, fltType, acType, airline, dist);
wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl;
time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; }
- void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
+ bool create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
- void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
- void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
+ bool createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
+ bool createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
void setLeg(int val) { leg = val;}
void setTime(time_t st) { start_time = st; }
std::string activeRunway;
FGTaxiRoute *taxiRoute;
std::string name;
+ bool isValid;
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
- void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
- void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
- void createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
- void createLanding(FGAIAircraft *, FGAirport *, const std::string&);
- void createParking(FGAIAircraft *, FGAirport *, double radius);
+ bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
+ bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
+ bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
+ bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
+ bool createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints();
void resetWaypoints();
- void createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
+ bool createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
- void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
+ bool createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
double getTurnRadius(double, bool);
public:
wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };
-
+ bool isValidPlan() { return isValid; };
};
#endif // _FG_AIFLIGHTPLAN_HXX
// Check lat/lon values during initialization;
-void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
+bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
FGAirport * arr, int legNr, double alt,
double speed, double latitude,
double longitude, bool firstFlight,
const string & aircraftType,
const string & airline, double distance)
{
+ bool retVal = true;
int currWpt = wpt_iterator - waypoints.begin();
switch (legNr) {
case 1:
- createPushBack(ac, firstFlight, dep, latitude, longitude,
- radius, fltType, aircraftType, airline);
+ retVal = createPushBack(ac, firstFlight, dep, latitude, longitude,
+ radius, fltType, aircraftType, airline);
break;
case 2:
- createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
+ retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
aircraftType, airline);
break;
case 3:
- createTakeOff(ac, firstFlight, dep, speed, fltType);
+ retVal = createTakeOff(ac, firstFlight, dep, speed, fltType);
break;
case 4:
- createClimb(ac, firstFlight, dep, speed, alt, fltType);
+ retVal = createClimb(ac, firstFlight, dep, speed, alt, fltType);
break;
case 5:
- createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
+ retVal = createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
alt, fltType);
break;
case 6:
- createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
+ retVal = createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
distance);
break;
case 7:
- createLanding(ac, arr, fltType);
+ retVal = createLanding(ac, arr, fltType);
break;
case 8:
- createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
+ retVal = createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
break;
case 9:
- createParking(ac, arr, radius);
+ retVal = createParking(ac, arr, radius);
break;
default:
//exit(1);
}
wpt_iterator = waypoints.begin() + currWpt;
leg++;
+ return retVal;
}
FGAIFlightPlan::waypoint *
waypoints.push_back(wpt);
}
-void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt,
double radius,
const string & fltType,
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
if (!gn->exists()) {
createDefaultTakeoffTaxi(ac, apt, rwy);
- return;
+ return true;
}
intVec ids;
if (taxiRoute->empty()) {
createDefaultTakeoffTaxi(ac, apt, rwy);
- return;
+ return true;
}
taxiRoute->first();
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
+ return true;
}
void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
waypoints.push_back(wpt);
}
-void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
double radius,
const string & fltType,
const string & acType,
// Find a route from runway end to parking/gate.
if (!gn->exists()) {
createDefaultLandingTaxi(ac, apt);
- return;
+ return true;
}
intVec ids;
if (taxiRoute->empty()) {
createDefaultLandingTaxi(ac, apt);
- return;
+ return true;
}
int node;
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
+ return true;
}
/*******************************************************************
* more likely however.
*
******************************************************************/
-void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed,
const string & fltType)
{
wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
wpt->altitude = airportElev + 5000;
waypoints.push_back(wpt);
+ return true;
}
/*******************************************************************
* CreateClimb
* initialize the Aircraft at the parking location
******************************************************************/
-void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed, double alt,
const string & fltType)
{
wpt->altitude = 18000;
waypoints.push_back(wpt);
}
+ return true;
}
* Generate a flight path from the last waypoint of the cruise to
* the permission to land point
******************************************************************/
-void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
double latitude, double longitude,
double speed, double alt,
const string & fltType,
//cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl;
ac->resetPositionFromFlightPlan();
}
-
-
+ return true;
}
/*******************************************************************
hardcoded at 5000 meters from the threshold) to the threshold, at
a standard glide slope angle of 3 degrees.
******************************************************************/
-void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
const string & fltType)
{
double vTouchdown = ac->getPerformance()->vTouchdown();
wpt->crossat = apt->getElevation();
waypoints.push_back(wpt);
*/
+ return true;
}
/*******************************************************************
* CreateParking
* initialize the Aircraft at the parking location
******************************************************************/
-void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
double radius)
{
waypoint *wpt;
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev,
vTaxiReduced);
waypoints.push_back(wpt);
+ return true;
}
/**
* Note that this is the original version that does not
* do any dynamic route computation.
******************************************************************/
-void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
+bool FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
FGAirport *arr, double latitude,
double longitude, double speed,
double alt, const string& fltType)
// TODO: Use James Turner's createOnGround functions.
-void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
+bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
bool firstFlight, FGAirport *dep,
double latitude,
double longitude,
" of flight type " << fltType <<
" of airline " << airline <<
" at airport " << dep->getId());
+ return false;
char buffer[10];
snprintf (buffer, 10, "%d", gateId);
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
if (gateId < 0) {
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
radius, fltType, aircraftType, airline);
- return;
+ return true;
}
//cerr << "getting parking " << gateId;
}
}
+ return true;
}
/*******************************************************************
* createPushBackFallBack
//dialog.init();
- osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
- cerr << "Adding groundnetWork to the scenegraph" << endl;
- globals->get_scenery()->get_scene_graph()->addChild(node);
+ //osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
+ //cerr << "Adding groundnetWork to the scenegraph::init" << endl;
+ //globals->get_scenery()->get_scene_graph()->addChild(node);
}
}
double speed = fgGetDouble("/velocities/groundspeed-kt");
double altitude = fgGetDouble("/position/altitude-ft");
- cerr << "Running FGATCManager::update()" << endl;
+ //cerr << "Running FGATCManager::update()" << endl;
controller->updateAircraftInformation(ai_ac.getID(),
latitude,
longitude,
speed,
altitude, time);
}
- /*string airport = fgGetString("/sim/presets/airport-id");
+ string airport = fgGetString("/sim/presets/airport-id");
FGAirport *apt = FGAirport::findByIdent(airport);
osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
- cerr << "Adding groundnetWork to the scenegraph" << endl;
+ //cerr << "Adding groundnetWork to the scenegraph::update" << endl;
+
globals->get_scenery()->get_scene_graph()->addChild(node);
-*/
}
// In essence, we should check whether the pusbback route itself, as well as the associcated
// taxiways near the pushback point are free of traffic.
// To do so, we need to
+ return true;
}
void allowRepeatedTransmissions () { allowTransmission=true; };
void nextFrequency() { frequencyId++; };
int getNextFrequency() { return frequencyId; };
+ intVec& getIntentions() { return intentions; };
+ int getCurrentPosition() { return currentPos; };
};
typedef vector<FGTrafficRecord> TrafficVector;
+
// groundnet.cxx - Implimentation of the FlightGear airport ground handling code
//
// Written by Durk Talsma, started June 2005.
#include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/material/mat.hxx>
#include <Airports/simple.hxx>
#include <Airports/dynamics.hxx>
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
+#include <Scenery/scenery.hxx>
+
#include "groundnetwork.hxx"
/***************************************************************************
SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length);
double coveredDistance = length * 0.5;
SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2);
- cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+ //cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
}
//maxDepth = 1000;
count = 0;
currTraffic = activeTraffic.begin();
+ group = 0;
}
+
osg::Node* FGGroundNetwork::getRenderNode()
{
- osg::Group* group = new osg::Group;
- for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
- osg::Matrix obj_pos;
- osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
- obj_trans->setDataVariance(osg::Object::STATIC);
- WorldCoordinate( obj_pos, (*i)->getLatitude(), (*i)->getLongitude(), parent->elevation()+10, -((*i)->getHeading()) );
+ SGMaterialLib *matlib = globals->get_matlib();
+ if (group) {
+ //int nr = ;
+ globals->get_scenery()->get_scene_graph()->removeChild(group);
+ //while (group->getNumChildren()) {
+ // cerr << "Number of children: " << group->getNumChildren() << endl;
+ simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
+ //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+ //geode->releaseGLObjects();
+ //group->removeChild(geode);
+ //delete geode;
+ }
+ group = new osg::Group;
+
+ //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
+ double dx = 0;
+ for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ // Handle start point
+ int pos = i->getCurrentPosition() - 1;
+ if (pos >= 0) {
+
+ SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+ SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
+
+ double length = SGGeodesy::distanceM(start, end);
+ //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+
+ double az2, heading; //, distanceM;
+ SGGeodesy::inverse(start, end, heading, az2, length);
+ double coveredDistance = length * 0.5;
+ SGGeod center;
+ SGGeodesy::direct(start, heading, coveredDistance, center, az2);
+ //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+ ///////////////////////////////////////////////////////////////////////////////
+ // Make a helper function out of this
+ osg::Matrix obj_pos;
+ osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+ obj_trans->setDataVariance(osg::Object::STATIC);
+
+ WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), parent->elevation()+8+dx, -(heading) );
+
+ obj_trans->setMatrix( obj_pos );
+ //osg::Vec3 center(0, 0, 0)
+
+ float width = length /2.0;
+ osg::Vec3 corner(-width, 0, 0.25f);
+ osg::Vec3 widthVec(2*width + 1, 0, 0);
+ osg::Vec3 heightVec(0, 1, 0);
+ osg::Geometry* geometry;
+ geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+ simgear::EffectGeode* geode = new simgear::EffectGeode;
+ geode->setName("test");
+ geode->addDrawable(geometry);
+ //osg::Node *custom_obj;
+ SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ if (mat)
+ geode->setEffect(mat->get_effect());
+ obj_trans->addChild(geode);
+ // wire as much of the scene graph together as we can
+ //->addChild( obj_trans );
+ group->addChild( obj_trans );
+ /////////////////////////////////////////////////////////////////////
+ } else {
+ cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
+ }
+ for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+ osg::Matrix obj_pos;
+ int k = (*j)-1;
+ if (k >= 0) {
+ osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+ obj_trans->setDataVariance(osg::Object::STATIC);
+
+ WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), parent->elevation()+8+dx, -(segments[k]->getHeading()) );
obj_trans->setMatrix( obj_pos );
- //osg::Vec3 center(0, 0, 0)
-
- float width = (*i)->getLength() /2.0;
- osg::Vec3 corner(-width, 0, 0.25f);
- osg::Vec3 widthVec(2*width + 1, 0, 0);
- osg::Vec3 heightVec(0, 0, 1);
- osg::Geometry* geometry;
- geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
- simgear::EffectGeode* geode = new simgear::EffectGeode;
- geode->setName("test");
- geode->addDrawable(geometry);
- //osg::Node *custom_obj;
-
- obj_trans->addChild(geode);
- // wire as much of the scene graph together as we can
- //->addChild( obj_trans );
- group->addChild( obj_trans );
+ //osg::Vec3 center(0, 0, 0)
+
+ float width = segments[k]->getLength() /2.0;
+ osg::Vec3 corner(-width, 0, 0.25f);
+ osg::Vec3 widthVec(2*width + 1, 0, 0);
+ osg::Vec3 heightVec(0, 1, 0);
+ osg::Geometry* geometry;
+ geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+ simgear::EffectGeode* geode = new simgear::EffectGeode;
+ geode->setName("test");
+ geode->addDrawable(geometry);
+ //osg::Node *custom_obj;
+ SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ if (mat)
+ geode->setEffect(mat->get_effect());
+ obj_trans->addChild(geode);
+ // wire as much of the scene graph together as we can
+ //->addChild( obj_trans );
+ group->addChild( obj_trans );
+ }
+ }
+ dx += 0.1;
}
#ifndef _GROUNDNETWORK_HXX_
#define _GROUNDNETWORK_HXX_
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/MatrixTransform>
+#include <osg/Shape>
+
+
#include <simgear/compiler.h>
#include <simgear/route/waypoint.hxx>
#include "parking.hxx"
#include <ATC/trafficcontrol.hxx>
+
class FGTaxiSegment; // forward reference
class FGAIFlightPlan; // forward reference
class FGAirport; // forward reference
void checkHoldPosition(int id, double lat, double lon,
double heading, double speed, double alt);
+ osg::Group* group;
+
public:
FGGroundNetwork();
~FGGroundNetwork();
radius = 0;
groundOffset = 0;
distanceToUser = 0;
+ valid = true;
//score = 0;
}
runCount = 0;
hits = 0;
initialized = false;
+ valid = true;
}
FGAISchedule::FGAISchedule(const FGAISchedule &other)
runCount = other.runCount;
hits = other.hits;
initialized = other.initialized;
+ valid = other.valid;
}
elapsedTimeEnroute,
remainingTimeEnroute,
deptime = 0;
-
+ if (!valid) {
+ return false;
+ }
scheduleFlights();
if (flights.empty()) { // No flights available for this aircraft
+ valid = false;
return false;
}
firstRun = false;
}
- FGScheduledFlight* flight = flights.front();
+ FGScheduledFlight* flight = flights.front();
if (!deptime) {
deptime = flight->getDepartureTime();
//cerr << "Settiing departure time " << deptime << endl;
aircraft->setBank(0);
courseToDest = SGGeodesy::courseDeg(position, arr->geod());
- aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime,
- dep, arr, true, radius,
- flight->getCruiseAlt()*100,
- position.getLatitudeDeg(),
- position.getLongitudeDeg(),
- speedKnots, flightType, acType,
- airline));
-
-
- FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
- aimgr->attach(aircraft);
- AIManagerRef = aircraft->getID();
- return true;
+ FGAIFlightPlan *fp = new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime,
+ dep, arr, true, radius,
+ flight->getCruiseAlt()*100,
+ position.getLatitudeDeg(),
+ position.getLongitudeDeg(),
+ speedKnots, flightType, acType,
+ airline);
+ if (fp->isValidPlan()) {
+ aircraft->SetFlightPlan(fp);
+ FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
+ aimgr->attach(aircraft);
+ AIManagerRef = aircraft->getID();
+ return true;
+ } else {
+ delete aircraft;
+ delete fp;
+ //hand back the flights that had already been scheduled
+ while (!flights.empty()) {
+ flights.front()->release();
+ flights.erase(flights.begin());
+ }
+ return false;
+ }
}
// Create an initial heading for user controlled aircraft.
bool firstRun;
double courseToDest;
bool initialized;
+ bool valid;
void scheduleFlights();
// used to sort in decending order of score: I've probably found a better way to
// decending order sorting, but still need to test that.
bool operator< (const FGAISchedule &other) const { return (score > other.score); };
+ void taint() { valid = false; };
//void * getAiRef () { return AIManagerRef; };
//FGAISchedule* getAddress () { return this;};
}
//cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
if (!((*currAircraft)->update(now, userCart))) {
+ (*currAircraft)->taint();
// NOTE: With traffic manager II, this statement below is no longer true
// after proper initialization, we shouldnt get here.
// But let's make sure