#include <simgear/math/SGMath.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/simple.hxx>
+#include <Scenery/scenery.hxx>
#include "atc_mgr.hxx"
aircraftRadius, leg, &ai_ac);
//dialog.init();
+
+ osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
+ cerr << "Adding groundnetWork to the scenegraph" << endl;
+ globals->get_scenery()->get_scene_graph()->addChild(node);
}
}
speed,
altitude, time);
}
+ /*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;
+ globals->get_scenery()->get_scene_graph()->addChild(node);
+*/
}
commands.push_back(txt);
}
+void FGATCDialogNew::removeEntry(int nr) {
+ commands.clear();
+}
+
+
void FGATCDialogNew::PopupDialog() {
- double onBoardRadioFreq0 =
+ /*double onBoardRadioFreq0 =
+ fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
+ double onBoardRadioFreq1 =
+ fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
+
+ const char *dialog_name = "atc-dialog";
+ _gui = (NewGUI *)globals->get_subsystem("gui");
+ SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
+ if (!dlg)
+ return;
+
+ _gui->closeDialog(dialog_name);
+ SGPropertyNode_ptr button_group = getNamedNode(dlg, "transmission-choice");
+ button_group->removeChildren("button", false);
+
+ const int bufsize = 32;
+ char buf[bufsize];
+ int commandNr = 0;
+ // loop over all entries that should fill up the dialog; use 10 items for now...
+ for (StringVecIterator i = commands.begin(); i != commands.end(); i++) {
+ snprintf(buf, bufsize, "/sim/atc/opt[%d]", commandNr);
+ fgSetBool(buf, false);
+ SGPropertyNode *entry = button_group->getNode("button", commandNr, true);
+ copyProperties(button_group->getNode("button-template", true), entry);
+ entry->removeChildren("enabled", true);
+ 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++;
+ }
+*/
+ //if (dialogVisible) {
+ // _gui->closeDialog(dialog_name);
+ //} else {
+ // _gui->showDialog(dialog_name);
+ //}
+ dialogVisible = !dialogVisible;
+ return;
+}
+
+void FGATCDialogNew::update(double dt) {
+ double onBoardRadioFreq0 =
fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
double onBoardRadioFreq1 =
fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
} else {
_gui->showDialog(dialog_name);
}
- dialogVisible = !dialogVisible;
+ //dialogVisible = !dialogVisible;
return;
-}
-
-void FGATCDialogNew::update(double dt) {
/*
static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
int n = trans_num->getIntValue();
void update(double dt);
void PopupDialog();
void addEntry(int, string);
+ void removeEntry(int);
};
extern FGATCDialogNew *currentATCDialog;
bool FGTrafficRecord::pushBackAllowed()
{
+ // With the user ATC / AI integration, checking whether the user's aircraft is near no longer works, because
+ // this will effectively block the user's aircraft itself from receiving pushback clearance.
+ // So, what can we do?
+ /*
double course, az2, dist;
SGGeod curr(SGGeod::fromDegM(getLongitude(),
getLatitude(), getAltitude()));
SGGeodesy::inverse(curr, user, course, az2, dist);
//cerr << "Distance to user : " << dist << endl;
return (dist > 250);
+ */
+
+ // 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
}
trans_num->setIntValue(-1);
// PopupCallback(n);
cerr << "Selected transmission message" << n << endl;
+ FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+ atc->getATCDialog()->removeEntry(1);
} else {
cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false);
}
checkTransmissionState(5, now, (startTime + 140), i, MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
checkTransmissionState(6, now, (startTime + 150), i, MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
+ checkTransmissionState(7, now, (startTime + 180), i, MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
random_shuffle(parkings.begin(), parkings.end());
sort(parkings.begin(), parkings.end());
// add the gate positions to the ground network.
+ groundNetwork.setParent(_ap);
groundNetwork.addNodes(&parkings);
groundNetwork.init();
groundNetwork.setTowerController(&towerController);
- groundNetwork.setParent(_ap);
+
}
bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
string chooseRunwayFallback();
bool innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading);
string chooseRwyByHeading(stringVec rwys, double heading);
+
+ double elevation;
+
public:
FGAirportDynamics(FGAirport* ap);
FGAirportDynamics(const FGAirportDynamics &other);
return value;
}
-bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b) {
- return a->hasSmallerHeadingDiff(*b);
-}
+//bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b) {
+// return a->hasSmallerHeadingDiff(*b);
+//}
bool sortByLength(FGTaxiSegment *a, FGTaxiSegment *b) {
return a->getLength() > b->getLength();
/**************************************************************************
* FGTaxiNode
*************************************************************************/
-
+void FGTaxiNode::setElevation(double val)
+{
+ geod.setElevationM(val);
+}
void FGTaxiNode::setLatitude (double val)
{
geod.setLongitudeDeg(processPosition(val));
}
-void FGTaxiNode::sortEndSegments(bool byLength)
-{
- if (byLength)
- sort(next.begin(), next.end(), sortByLength);
- else
- sort(next.begin(), next.end(), sortByHeadingDiff);
-}
+//void FGTaxiNode::sortEndSegments(bool byLength)
+//{
+// if (byLength)
+// sort(next.begin(), next.end(), sortByLength);
+// else
+// sort(next.begin(), next.end(), sortByHeadingDiff);
+//}
void setIndex(int idx) { index = idx; };
void setLatitude (double val);
void setLongitude(double val);
+ void setElevation(double val);
void setLatitude (const std::string& val);
void setLongitude(const std::string& val);
void addSegment(FGTaxiSegment *segment) { next.push_back(segment); };
double getPathScore() { return pathScore; };
double getLatitude() { return geod.getLatitudeDeg();};
double getLongitude(){ return geod.getLongitudeDeg();};
+ double getElevation() { return geod.getElevationM();};
const SGGeod& getGeod() const { return geod; }
FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); };
bool operator<(const FGTaxiNode &other) const { return index < other.index; };
- void sortEndSegments(bool);
+ //void sortEndSegments(bool);
};
#include <math.h>
#include <algorithm>
+
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/MatrixTransform>
+#include <osg/Shape>
+
#include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <Airports/simple.hxx>
#include <Airports/dynamics.hxx>
// There is probably a computationally cheaper way of
// doing this.
-void FGTaxiSegment::setTrackDistance()
+void FGTaxiSegment::setDimensions(double elevation)
{
length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
+ //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+
+ double az2; //, distanceM;
+ 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;
}
-void FGTaxiSegment::setCourseDiff(double crse)
-{
- headingDiff = fabs(course - crse);
+//void FGTaxiSegment::setCourseDiff(double crse)
+//{
+// headingDiff = fabs(course - crse);
- if (headingDiff > 180)
- headingDiff = fabs(headingDiff - 360);
-}
+// if (headingDiff > 180)
+// headingDiff = fabs(headingDiff - 360);
+//}
/***************************************************************************
n.setIndex(i->getIndex());
n.setLatitude(i->getLatitude());
n.setLongitude(i->getLongitude());
+ n.setElevation(parent->getElevation());
nodes.push_back(new FGTaxiNode(n));
i++;
while (i != segments.end()) {
(*i)->setStart(&nodes);
(*i)->setEnd(&nodes);
- (*i)->setTrackDistance();
+ (*i)->setDimensions(parent->getElevation());
(*i)->setIndex(index);
if ((*i)->isPushBack()) {
pushBackNodes.push_back((*i)->getEnd());
}
}
+bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
+ AtcMsgDir msgDir)
+{
+ int state = i->getState();
+ if ((state >= minState) && (state <= maxState) && available) {
+ if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
+
+ cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl;
+ static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
+ int n = trans_num->getIntValue();
+ if (n >= 0) {
+ trans_num->setIntValue(-1);
+ // PopupCallback(n);
+ cerr << "Selected transmission message" << n << endl;
+ } else {
+ cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
+ transmit(&(*i), msgId, msgDir, false);
+ return false;
+ }
+ }
+ //cerr << "Transmitting startup msg" << endl;
+ transmit(&(*i), msgId, msgDir, true);
+ i->updateState();
+ lastTransmission = now;
+ available = false;
+ return true;
+ }
+ return false;
+}
+
void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
double heading, double speed, double alt,
double dt)
if ((now - lastTransmission) > 15) {
available = true;
}
- if ((state < 3) && available) {
- transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND, true);
- current->setState(3);
- lastTransmission = now;
- available = false;
+ if (checkTransmissionState(0,2, current, now, MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
+ current->setState(3);
}
- if ((state == 3) && available) {
- transmit(&(*current), MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR, true);
+ if (checkTransmissionState(3,3, current, now, MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR)) {
current->setState(4);
- lastTransmission = now;
- available = false;
}
- if ((state == 4) && available) {
- transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND, true);
+ if (checkTransmissionState(4,4, current, now, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
current->setState(5);
- lastTransmission = now;
- available = false;
}
if ((state == 5) && available) {
current->setState(0);
//cerr << "Current state " << current->getState() << endl;
} else {
}
- int state = current->getState();
- if ((state == 1) && (available)) {
+ //int state = current->getState();
+ if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
+ current->setState(0);
+ current->setHoldPosition(true);
+ }
+ if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
+ current->setState(0);
+ current->setHoldPosition(false);
+ }
+
+ /*if ((state == 1) && (available)) {
//cerr << "ACKNOWLEDGE HOLD" << endl;
transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND, true);
current->setState(0);
current->setHoldPosition(false);
lastTransmission = now;
available = false;
- }
-}
+ }*/
+}
/**
* Check whether situations occur where the current aircraft is waiting for itself
}
return FGATCInstruction();
}
+
+// Note that this function is copied from simgear. for maintanance purposes, it's probabtl better to make a general function out of that.
+static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
+ double lon, double elev, double hdg)
+{
+ SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
+ obj_pos = geod.makeZUpFrame();
+ // hdg is not a compass heading, but a counter-clockwise rotation
+ // around the Z axis
+ obj_pos.preMult(osg::Matrix::rotate(hdg * SGD_DEGREES_TO_RADIANS,
+ 0.0, 0.0, 1.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()) );
+
+ 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 );
+ }
+
+
+ return group;
+}
\ No newline at end of file
int startNode;
int endNode;
double length;
- double course;
- double headingDiff;
+ double heading;
+ SGGeod center;
bool isActive;
bool isPushBackRoute;
FGTaxiNode *start;
startNode(0),
endNode(0),
length(0),
- course(0),
- headingDiff(0),
+ heading(0),
isActive(0),
isPushBackRoute(0),
start(0),
startNode (other.startNode),
endNode (other.endNode),
length (other.length),
- course (other.course),
- headingDiff (other.headingDiff),
+ heading (other.heading),
+ center (other.center),
isActive (other.isActive),
isPushBackRoute (other.isPushBackRoute),
start (other.start),
startNode = other.startNode;
endNode = other.endNode;
length = other.length;
- course = other.course;
- headingDiff = other.headingDiff;
+ heading = other.heading;
+ center = other.center;
isActive = other.isActive;
isPushBackRoute = other.isPushBackRoute;
start = other.start;
void setStart(FGTaxiNodeVector *nodes);
void setEnd (FGTaxiNodeVector *nodes);
void setPushBackType(bool val) { isPushBackRoute = val; };
- void setTrackDistance();
+ void setDimensions(double elevation);
FGTaxiNode * getEnd() { return end;};
FGTaxiNode * getStart() { return start; };
double getLength() { return length; };
int getIndex() { return index; };
-
+ double getLatitude() { return center.getLatitudeDeg(); };
+ double getLongitude() { return center.getLongitudeDeg(); };
+ double getHeading() { return heading; };
bool isPushBack() { return isPushBackRoute; };
int getPenalty(int nGates);
FGTaxiSegment *getAddress() { return this;};
bool operator<(const FGTaxiSegment &other) const { return index < other.index; };
- bool hasSmallerHeadingDiff (const FGTaxiSegment &other) const { return headingDiff < other.headingDiff; };
+ //bool hasSmallerHeadingDiff (const FGTaxiSegment &other) const { return headingDiff < other.headingDiff; };
FGTaxiSegment *opposite() { return oppositeDirection; };
void setCourseDiff(double crse);
virtual bool hasInstruction(int id);
virtual FGATCInstruction getInstruction(int id);
+ bool checkTransmissionState(int minState, int MaxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
+ AtcMsgDir msgDir);
bool checkForCircularWaits(int id);
+ osg::Node* getRenderNode();
};
if ( tile_cache.insert_tile( t ) )
{
// Attach to scene graph
+
t->addToSceneGraph(globals->get_scenery()->get_terrain_branch());
} else
{