const string & acType,
const string & airline)
{
-
+ int route;
// If this function is called during initialization,
// make sure we obtain a valid gate ID first
// and place the model at the location of the gate.
if (node == -1) {
node = park->guid();
} else if (node == 0) {
- // HAndle case where parking doens't have a node
+ // Handle case where parking doesn't have a node
if (firstFlight) {
node = park->guid();
} else {
// 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);
+ taxiRoute.next(&node, &route);
}
gate.release(); // free up our gate as required
} else {
if (taxiRoute.size() > 1) {
- taxiRoute.next(&node); // chop off the first waypoint, because that is already the last of the pushback route
+ taxiRoute.next(&node, &route); // chop off the first waypoint, because that is already the last of the pushback route
}
}
// push each node on the taxi route as a waypoint
- // int route;
+
//cerr << "Building taxi route" << endl;
- while (taxiRoute.next(&node)) {
+
+ // 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)) {
char buffer[10];
snprintf(buffer, 10, "%lld", (long long int) node);
FGTaxiNode *tn =
FGAIWaypoint *wpt =
createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
- // wpt->setRouteIndex(route);
+ wpt->setRouteIndex(route);
//cerr << "Nodes left " << taxiRoute->nodesLeft() << " ";
if (taxiRoute.nodesLeft() == 1) {
// Note that we actually have hold points in the ground network, but this is just an initial test.
const string & acType,
const string & airline)
{
+ int route;
gate = apt->getDynamics()->getAvailableParking(radius, fltType,
acType, airline);
// those are created by createParking()
// int route;
for (int i = 0; i < size - 2; i++) {
- taxiRoute.next(&node);
+ taxiRoute.next(&node, &route);
char buffer[10];
snprintf(buffer, 10, "%lld", (long long int) node);
FGTaxiNode *tn = gn->findNode(node);
FGAIWaypoint *wpt =
createOnGround(ac, buffer, tn->geod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
- // wpt->setRouteIndex(route);
+
+ wpt->setRouteIndex(route);
pushBackWaypoint(wpt);
}
return true;
double vTaxi = ac->getPerformance()->vTaxi();
double vTaxiBackward = vTaxi * (-2.0/3.0);
double vTaxiReduced = vTaxi * (2.0/3.0);
+
// Active runway can be conditionally set by ATC, so at the start of a new flight, this
// must be reset.
activeRunway.clear();
}
route.first();
- PositionedID node, previous= 0;
+ PositionedID node;
+ int rte;
- while (route.next(&node))
+ 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);
-
+
+ /*
if (previous) {
FGTaxiSegment* segment = groundNet->findSegment(previous, node);
wpt->setRouteIndex(segment->getIndex());
// not on the route yet, make up a unique segment ID
int x = (int) tn->guid();
wpt->setRouteIndex(x);
- }
-
+ }*/
+
+ wpt->setRouteIndex(rte);
pushBackWaypoint(wpt);
- previous = node;
+ //previous = node;
}
// some special considerations for the last point:
waypoints.back()->setName(string("PushBackPoint"));
ballist->setXoffset(sm->x_offset);
ballist->setYoffset(sm->y_offset);
ballist->setZoffset(sm->z_offset);
- ballist->setPitchoffset(sm->pitch_offset);
- ballist->setYawoffset(sm->yaw_offset);
+ ballist->setPitchoffset(sm->pitch_offset->get_value());
+ ballist->setYawoffset(sm->yaw_offset->get_value());
ballist->setParentNodes(_selected_ac);
ballist->setContentsNode(sm->contents_node);
ballist->setWeight(sm->weight);
if (sm->speed_node != 0)
sm->speed = sm->speed_node->getDoubleValue();
+ double yaw_offset = sm->yaw_offset->get_value();
+ double pitch_offset = sm->pitch_offset->get_value();
//cout << " name " << name << " id " << id << " sub id" << sub_id << endl;
// Get submodel initial velocity vector angles in XZ and XY planes.
// This vector should be added to aircraft's vector.
- IC.elevation += (sm->yaw_offset * sinRx) + (sm->pitch_offset * cosRx);
- IC.azimuth += (sm->yaw_offset * cosRx) - (sm->pitch_offset * sinRx);
+ IC.elevation += (yaw_offset * sinRx) + (pitch_offset * cosRx);
+ IC.azimuth += (yaw_offset * cosRx) - (pitch_offset * sinRx);
// calculate the total speed north
IC.total_speed_north = sm->speed * cos(IC.elevation * SG_DEGREES_TO_RADIANS)
sm->x_offset = entry_node->getDoubleValue("x-offset", 0.0);
sm->y_offset = entry_node->getDoubleValue("y-offset", 0.0);
sm->z_offset = entry_node->getDoubleValue("z-offset", 0.0);
- sm->yaw_offset = entry_node->getDoubleValue("yaw-offset", 0.0);
- sm->pitch_offset = entry_node->getDoubleValue("pitch-offset", 0.0);
sm->drag_area = entry_node->getDoubleValue("eda", 0.034);
sm->life = entry_node->getDoubleValue("life", 900.0);
sm->buoyancy = entry_node->getDoubleValue("buoyancy", 0);
sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
+ SGPropertyNode_ptr prop_root = fgGetNode("/", true);
+ SGPropertyNode n;
+
+ SGPropertyNode_ptr a = entry_node->getNode("yaw-offset");
+ sm->yaw_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+
+ a = entry_node->getNode("pitch-offset");
+ sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+
if (sm->contents_node != 0)
sm->contents = sm->contents_node->getDoubleValue();
sm->x_offset = entry_node->getDoubleValue("x-offset", 0.0);
sm->y_offset = entry_node->getDoubleValue("y-offset", 0.0);
sm->z_offset = entry_node->getDoubleValue("z-offset", 0.0);
- sm->yaw_offset = entry_node->getDoubleValue("yaw-offset", 0.0);
- sm->pitch_offset = entry_node->getDoubleValue("pitch-offset", 0.0);
sm->drag_area = entry_node->getDoubleValue("eda", 0.034);
sm->life = entry_node->getDoubleValue("life", 900.0);
sm->buoyancy = entry_node->getDoubleValue("buoyancy", 0);
sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
+ SGPropertyNode_ptr prop_root = fgGetNode("/", true);
+ SGPropertyNode n;
+
+ SGPropertyNode_ptr a = entry_node->getNode("yaw-offset");
+ sm->yaw_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+
+ a = entry_node->getNode("pitch-offset");
+ sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n );
+
if (sm->contents_node != 0)
sm->contents = sm->contents_node->getDoubleValue();
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/SGMath.hxx>
+#include <Autopilot/inputvalue.hxx>
+
#include <vector>
#include <string>
double x_offset;
double y_offset;
double z_offset;
- double yaw_offset;
- double pitch_offset;
+ FGXMLAutopilot::InputValue_ptr yaw_offset;
+ FGXMLAutopilot::InputValue_ptr pitch_offset;
double drag_area;
double life;
double buoyancy;
}
FGATCManager::~FGATCManager() {
-
+ delete pk;
}
void FGATCManager::init() {
FGAirport *apt = FGAirport::findByIdent(airport);
if (apt && onGround) {// && !runway.empty()) {
FGAirportDynamics* dcs = apt->getDynamics();
- ParkingAssignment pk(dcs->getParkingByName(parking));
+ pk = new ParkingAssignment(dcs->getParkingByName(parking));
// No valid parking location, so either at the runway or at a random location.
- if (pk.isValid()) {
+ if (pk->isValid()) {
+ dcs->setParkingAvailable(pk->parking()->guid(), false);
fp = new FGAIFlightPlan;
controller = apt->getDynamics()->getStartupController();
int stationFreq = apt->getDynamics()->getGroundFrequency(1);
leg = 1;
//double, lat, lon, head; // Unused variables;
//int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head);
- aircraftRadius = pk.parking()->getRadius();
- string fltType = pk.parking()->getType(); // gate / ramp, ga, etc etc.
+ aircraftRadius = pk->parking()->getRadius();
+ string fltType = pk->parking()->getType(); // gate / ramp, ga, etc etc.
string aircraftType; // Unused.
string airline; // Currently used for gate selection, but a fallback mechanism will apply when not specified.
- fp->setGate(pk);
+ fp->setGate(*pk);
if (!(fp->createPushBack(&ai_ac,
false,
apt,
//cerr << "Shutting down the atc_mgr" << endl;
return;
}
- //cerr << "Size of waypoint cue " << size << " ";
- //for (int i = 0; i < size; i++) {
- // int val = fp->getRouteIndex(i);
- //cerr << fp->getWayPoint(i)->getName() << " ";
+ // Test code: Print how far we're progressing along the taxi route.
+ //std::cerr << "Size of waypoint cue " << size << " ";
+ for (int i = 0; i < size; i++) {
+ int val = fp->getRouteIndex(i);
+ //std::cerr << fp->getWayPoint(i)->getName() << " ";
//if ((val) && (val != pos)) {
- //intentions.push_back(val);
- //cerr << "[done ] " << endl;
+ // intentions.push_back(val);
+ // std::cerr << "[done ] " << std::endl;
//}
- //}
- //cerr << "[done ] " << endl;
+ }
+ //std::cerr << "[done ] " << std::endl;
}
if (fp) {
//cerr << "Currently at leg : " << fp->getLeg() << endl;
bool networkVisible;
bool initSucceeded;
SGPropertyNode_ptr trans_num;
+ ParkingAssignment *pk;
public:
FGATCManager();
static SGPropertyNode *getNamedNode(SGPropertyNode *prop, const char *name)
{
- SGPropertyNode* p;
-
- for (int i = 0; i < prop->nChildren(); i++)
- if ((p = getNamedNode(prop->getChild(i), name)))
- return p;
-
- if (!strcmp(prop->getStringValue("name"), name))
- return prop;
- return 0;
+ SGPropertyNode* p;
+
+ for (int i = 0; i < prop->nChildren(); i++)
+ if ((p = getNamedNode(prop->getChild(i), name)))
+ return p;
+
+ if (!strcmp(prop->getStringValue("name"), name))
+ return prop;
+ return 0;
}
static void atcUppercase(string &s) {
- for(unsigned int i=0; i<s.size(); ++i) {
- s[i] = toupper(s[i]);
- }
+ for(unsigned int i=0; i<s.size(); ++i) {
+ s[i] = toupper(s[i]);
+ }
}
class AirportsWithATC : public FGAirport::AirportFilter
{
public:
- virtual FGPositioned::Type maxType() const {
- return FGPositioned::SEAPORT;
- }
-
- virtual bool passAirport(FGAirport* aApt) const
- {
- return (!aApt->commStations().empty());
- }
+ virtual FGPositioned::Type maxType() const {
+ return FGPositioned::SEAPORT;
+ }
+
+ virtual bool passAirport(FGAirport* aApt) const
+ {
+ return (!aApt->commStations().empty());
+ }
};
void FGATCDialogNew::frequencySearch()
{
- const char *dialog_name = "atc-freq-search";
- SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
- if (!dlg)
- return;
-
- _gui->closeDialog(dialog_name);
-
- SGPropertyNode_ptr button_group = getNamedNode(dlg, "quick-buttons");
- // remove all dynamic airport/ATC buttons
- button_group->removeChildren("button");
-
- AirportsWithATC filt;
- FGPositionedList results = FGPositioned::findWithinRange(globals->get_aircraft_position(), 50.0, &filt);
- FGPositioned::sortByRange(results, globals->get_aircraft_position());
- for (unsigned int r=0; (r<results.size()) && (r < 6); ++r) {
-
- SGPropertyNode *entry = button_group->getNode("button", r, true);
- copyProperties(button_group->getNode("button-template", true), entry);
- entry->removeChildren("enabled");
- entry->setStringValue("legend", results[r]->ident());
- entry->setStringValue("binding[0]/icao", results[r]->ident());
- }
-
- // (un)hide message saying no things in range
- SGPropertyNode_ptr range_error = getNamedNode(dlg, "no-atc-in-range");
- range_error->setBoolValue("visible", !results.empty());
-
- _gui->showDialog(dialog_name);
+ const char *dialog_name = "atc-freq-search";
+ SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
+ if (!dlg)
+ return;
+
+ _gui->closeDialog(dialog_name);
+
+ SGPropertyNode_ptr button_group = getNamedNode(dlg, "quick-buttons");
+ // remove all dynamic airport/ATC buttons
+ button_group->removeChildren("button");
+
+ AirportsWithATC filt;
+ FGPositionedList results = FGPositioned::findWithinRange(globals->get_aircraft_position(), 50.0, &filt);
+ FGPositioned::sortByRange(results, globals->get_aircraft_position());
+ for (unsigned int r=0; (r<results.size()) && (r < 6); ++r) {
+
+ SGPropertyNode *entry = button_group->getNode("button", r, true);
+ copyProperties(button_group->getNode("button-template", true), entry);
+ entry->removeChildren("enabled");
+ entry->setStringValue("legend", results[r]->ident());
+ entry->setStringValue("binding[0]/icao", results[r]->ident());
+ }
+
+ // (un)hide message saying no things in range
+ SGPropertyNode_ptr range_error = getNamedNode(dlg, "no-atc-in-range");
+ range_error->setBoolValue("visible", !results.empty());
+
+ _gui->showDialog(dialog_name);
}
void FGATCDialogNew::frequencyDisplay(const std::string& ident)
{
- const char *dialog_name = "atc-freq-display";
- SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
- if (!dlg)
- return;
-
- _gui->closeDialog(dialog_name);
-
- SGPropertyNode_ptr freq_group = getNamedNode(dlg, "frequency-list");
- // remove all frequency entries
- freq_group->removeChildren("group");
-
- std::string uident(ident);
- atcUppercase(uident);
- string label;
-
- const FGAirport *a = fgFindAirportID(uident);
- if (!a) {
- label = "Airport " + ident + " not found in database.";
- mkDialog(label.c_str());
- return;
- }
-
- // set title
- label = uident + " Frequencies";
- dlg->setStringValue("text/label", label.c_str());
-
- const flightgear::CommStationList& comms(a->commStations());
- if (comms.empty()) {
- label = "No frequencies found for airport " + uident;
- mkDialog(label.c_str());
- return;
- }
-
- for (unsigned int c=0; c < comms.size(); ++c) {
- flightgear::CommStation* comm = comms[c];
-
- // add frequency line (modified copy of <group-template>)
- SGPropertyNode *entry = freq_group->getNode("group", c, true);
- copyProperties(freq_group->getNode("group-template", true), entry);
- entry->removeChildren("enabled");
-
- entry->setStringValue("text[0]/label", comm->ident());
-
- char buf[8];
- snprintf(buf, 8, "%.2f", comm->freqMHz());
- if(buf[5] == '3') buf[5] = '2';
- if(buf[5] == '8') buf[5] = '7';
- buf[7] = '\0';
-
- entry->setStringValue("text[1]/label", buf);
- }
-
- _gui->showDialog(dialog_name);
+ const char *dialog_name = "atc-freq-display";
+ SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
+ if (!dlg)
+ return;
+
+ _gui->closeDialog(dialog_name);
+
+ SGPropertyNode_ptr freq_group = getNamedNode(dlg, "frequency-list");
+ // remove all frequency entries
+ freq_group->removeChildren("group");
+
+ std::string uident(ident);
+ atcUppercase(uident);
+ string label;
+
+ const FGAirport *a = fgFindAirportID(uident);
+ if (!a) {
+ label = "Airport " + ident + " not found in database.";
+ mkDialog(label.c_str());
+ return;
+ }
+
+ // set title
+ label = uident + " Frequencies";
+ dlg->setStringValue("text/label", label.c_str());
+
+ const flightgear::CommStationList& comms(a->commStations());
+ if (comms.empty()) {
+ label = "No frequencies found for airport " + uident;
+ mkDialog(label.c_str());
+ return;
+ }
+
+ for (unsigned int c=0; c < comms.size(); ++c) {
+ flightgear::CommStation* comm = comms[c];
+
+ // add frequency line (modified copy of <group-template>)
+ SGPropertyNode *entry = freq_group->getNode("group", c, true);
+ copyProperties(freq_group->getNode("group-template", true), entry);
+ entry->removeChildren("enabled");
+
+ entry->setStringValue("text[0]/label", comm->ident());
+
+ char buf[8];
+ snprintf(buf, 8, "%.2f", comm->freqMHz());
+ if(buf[5] == '3') buf[5] = '2';
+ if(buf[5] == '8') buf[5] = '7';
+ buf[7] = '\0';
+
+ entry->setStringValue("text[1]/label", buf);
+ }
+
+ _gui->showDialog(dialog_name);
}
static bool doFrequencySearch( const SGPropertyNode* )
{
- FGATCDialogNew::instance()->frequencySearch();
- return true;
+ FGATCDialogNew::instance()->frequencySearch();
+ return true;
}
static bool doFrequencyDisplay( const SGPropertyNode* args )
{
- std::string icao = args->getStringValue("icao");
- if (icao.empty()) {
- icao = fgGetString("/sim/atc/freq-airport");
- }
-
- FGATCDialogNew::instance()->frequencyDisplay(icao);
- return true;
+ std::string icao = args->getStringValue("icao");
+ if (icao.empty()) {
+ icao = fgGetString("/sim/atc/freq-airport");
+ }
+
+ FGATCDialogNew::instance()->frequencyDisplay(icao);
+ return true;
}
FGATCDialogNew * FGATCDialogNew::_instance = NULL;
FGATCDialogNew::FGATCDialogNew()
-: _gui(NULL),
- dialogVisible(true)
+ : _gui(NULL),
+ dialogVisible(true)
{
}
// Add ATC-freq-search to the command list
globals->get_commands()->addCommand("ATC-freq-search", doFrequencySearch);
globals->get_commands()->addCommand("ATC-freq-display", doFrequencyDisplay);
-
+
// initialize properties polled in Update()
//globals->get_props()->setStringValue("/sim/atc/freq-airport", "");
globals->get_props()->setIntValue("/sim/atc/transmission-num", -1);
// Display the ATC popup dialog box with options relevant to the users current situation.
-//
+//
// So, the first thing we need to do is check the frequency that our pilot's nav radio
-// is currently tuned to. The dialog should always contain an option to to tune the
+// is currently tuned to. The dialog should always contain an option to to tune the
// to a particular frequency,
// Okay, let's see, according to my interpretation of David Luff's original code,
const char *dialog_name = "atc-dialog";
_gui = (NewGUI *)globals->get_subsystem("gui");
if (!_gui) {
- return;
+ return;
}
-
+
SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
if (!dlg)
return;
// loop over all entries that should fill up the dialog; use 10 items for now...
BOOST_FOREACH(const std::string& i, commands) {
snprintf(buf, bufsize, "/sim/atc/opt[%d]", commandNr);
- fgSetBool(buf, false);
+ fgSetBool(buf, false);
SGPropertyNode *entry = button_group->getNode("button", commandNr, true);
copyProperties(button_group->getNode("button-template", true), entry);
- entry->removeChildren("enabled");
- entry->setStringValue("property", buf);
- entry->setIntValue("keynum", '1' + commandNr);
- if (commandNr == 0)
- entry->setBoolValue("default", true);
-
- snprintf(buf, bufsize, "%d", 1 + commandNr);
- string legend = string(buf) + i; //"; // + current->menuentry;
- entry->setStringValue("legend", legend.c_str());
- entry->setIntValue("binding/value", commandNr);
+ entry->removeChildren("enabled");
+ entry->setStringValue("property", buf);
+ entry->setIntValue("keynum", '1' + commandNr);
+ if (commandNr == 0)
+ entry->setBoolValue("default", true);
+
+ snprintf(buf, bufsize, "%d", 1 + commandNr);
+ string legend = string(buf) + i; //"; // + current->menuentry;
+ entry->setStringValue("legend", legend.c_str());
+ entry->setIntValue("binding/value", commandNr);
commandNr++;
- //current++;
+ //current++;
}
if (dialogVisible) {
}
void FGTowerController::render(bool visible) {
- //cerr << "FGTowerController::render function not yet implemented" << endl;
+ //std::cerr << "FGTowerController::render function not yet implemented" << std::endl;
}
string FGTowerController::getName() {
void FGStartupController::render(bool visible)
{
-
+ //std::cerr << "Rendering startup controller" << std::endl;
SGMaterialLib *matlib = globals->get_matlib();
if (group) {
//int nr = ;
}
void FGApproachController::render(bool visible) {
- //cerr << "FGApproachController::render function not yet implemented" << endl;
+ std::cerr << "FGApproachController::render function not yet implemented" << std::endl;
}
/***************************************************************************
* FGTaxiRoute
**************************************************************************/
-bool FGTaxiRoute::next(PositionedID *nde)
+bool FGTaxiRoute::next(PositionedID *nde, int *rte)
{
+ if (nodes.size() != (routes.size()) + 1) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size());
+ throw sg_range_exception("Misconfigured taxi route");
+ }
if (currNode == nodes.end())
return false;
-
*nde = *(currNode);
-
+ if (currNode != nodes.begin()) {
+ *rte = *(currRoute);
+ currRoute++;
+ } else {
+ // Handle special case for the first node.
+ *rte = -1 * *(currRoute);
+ }
currNode++;
return true;
};
segment->setIndex(index++);
if (segment->oppositeDirection) {
- continue; // already establish
+ continue; // already established
}
FGTaxiSegment* opp = findSegment(segment->endNode, segment->startNode);
// assemble route from backtrace information
PositionedIDVec nodes;
+ intVec routes;
FGTaxiNode *bt = lastNode;
+
while (searchData[bt].previousNode != 0) {
nodes.push_back(bt->guid());
+ FGTaxiSegment *segment = findSegment(searchData[bt].previousNode->guid(), bt->guid());
+ int idx = segment->getIndex();
+ routes.push_back(idx);
bt = searchData[bt].previousNode;
+
}
nodes.push_back(start);
reverse(nodes.begin(), nodes.end());
- return FGTaxiRoute(nodes, searchData[lastNode].score, 0);
+ reverse(routes.begin(), routes.end());
+ return FGTaxiRoute(nodes, routes, searchData[lastNode].score, 0);
}
/* ATC Related Functions */
double radius, int leg,
FGAIAircraft * aircraft)
{
+
assert(parent);
+ init(parent);
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id alread has an entry
void FGGroundNetwork::render(bool visible)
{
-
SGMaterialLib *matlib = globals->get_matlib();
if (group) {
//int nr = ;
//for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
//double dx = 0;
for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
- // Handle start point
+ // Handle start point i.e. the segment that is connected to the aircraft itself on the starting end
+ // and to the the first "real" taxi segment on the other end.
int pos = i->getCurrentPosition() - 1;
if (pos >= 0) {
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;
+ //std::cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << std::endl;
///////////////////////////////////////////////////////////////////////////////
// Make a helper function out of this
osg::Matrix obj_pos;
group->addChild( obj_trans );
/////////////////////////////////////////////////////////////////////
} else {
- //cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
+ //std::cerr << "BIG FAT WARNING: current position is here : " << pos << std::endl;
}
+ // Next: Draw the other taxi segments.
for (intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
osg::Matrix obj_pos;
int k = (*j)-1;
{
private:
PositionedIDVec nodes;
+ intVec routes;
double distance;
PositionedIDVec::iterator currNode;
+ intVec::iterator currRoute;
public:
FGTaxiRoute() {
distance = 0;
currNode = nodes.begin();
+ currRoute = routes.begin();
};
- FGTaxiRoute(const PositionedIDVec& nds, double dist, int dpth) {
+ FGTaxiRoute(const PositionedIDVec& nds, intVec rts, double dist, int dpth) {
nodes = nds;
+ routes = rts;
distance = dist;
currNode = nodes.begin();
+ currRoute = routes.begin();
};
FGTaxiRoute& operator= (const FGTaxiRoute &other) {
nodes = other.nodes;
+ routes = other.routes;
distance = other.distance;
currNode = nodes.begin();
+ currRoute = routes.begin();
return *this;
};
FGTaxiRoute(const FGTaxiRoute& copy) :
nodes(copy.nodes),
+ routes(copy.routes),
distance(copy.distance),
- currNode(nodes.begin())
+ currNode(nodes.begin()),
+ currRoute(routes.begin())
{};
bool operator< (const FGTaxiRoute &other) const {
bool empty () {
return nodes.empty();
};
- bool next(PositionedID *nde);
+ bool next(PositionedID *nde, int *rte);
void first() {
currNode = nodes.begin();
+ currRoute = routes.begin();
};
int size() {
return nodes.size();
}
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
- if (!cache->isCachedFileModified(path) || cache->isReadOnly()) {
- return;
- }
+ //if (!cache->isCachedFileModified(path) || cache->isReadOnly()) {
+ // return;
+ //}
SG_LOG(SG_NAVAID, SG_INFO, "reading groundnet data from " << path);
SGTimeStamp t;
// Set current_options lon/lat given an airport id and parkig position name
static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& parkpos )
{
+ string fltType;
+ string acOperator;
+ string acType; // Currently not used by findAvailable parking, so safe to leave empty.
+ SGPath acData;
if ( id.empty() )
return false;
ParkingAssignment pka;
double radius = fgGetDouble("/sim/dimensions/radius-m");
if ((parkpos == string("AVAILABLE")) && (radius > 0)) {
- string fltType;
- string acOperator;
- SGPath acData;
+
try {
acData = globals->get_fg_home();
acData.append("aircraft-data");
acOperator = fgGetString("/sim/aircraft-operator" );
}
- string acType; // Currently not used by findAvailable parking, so safe to leave empty.
+
pka = dcs->getAvailableParking(radius, fltType, acType, acOperator);
if (pka.isValid()) {
+ // why is the following line necessary?
fgGetString("/sim/presets/parkpos");
fgSetString("/sim/presets/parkpos", pka.parking()->getName());
} else {
return false;
}
} else {
+
pka = dcs->getParkingByName(parkpos);
if (!pka.isValid()) {
SG_LOG( SG_GENERAL, SG_ALERT,
return false;
}
}
-
+ // Why is the following line necessary?
+ fgGetString("/sim/presets/parkpos");
+ fgSetString("/sim/presets/parkpos", pka.parking()->getName());
+ // The problem is, this line doesn't work because the ParkingAssignment's refcounting mechanism:
+ // 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);
fgApplyStartOffset(pka.parking()->geod(), pka.parking()->getHeading());
return true;
}
_device_name = fgGetNode("/sim/sound/device-name");
_currentView = fgGetNode("sim/current-view");
- _viewPosLon = fgGetNode("sim/current-view/viewer-lon-deg");
- _viewPosLat = fgGetNode("sim/current-view/viewer-lat-deg");
- _viewPosElev = fgGetNode("sim/current-view/viewer-elev-ft");
+
+ _viewX = _currentView->getNode("viewer-x-m", true);
+ _viewY = _currentView->getNode("viewer-y-m", true);
+ _viewZ = _currentView->getNode("viewer-z-m", true);
_velocityNorthFPS = fgGetNode("velocities/speed-north-fps", true);
_velocityEastFPS = fgGetNode("velocities/speed-east-fps", true);
}
if (enabled)
{
- SGGeod viewPosGeod(SGGeod::fromDegFt(_viewPosLon->getDoubleValue(),
- _viewPosLat->getDoubleValue(),
- _viewPosElev->getDoubleValue()));
- SGVec3d cartPos = SGVec3d::fromGeod(viewPosGeod);
+ SGVec3d cartPos(_viewX->getDoubleValue(),
+ _viewY->getDoubleValue(),
+ _viewZ->getDoubleValue());
+ SGGeod geodPos = SGGeod::fromCart(cartPos);
- set_position(cartPos, viewPosGeod);
+ set_position(cartPos, geodPos);
SGQuatd viewOrientation;
for (int i=0; i<4; ++i) {
bool _is_initialized, _enabled;
SGPropertyNode_ptr _sound_working, _sound_enabled, _volume, _device_name;
SGPropertyNode_ptr _currentView;
- SGPropertyNode_ptr _viewPosLon, _viewPosLat, _viewPosElev;
+ SGPropertyNode_ptr _viewX, _viewY, _viewZ;
SGPropertyNode_ptr _velocityNorthFPS, _velocityEastFPS, _velocityDownFPS;
SGPropertyNode_ptr _viewXoffset, _viewYoffset, _viewZoffset;
std::auto_ptr<Listener> _listener;
::snprintf(buffer, 128, "%c/%c/%c/",
airport[0], airport[1], airport[2]);
cacheData.append(buffer);
+ cacheData.append(airport + "-cache.txt");
+
+ // Note: Intuitively, this doesn't make sense, but I do need to create the full file path first
+ // before creating the directories. The SimGear fgpath code has changed so that it first chops off
+ // the trailing dir separator and then determines the directory part of the file path by searching
+ // for the last dir separator. Effecively, this causes a full element of the directory tree to be
+ // skipped.
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Trying to create dir for : " << cacheData.c_str());
if (!cacheData.exists()) {
cacheData.create_dir(0755);
}
- cacheData.append(airport + "-cache.txt");
- //cerr << "Saving AI traffic heuristics" << endl;
saveData = true;
cachefile.open(cacheData.str().c_str());
cachefile << "[TrafficManagerCachedata:ref:2011:09:04]" << endl;
+
}
}
{
_dirty = true;
_goal_pitch_offset_deg = goal_pitch_offset_deg;
- if ( _goal_pitch_offset_deg < -90 ) {
- _goal_pitch_offset_deg = -90.0;
+ /* The angle is set to 1/1000th of a degree from the poles to avoid the
+ * singularity where the azimuthal angle becomes undefined, inducing optical
+ * artefacts. The arbitrary angle offset is visually unnoticeable while
+ * avoiding any possible floating point truncation artefacts. */
+ if ( _goal_pitch_offset_deg < -89.999 ) {
+ _goal_pitch_offset_deg = -89.999;
}
- if ( _goal_pitch_offset_deg > 90.0 ) {
- _goal_pitch_offset_deg = 90.0;
+ if ( _goal_pitch_offset_deg > 89.999 ) {
+ _goal_pitch_offset_deg = 89.999;
}
}