diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 98d95fb5c..b56a7893a 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -120,7 +120,7 @@ void FGAIAircraft::readFromScenario(SGPropertyNode* scFileNode) { bool FGAIAircraft::init() { //refuel_node = fgGetNode("systems/refuel/contact", true); - return FGAIBase::init(); + return FGAIBase::init(true); } @@ -647,7 +647,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { no_roll = prev->on_ground; if (no_roll) { Transform(); // make sure aip is initialized. - getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value + getGroundElev(60.1); // make sure it's executed first time around, so force a large dt value doGroundAltitude(); } // Make sure to announce the aircraft's position @@ -655,16 +655,19 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { prevSpeed = 0; return; } // end of initialization - + /////////////////////////////////////////////////////////////////////////// + // Check Execution time (currently once every 100 ms) + // Add a bit of randomization to prevent the execution of all flight plans + // in synchrony, which can add significant periodic framerate flutter. /////////////////////////////////////////////////////////////////////////// - // Check Execution time (currently once every 100 ms - /////////////////////////////////////////////////////////////////////////// - if ((dt_count < 0.1) || (now < fp->getStartTime())) { + double rand_exec_time = (rand() % 100) / 100; + if ((dt_count < (0.1+rand_exec_time)) || (now < fp->getStartTime())) { //cerr << "done fp dt" << endl; return; } else { dt_count = 0; } + // check to see if we've reached the lead point for our next turn double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index 27cc00eb9..ebf34e94d 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -125,27 +125,28 @@ void FGAIBase::Transform() { } } - -bool FGAIBase::init() { - - if (!model_path.empty()) { - SGPath ai_path("AI"); - ai_path.append(model_path); - try { - model = load3DModel( globals->get_fg_root(), ai_path.str(), props, +bool FGAIBase::init(bool search_in_AI_path) { + if (!model_path.empty()) { + if ( (search_in_AI_path) + &&(model_path.substr(model_path.size() - 4, 4) == ".xml")) { + SGPath ai_path("AI"); + ai_path.append(model_path); + try { + model = load3DModel( globals->get_fg_root(), ai_path.str(), props, globals->get_sim_time_sec() ); - } catch (const sg_exception &) { - model = NULL; - } + } catch (const sg_exception &e) { + model = NULL; + } + } else model = NULL; if (!model) { try { model = load3DModel( globals->get_fg_root(), model_path, props, globals->get_sim_time_sec() ); - } catch (const sg_exception &) { + } catch (const sg_exception &e) { model = NULL; } - } - } + } + } if (model.get()) { aip.init( model.get() ); aip.setVisible(true); @@ -161,7 +162,6 @@ bool FGAIBase::init() { } setDie(false); - return true; } @@ -207,6 +207,19 @@ void FGAIBase::bind() { &FGAIBase::_getLongitude, &FGAIBase::_setLongitude)); + props->tie("position/global-x", + SGRawValueMethods(*this, + &FGAIBase::_getCartPosX, + 0)); + props->tie("position/global-y", + SGRawValueMethods(*this, + &FGAIBase::_getCartPosY, + 0)); + props->tie("position/global-z", + SGRawValueMethods(*this, + &FGAIBase::_getCartPosZ, + 0)); + props->tie("orientation/pitch-deg", SGRawValuePointer(&pitch)); props->tie("orientation/roll-deg", SGRawValuePointer(&roll)); props->tie("orientation/true-heading-deg", SGRawValuePointer(&hdg)); @@ -248,6 +261,9 @@ void FGAIBase::unbind() { props->untie("position/altitude-ft"); props->untie("position/latitude-deg"); props->untie("position/longitude-deg"); + props->untie("position/global-x"); + props->untie("position/global-y"); + props->untie("position/global-z"); props->untie("orientation/pitch-deg"); props->untie("orientation/roll-deg"); @@ -386,6 +402,42 @@ FGAIBase::getCartPosAt(const SGVec3d& _off) const return cartPos + off; } +SGVec3d +FGAIBase::getCartPos() const +{ + // Transform that one to the horizontal local coordinate system. + + SGQuatd hlTrans = SGQuatd::fromLonLat(pos); + // and postrotate the orientation of the AIModel wrt the horizontal + // local frame + hlTrans *= SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); + + SGVec3d cartPos = SGVec3d::fromGeod(pos); + + return cartPos; +} + +double +FGAIBase::_getCartPosX() const +{ + SGVec3d cartPos = getCartPos(); + return cartPos.x(); +} + +double +FGAIBase::_getCartPosY() const +{ + SGVec3d cartPos = getCartPos(); + return cartPos.y(); +} + +double +FGAIBase::_getCartPosZ() const +{ + SGVec3d cartPos = getCartPos(); + return cartPos.z(); +} + /* * getters and Setters */ diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 2fa960ace..1af25d080 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -51,7 +51,7 @@ public: virtual void readFromScenario(SGPropertyNode* scFileNode); - virtual bool init(); + virtual bool init(bool search_in_AI_path=false); virtual void update(double dt); virtual void bind(); virtual void unbind(); @@ -76,6 +76,10 @@ public: bool getDie(); SGVec3d getCartPosAt(const SGVec3d& off) const; + SGVec3d getCartPos() const; + double _getCartPosX() const; + double _getCartPosY() const; + double _getCartPosZ() const; protected: diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 1b6bf324d..72f592a1e 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -136,12 +136,27 @@ FGAIManager::attach(SGSharedPtr model) unsigned idx = mNumAiTypeModels[model->getType()]; const char* typeString = model->getTypeString(); SGPropertyNode* root = globals->get_props()->getNode("ai/models", true); - SGPropertyNode* p = root->getNode(typeString, idx, true); + SGPropertyNode* p; + int i; + for (i=0;i<10000;i++) //find free index in the property tree, if we have + //more than 10000 mp-aircrafts in the property tree we should optimize the mp-server + { + p = root->getNode(typeString, i, false); + if (!p) break; + if (p->getIntValue("id",-1)==model->getID()) + { + p->setStringValue("callsign","***invalid node***"); //debug only, should never set! + + } + } + p = root->getNode(typeString, i, true); model->setManager(this, p); ai_list.push_back(model); ++mNumAiModels; ++(mNumAiTypeModels[model->getType()]); - model->init(); + model->init(model->getType()==FGAIBase::otAircraft + || model->getType()==FGAIBase::otMultiplayer + || model->getType()==FGAIBase::otStatic); model->bind(); } diff --git a/src/AIModel/AIMultiplayer.cxx b/src/AIModel/AIMultiplayer.cxx index 9a0e80e6f..9888d58ef 100755 --- a/src/AIModel/AIMultiplayer.cxx +++ b/src/AIModel/AIMultiplayer.cxx @@ -57,7 +57,7 @@ bool FGAIMultiplayer::init() { isTanker = true; // cout << "isTanker " << isTanker << " " << mCallSign <