From bc12f0be21d703653620743b6bf86db7c78a69cd Mon Sep 17 00:00:00 2001 From: Vivian Meazza Date: Thu, 2 Sep 2010 09:24:45 +0100 Subject: [PATCH] Walk the AImodels property tree only once at init, rather than at update. Should have a beneficial effect on frame rate, but in practice makes no discernible improvement. It is cleaner code though. Signed-off-by: Vivian Meazza --- src/AIModel/AIBallistic.cxx | 4 + src/AIModel/AIBallistic.hxx | 1 + src/AIModel/AIEscort.cxx | 926 +++++++++++++++++--------------- src/AIModel/AIEscort.hxx | 213 ++++---- src/AIModel/AIGroundVehicle.cxx | 79 +-- src/AIModel/AIGroundVehicle.hxx | 212 ++++---- src/AIModel/AIShip.cxx | 15 +- src/AIModel/AIWingman.cxx | 7 + 8 files changed, 761 insertions(+), 696 deletions(-) diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index 0306c3ec5..2f5bb4f6f 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -479,6 +479,10 @@ bool FGAIBallistic::getSlaved() const { return _slave_to_ac; } +bool FGAIBallistic::getFormate() const { + return _formate_to_ac; +} + double FGAIBallistic::getMass() const { return _mass; } diff --git a/src/AIModel/AIBallistic.hxx b/src/AIModel/AIBallistic.hxx index c9613de89..91a50acbd 100644 --- a/src/AIModel/AIBallistic.hxx +++ b/src/AIModel/AIBallistic.hxx @@ -105,6 +105,7 @@ public: bool getHtAGL(double start); bool getSlaved() const; + bool getFormate() const; bool getSlavedLoad() const; virtual const char* getTypeString(void) const { return "ballistic"; } diff --git a/src/AIModel/AIEscort.cxx b/src/AIModel/AIEscort.cxx index c9901ca24..5ef848535 100644 --- a/src/AIModel/AIEscort.cxx +++ b/src/AIModel/AIEscort.cxx @@ -1,443 +1,483 @@ -// FGAIEscort - FGAIShip-derived class creates an AI Ground Vehicle -// by adding a ground following utility -// -// Written by Vivian Meazza, started August 2009. -// - vivian.meazza at lineone.net -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include -#include -#include - -#include -#include
-#include
- -#include -#include - -#include "AIEscort.hxx" - -using std::string; - -FGAIEscort::FGAIEscort() : -FGAIShip(otEscort), - -_selected_ac(0), -_relbrg (0), -_stn_truebrg(0), -_parent_speed(0), -_stn_limit(0), -_stn_angle_limit(0), -_stn_speed(0), -_stn_height(0), -_max_speed(0), -_interval(0), -_MPControl(false), -_patrol(false), -_stn_deg_true(false), -_parent("") - -{ - invisible = false; -} - -FGAIEscort::~FGAIEscort() {} - -void FGAIEscort::readFromScenario(SGPropertyNode* scFileNode) { - if (!scFileNode) - return; - - FGAIShip::readFromScenario(scFileNode); - - setName(scFileNode->getStringValue("name", "Escort")); - setSMPath(scFileNode->getStringValue("submodel-path", "")); - setStnRange(scFileNode->getDoubleValue("station/range-nm", 1)); - setStnBrg(scFileNode->getDoubleValue("station/brg-deg", 0.0)); - setStnLimit(scFileNode->getDoubleValue("station/range-limit-nm", 0.2)); - setStnAngleLimit(scFileNode->getDoubleValue("station/angle-limit-deg", 15.0)); - setStnSpeed(scFileNode->getDoubleValue("station/speed-kts", 2.5)); - setStnPatrol(scFileNode->getBoolValue("station/patrol", false)); - setStnHtFt(scFileNode->getDoubleValue("station/height-ft", 0.0)); - setStnDegTrue(scFileNode->getBoolValue("station/deg-true", false)); - setParentName(scFileNode->getStringValue("station/parent", "")); - setMaxSpeed(scFileNode->getDoubleValue("max-speed-kts", 30.0)); - setUpdateInterval(scFileNode->getDoubleValue("update-interval-sec", 10.0)); - setCallSign(scFileNode->getStringValue("callsign", "")); - - if(_patrol) - sg_srandom_time(); - -} - -void FGAIEscort::bind() { - FGAIShip::bind(); - - props->tie("station/rel-bearing-deg", - SGRawValuePointer(&_stn_relbrg)); - props->tie("station/true-bearing-deg", - SGRawValuePointer(&_stn_truebrg)); - props->tie("station/range-nm", - SGRawValuePointer(&_stn_range)); - props->tie("station/range-limit-nm", - SGRawValuePointer(&_stn_limit)); - props->tie("station/angle-limit-deg", - SGRawValuePointer(&_stn_angle_limit)); - props->tie("station/speed-kts", - SGRawValuePointer(&_stn_speed)); - props->tie("station/height-ft", - SGRawValuePointer(&_stn_height)); - props->tie("controls/update-interval-sec", - SGRawValuePointer(&_interval)); - props->tie("controls/parent-mp-control", - SGRawValuePointer(&_MPControl)); - props->tie("station/target-range-nm", - SGRawValuePointer(&_tgtrange)); - props->tie("station/target-brg-deg-t", - SGRawValuePointer(&_tgtbrg)); - props->tie("station/patrol", - SGRawValuePointer(&_patrol)); -} - -void FGAIEscort::unbind() { - FGAIShip::unbind(); - - props->untie("station/rel-bearing-deg"); - props->untie("station/true-bearing-deg"); - props->untie("station/range-nm"); - props->untie("station/range-limit-nm"); - props->untie("station/angle-limit-deg"); - props->untie("station/speed-kts"); - props->untie("station/height-ft"); - props->untie("controls/update-interval-sec"); - -} - -bool FGAIEscort::init(bool search_in_AI_path) { - if (!FGAIShip::init(search_in_AI_path)) - return false; - - invisible = false; - no_roll = false; - - props->setStringValue("controls/parent-name", _parent.c_str()); - setParent(); - pos = _tgtpos; - speed = _parent_speed; - hdg = _parent_hdg; - - return true; -} - -void FGAIEscort::update(double dt) { - FGAIShip::update(dt); - - RunEscort(dt); -} - -void FGAIEscort::setStnRange(double r) { - _stn_range = r; -} - -void FGAIEscort::setStnBrg(double b) { - _stn_brg = b; -} - -void FGAIEscort::setStnLimit(double l) { - _stn_limit = l; -} - -void FGAIEscort::setStnAngleLimit(double al) { - _stn_angle_limit = al; -} - -void FGAIEscort::setStnSpeed(double s) { - _stn_speed = s; -} - -void FGAIEscort::setStnHtFt(double h) { - _stn_height = h; -} - -void FGAIEscort::setStnDegTrue(bool t) { - _stn_deg_true = t; -} - -void FGAIEscort::setMaxSpeed(double m) { - _max_speed = m; -} - -void FGAIEscort::setUpdateInterval(double i) { - _interval = i; -} - -void FGAIEscort::setStnPatrol(bool p) { - _patrol = p; -} - -void FGAIEscort::setParentName(const string& p) { - _parent = p; -} - -bool FGAIEscort::getGroundElev(SGGeod inpos) { - - double height_m ; - - if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 3000), height_m, &_material,0)){ - _ht_agl_ft = inpos.getElevationFt() - height_m * SG_METER_TO_FEET; - - if (_material) { - const vector& names = _material->get_names(); - - _solid = _material->get_solid(); - - if (!names.empty()) - props->setStringValue("material/name", names[0].c_str()); - else - props->setStringValue("material/name", ""); - - //cout << "material " << names[0].c_str() - // << " _elevation_m " << _elevation_m - // << " solid " << _solid - // << " load " << _load_resistance - // << " frictionFactor " << _frictionFactor - // << endl; - - } - - return true; - } else { - return false; - } - -} - -void FGAIEscort::setParent() { - - const SGPropertyNode_ptr ai = fgGetNode("/ai/models", true); - - for (int i = ai->nChildren() - 1; i >= -1; i--) { - SGPropertyNode_ptr model; - - if (i < 0) { // last iteration: selected model - model = _selected_ac; - } else { - model = ai->getChild(i); - string path = ai->getPath(); - const string name = model->getStringValue("name"); - - if (!model->nChildren()){ - continue; - } - if (name == _parent) { - _selected_ac = model; // save selected model for last iteration - break; - } - - } - if (!model) - continue; - - }// end for loop - - if (_selected_ac != 0){ - const string name = _selected_ac->getStringValue("name"); - double lat = _selected_ac->getDoubleValue("position/latitude-deg"); - double lon = _selected_ac->getDoubleValue("position/longitude-deg"); - double elevation = _selected_ac->getDoubleValue("position/altitude-ft"); - _MPControl = _selected_ac->getBoolValue("controls/mp-control"); - - _selectedpos.setLatitudeDeg(lat); - _selectedpos.setLongitudeDeg(lon); - _selectedpos.setElevationFt(elevation); - - _parent_speed = _selected_ac->getDoubleValue("velocities/speed-kts"); - _parent_hdg = _selected_ac->getDoubleValue("orientation/true-heading-deg"); - - if(!_stn_deg_true){ - _stn_truebrg = calcTrueBearingDeg(_stn_brg, _parent_hdg); - _stn_relbrg = _stn_brg; - //cout << _name <<" set rel"<getDoubleValue("orientation/true-heading-deg"); - double pitch = _selected_ac->getDoubleValue("orientation/pitch-deg"); - double roll = _selected_ac->getDoubleValue("orientation/roll-deg"); - - // Transform that one to the horizontal local coordinate system. - SGQuatd hlTrans = SGQuatd::fromLonLat(_selectedpos); - - // and postrotate the orientation of the AIModel wrt the horizontal - // local frame - hlTrans *= SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); - - // The offset converted to the usual body fixed coordinate system - // rotated to the earth fiexed coordinates axis - SGVec3d off = hlTrans.backTransform(_off); - - // Add the position offset of the AIModel to gain the earth centered position - SGVec3d cartPos = SGVec3d::fromGeod(_selectedpos); - - return cartPos + off; -} - - -void FGAIEscort::setStationSpeed(){ - - double speed = 0; - double angle = 0; - - // these are the AI rules for the manoeuvring of escorts - - if (_MPControl && _tgtrange > 4 * _stn_limit){ - SG_LOG(SG_GENERAL, SG_ALERT, "AIEscort: " << _name - << " re-aligning to MP pos"); - pos = _tgtpos; - speed = 0; - angle = 0; - }else if ((_relbrg < -90 || _relbrg > 90) && _tgtrange > _stn_limit ){ - angle =_relbrg; - - if(_tgtrange > 4 * _stn_limit) - speed = 4 * -_stn_speed; - else - speed = -_stn_speed; - - }else if ((_relbrg >= -90 || _relbrg <= 90) && _tgtrange > _stn_limit){ - angle = _relbrg; - - if(_tgtrange > 4 * _stn_limit) - speed = 4 * _stn_speed; - else - speed = _stn_speed; - - } else { - - if(_patrol){ - angle = 15 * sg_random(); - speed = 5 * sg_random(); - } else { - angle = 0; - speed = 0; - } - - } - - double station_speed = _parent_speed + speed; - - SG_CLAMP_RANGE(station_speed, 5.0, _max_speed); - SG_CLAMP_RANGE(angle, -_stn_angle_limit, _stn_angle_limit); - - AccelTo(station_speed); - TurnTo(_parent_hdg + angle); - ClimbTo(_stn_height); - -} - -void FGAIEscort::RunEscort(double dt){ - - _dt_count += dt; - - - - /////////////////////////////////////////////////////////////////////////// - // Check execution time (currently once every 0.05 sec or 20 fps) - // Add a bit of randomization to prevent the execution of all flight plans - // in synchrony, which can add significant periodic framerate flutter. - // Randomization removed to get better appearance - /////////////////////////////////////////////////////////////////////////// - - //cout << "_start_sec " << _start_sec << " time_sec " << time_sec << endl; - if (_dt_count < _next_run) - return; - _next_run = _interval /*+ (0.015 * sg_random())*/; - - if(_parent == ""){ - return; - } - - setParent(); - setStationSpeed(); - //getGroundElev(pos); - - _dt_count = 0; - -} - -// end AIGroundvehicle +// FGAIEscort - FGAIShip-derived class creates an AI Ground Vehicle +// by adding a ground following utility +// +// Written by Vivian Meazza, started August 2009. +// - vivian.meazza at lineone.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include
+#include
+ +#include +#include + +#include "AIEscort.hxx" + +using std::string; + +FGAIEscort::FGAIEscort() : +FGAIShip(otEscort), + +_selected_ac(0), +_relbrg (0), +_stn_truebrg(0), +_parent_speed(0), +_stn_limit(0), +_stn_angle_limit(0), +_stn_speed(0), +_stn_height(0), +_max_speed(0), +_interval(0), +_MPControl(false), +_patrol(false), +_stn_deg_true(false), +_parent("") + +{ + invisible = false; +} + +FGAIEscort::~FGAIEscort() {} + +void FGAIEscort::readFromScenario(SGPropertyNode* scFileNode) { + if (!scFileNode) + return; + + FGAIShip::readFromScenario(scFileNode); + + setName(scFileNode->getStringValue("name", "Escort")); + setSMPath(scFileNode->getStringValue("submodel-path", "")); + setStnRange(scFileNode->getDoubleValue("station/range-nm", 1)); + setStnBrg(scFileNode->getDoubleValue("station/brg-deg", 0.0)); + setStnLimit(scFileNode->getDoubleValue("station/range-limit-nm", 0.2)); + setStnAngleLimit(scFileNode->getDoubleValue("station/angle-limit-deg", 15.0)); + setStnSpeed(scFileNode->getDoubleValue("station/speed-kts", 2.5)); + setStnPatrol(scFileNode->getBoolValue("station/patrol", false)); + setStnHtFt(scFileNode->getDoubleValue("station/height-ft", 0.0)); + setStnDegTrue(scFileNode->getBoolValue("station/deg-true", false)); + setParentName(scFileNode->getStringValue("station/parent", "")); + setMaxSpeed(scFileNode->getDoubleValue("max-speed-kts", 30.0)); + setUpdateInterval(scFileNode->getDoubleValue("update-interval-sec", 10.0)); + setCallSign(scFileNode->getStringValue("callsign", "")); + + if(_patrol) + sg_srandom_time(); + +} + +void FGAIEscort::bind() { + FGAIShip::bind(); + + props->tie("station/rel-bearing-deg", + SGRawValuePointer(&_stn_relbrg)); + props->tie("station/true-bearing-deg", + SGRawValuePointer(&_stn_truebrg)); + props->tie("station/range-nm", + SGRawValuePointer(&_stn_range)); + props->tie("station/range-limit-nm", + SGRawValuePointer(&_stn_limit)); + props->tie("station/angle-limit-deg", + SGRawValuePointer(&_stn_angle_limit)); + props->tie("station/speed-kts", + SGRawValuePointer(&_stn_speed)); + props->tie("station/height-ft", + SGRawValuePointer(&_stn_height)); + props->tie("controls/update-interval-sec", + SGRawValuePointer(&_interval)); + props->tie("controls/parent-mp-control", + SGRawValuePointer(&_MPControl)); + props->tie("station/target-range-nm", + SGRawValuePointer(&_tgtrange)); + props->tie("station/target-brg-deg-t", + SGRawValuePointer(&_tgtbrg)); + props->tie("station/patrol", + SGRawValuePointer(&_patrol)); +} + +void FGAIEscort::unbind() { + FGAIShip::unbind(); + + props->untie("station/rel-bearing-deg"); + props->untie("station/true-bearing-deg"); + props->untie("station/range-nm"); + props->untie("station/range-limit-nm"); + props->untie("station/angle-limit-deg"); + props->untie("station/speed-kts"); + props->untie("station/height-ft"); + props->untie("controls/update-interval-sec"); + +} + +bool FGAIEscort::init(bool search_in_AI_path) { + if (!FGAIShip::init(search_in_AI_path)) + return false; + + invisible = false; + no_roll = false; + + props->setStringValue("controls/parent-name", _parent.c_str()); + setParentNode(); + pos = _tgtpos; + speed = _parent_speed; + hdg = _parent_hdg; + + return true; +} + +void FGAIEscort::update(double dt) { + FGAIShip::update(dt); + + RunEscort(dt); +} + +void FGAIEscort::setStnRange(double r) { + _stn_range = r; +} + +void FGAIEscort::setStnBrg(double b) { + _stn_brg = b; +} + +void FGAIEscort::setStnLimit(double l) { + _stn_limit = l; +} + +void FGAIEscort::setStnAngleLimit(double al) { + _stn_angle_limit = al; +} + +void FGAIEscort::setStnSpeed(double s) { + _stn_speed = s; +} + +void FGAIEscort::setStnHtFt(double h) { + _stn_height = h; +} + +void FGAIEscort::setStnDegTrue(bool t) { + _stn_deg_true = t; +} + +void FGAIEscort::setMaxSpeed(double m) { + _max_speed = m; +} + +void FGAIEscort::setUpdateInterval(double i) { + _interval = i; +} + +void FGAIEscort::setStnPatrol(bool p) { + _patrol = p; +} + +void FGAIEscort::setParentName(const string& p) { + _parent = p; +} + +bool FGAIEscort::getGroundElev(SGGeod inpos) { + + double height_m ; + + if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 3000), height_m, &_material,0)){ + _ht_agl_ft = inpos.getElevationFt() - height_m * SG_METER_TO_FEET; + + if (_material) { + const vector& names = _material->get_names(); + + _solid = _material->get_solid(); + + if (!names.empty()) + props->setStringValue("material/name", names[0].c_str()); + else + props->setStringValue("material/name", ""); + + //cout << "material " << names[0].c_str() + // << " _elevation_m " << _elevation_m + // << " solid " << _solid + // << " load " << _load_resistance + // << " frictionFactor " << _frictionFactor + // << endl; + + } + + return true; + } else { + return false; + } + +} + +void FGAIEscort::setParentNode() { + + const SGPropertyNode_ptr ai = fgGetNode("/ai/models", true); + + for (int i = ai->nChildren() - 1; i >= -1; i--) { + SGPropertyNode_ptr model; + + if (i < 0) { // last iteration: selected model + model = _selected_ac; + } else { + model = ai->getChild(i); + string path = ai->getPath(); + const string name = model->getStringValue("name"); + + if (!model->nChildren()){ + continue; + } + if (name == _parent) { + _selected_ac = model; // save selected model for last iteration + break; + } + + } + if (!model) + continue; + + }// end for loop + + if (_selected_ac != 0){ + const string name = _selected_ac->getStringValue("name"); + setParent(); + + //double lat = _selected_ac->getDoubleValue("position/latitude-deg"); + //double lon = _selected_ac->getDoubleValue("position/longitude-deg"); + //double elevation = _selected_ac->getDoubleValue("position/altitude-ft"); + //_MPControl = _selected_ac->getBoolValue("controls/mp-control"); + + //_selectedpos.setLatitudeDeg(lat); + //_selectedpos.setLongitudeDeg(lon); + //_selectedpos.setElevationFt(elevation); + + //_parent_speed = _selected_ac->getDoubleValue("velocities/speed-kts"); + //_parent_hdg = _selected_ac->getDoubleValue("orientation/true-heading-deg"); + + //if(!_stn_deg_true){ + // _stn_truebrg = calcTrueBearingDeg(_stn_brg, _parent_hdg); + // _stn_relbrg = _stn_brg; + // //cout << _name <<" set rel"<getDoubleValue("position/latitude-deg"); + double lon = _selected_ac->getDoubleValue("position/longitude-deg"); + double elevation = _selected_ac->getDoubleValue("position/altitude-ft"); + _MPControl = _selected_ac->getBoolValue("controls/mp-control"); + + _selectedpos.setLatitudeDeg(lat); + _selectedpos.setLongitudeDeg(lon); + _selectedpos.setElevationFt(elevation); + + _parent_speed = _selected_ac->getDoubleValue("velocities/speed-kts"); + _parent_hdg = _selected_ac->getDoubleValue("orientation/true-heading-deg"); + + if(!_stn_deg_true){ + _stn_truebrg = calcTrueBearingDeg(_stn_brg, _parent_hdg); + _stn_relbrg = _stn_brg; + //cout << _name <<" set rel"<getDoubleValue("orientation/true-heading-deg"); + double pitch = _selected_ac->getDoubleValue("orientation/pitch-deg"); + double roll = _selected_ac->getDoubleValue("orientation/roll-deg"); + + // Transform that one to the horizontal local coordinate system. + SGQuatd hlTrans = SGQuatd::fromLonLat(_selectedpos); + + // and postrotate the orientation of the AIModel wrt the horizontal + // local frame + hlTrans *= SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); + + // The offset converted to the usual body fixed coordinate system + // rotated to the earth fiexed coordinates axis + SGVec3d off = hlTrans.backTransform(_off); + + // Add the position offset of the AIModel to gain the earth centered position + SGVec3d cartPos = SGVec3d::fromGeod(_selectedpos); + + return cartPos + off; +} + + +void FGAIEscort::setStationSpeed(){ + + double speed = 0; + double angle = 0; + + // these are the AI rules for the manoeuvring of escorts + + if (_MPControl && _tgtrange > 4 * _stn_limit){ + SG_LOG(SG_GENERAL, SG_ALERT, "AIEscort: " << _name + << " re-aligning to MP pos"); + pos = _tgtpos; + speed = 0; + angle = 0; + }else if ((_relbrg < -90 || _relbrg > 90) && _tgtrange > _stn_limit ){ + angle =_relbrg; + + if(_tgtrange > 4 * _stn_limit) + speed = 4 * -_stn_speed; + else + speed = -_stn_speed; + + }else if ((_relbrg >= -90 || _relbrg <= 90) && _tgtrange > _stn_limit){ + angle = _relbrg; + + if(_tgtrange > 4 * _stn_limit) + speed = 4 * _stn_speed; + else + speed = _stn_speed; + + } else { + + if(_patrol){ + angle = 15 * sg_random(); + speed = 5 * sg_random(); + } else { + angle = 0; + speed = 0; + } + + } + + double station_speed = _parent_speed + speed; + + SG_CLAMP_RANGE(station_speed, 5.0, _max_speed); + SG_CLAMP_RANGE(angle, -_stn_angle_limit, _stn_angle_limit); + + AccelTo(station_speed); + TurnTo(_parent_hdg + angle); + ClimbTo(_stn_height); + +} + +void FGAIEscort::RunEscort(double dt){ + + _dt_count += dt; + + + + /////////////////////////////////////////////////////////////////////////// + // Check execution time (currently once every 0.05 sec or 20 fps) + // Add a bit of randomization to prevent the execution of all flight plans + // in synchrony, which can add significant periodic framerate flutter. + // Randomization removed to get better appearance + /////////////////////////////////////////////////////////////////////////// + + //cout << "_start_sec " << _start_sec << " time_sec " << time_sec << endl; + if (_dt_count < _next_run) + return; + _next_run = _interval /*+ (0.015 * sg_random())*/; + + if(_parent == ""){ + return; + } + + setParent(); + setStationSpeed(); + //getGroundElev(pos); + + _dt_count = 0; + +} + +// end AIGroundvehicle diff --git a/src/AIModel/AIEscort.hxx b/src/AIModel/AIEscort.hxx index d5adff5d5..a2e0ab678 100644 --- a/src/AIModel/AIEscort.hxx +++ b/src/AIModel/AIEscort.hxx @@ -1,106 +1,107 @@ -// FGAIGroundVehicle - FGAIShip-derived class creates an AI Ground Vehicle -// by adding a ground following utility -// -// Written by Vivian Meazza, started August 2009. -// - vivian.meazza at lineone.net -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifndef _FG_AIESCORT_HXX -#define _FG_AIESCORT_HXX - -#include -#include - -#include - -#include "AIBase.hxx" - -#include "AIShip.hxx" - -#include "AIManager.hxx" -#include "AIBase.hxx" - -class FGAIEscort : public FGAIShip { -public: - FGAIEscort(); - virtual ~FGAIEscort(); - - virtual void readFromScenario(SGPropertyNode* scFileNode); - virtual void bind(); - virtual void unbind(); - virtual const char* getTypeString(void) const { return "escort"; } - - bool init(bool search_in_AI_path=false); - -private: - - virtual void reinit() { init(); } - virtual void update (double dt); - - void setParentName(const std::string& p); - void setParent(); - void setStnRange(double r); - void setStnBrg(double y); - void setStationSpeed(); - void setStnLimit(double l); - void setStnAngleLimit(double l); - void setStnSpeed(double s); - void setStnHtFt(double h); - void setStnPatrol(bool p); - void setStnDegTrue(bool t); - - void setMaxSpeed(double m); - void setUpdateInterval(double i); - - void RunEscort(double dt); - - bool getGroundElev(SGGeod inpos); - - SGVec3d getCartHitchPosAt(const SGVec3d& off) const; - - void calcRangeBearing(double lat, double lon, double lat2, double lon2, - double &range, double &bearing) const; - double calcRelBearingDeg(double bearing, double heading); - double calcTrueBearingDeg(double bearing, double heading); - double calcRecipBearingDeg(double bearing); - - SGGeod _selectedpos; - SGGeod _tgtpos; - - bool _solid; // if true ground is solid for FDMs - double _load_resistance; // ground load resistanc N/m^2 - double _frictionFactor; // dimensionless modifier for Coefficient of Friction - double _tgtrange, _tgtbrg; - double _ht_agl_ft; - double _relbrg, _truebrg; - double _parent_speed, _parent_hdg; - double _interval; - - double _stn_relbrg, _stn_truebrg, _stn_brg, _stn_range, _stn_height; - double _stn_speed, _stn_angle_limit, _stn_limit; - - double _max_speed; - - const SGMaterial* _material; - SGPropertyNode_ptr _selected_ac; - - bool _MPControl, _patrol, _stn_deg_true; - - std::string _parent; - -}; - -#endif // FG_AIGROUNDVEHICLE_HXX +// FGAIGroundVehicle - FGAIShip-derived class creates an AI Ground Vehicle +// by adding a ground following utility +// +// Written by Vivian Meazza, started August 2009. +// - vivian.meazza at lineone.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef _FG_AIESCORT_HXX +#define _FG_AIESCORT_HXX + +#include +#include + +#include + +#include "AIBase.hxx" + +#include "AIShip.hxx" + +#include "AIManager.hxx" +#include "AIBase.hxx" + +class FGAIEscort : public FGAIShip { +public: + FGAIEscort(); + virtual ~FGAIEscort(); + + virtual void readFromScenario(SGPropertyNode* scFileNode); + virtual void bind(); + virtual void unbind(); + virtual const char* getTypeString(void) const { return "escort"; } + + bool init(bool search_in_AI_path=false); + +private: + + virtual void reinit() { init(); } + virtual void update (double dt); + + void setParentName(const std::string& p); + void setParentNode(); + void setStnRange(double r); + void setStnBrg(double y); + void setStationSpeed(); + void setStnLimit(double l); + void setStnAngleLimit(double l); + void setStnSpeed(double s); + void setStnHtFt(double h); + void setStnPatrol(bool p); + void setStnDegTrue(bool t); + void setParent(); + + void setMaxSpeed(double m); + void setUpdateInterval(double i); + + void RunEscort(double dt); + + bool getGroundElev(SGGeod inpos); + + SGVec3d getCartHitchPosAt(const SGVec3d& off) const; + + void calcRangeBearing(double lat, double lon, double lat2, double lon2, + double &range, double &bearing) const; + double calcRelBearingDeg(double bearing, double heading); + double calcTrueBearingDeg(double bearing, double heading); + double calcRecipBearingDeg(double bearing); + + SGGeod _selectedpos; + SGGeod _tgtpos; + + bool _solid; // if true ground is solid for FDMs + double _load_resistance; // ground load resistanc N/m^2 + double _frictionFactor; // dimensionless modifier for Coefficient of Friction + double _tgtrange, _tgtbrg; + double _ht_agl_ft; + double _relbrg, _truebrg; + double _parent_speed, _parent_hdg; + double _interval; + + double _stn_relbrg, _stn_truebrg, _stn_brg, _stn_range, _stn_height; + double _stn_speed, _stn_angle_limit, _stn_limit; + + double _max_speed; + + const SGMaterial* _material; + SGPropertyNode_ptr _selected_ac; + + bool _MPControl, _patrol, _stn_deg_true; + + std::string _parent; + +}; + +#endif // FG_AIGROUNDVEHICLE_HXX diff --git a/src/AIModel/AIGroundVehicle.cxx b/src/AIModel/AIGroundVehicle.cxx index e65ea5b7e..10ea47e59 100644 --- a/src/AIModel/AIGroundVehicle.cxx +++ b/src/AIModel/AIGroundVehicle.cxx @@ -61,9 +61,9 @@ void FGAIGroundVehicle::readFromScenario(SGPropertyNode* scFileNode) { FGAIShip::readFromScenario(scFileNode); - setNoRoll(scFileNode->getBoolValue("no-roll", true)); setName(scFileNode->getStringValue("name", "groundvehicle")); - setSMPath(scFileNode->getStringValue("submodel-path", "")); + setParentName(scFileNode->getStringValue("parent", "")); + setNoRoll(scFileNode->getBoolValue("no-roll", true)); setContactX1offset(scFileNode->getDoubleValue("contact-x1-offset", 0.0)); setContactX2offset(scFileNode->getDoubleValue("contact-x2-offset", 0.0)); setXOffset(scFileNode->getDoubleValue("hitch-x-offset", 35.0)); @@ -74,7 +74,6 @@ void FGAIGroundVehicle::readFromScenario(SGPropertyNode* scFileNode) { setYawoffset(scFileNode->getDoubleValue("yaw-offset", 0.0)); setPitchCoeff(scFileNode->getDoubleValue("pitch-coefficient", 0.1)); setElevCoeff(scFileNode->getDoubleValue("elevation-coefficient", 0.25)); - setParentName(scFileNode->getStringValue("parent", "")); setTowAngleGain(scFileNode->getDoubleValue("tow-angle-gain", 1.0)); setTowAngleLimit(scFileNode->getDoubleValue("tow-angle-limit-deg", 2.0)); setInitialTunnel(scFileNode->getBoolValue("tunnel", false)); @@ -125,7 +124,7 @@ void FGAIGroundVehicle::unbind() { FGAIShip::unbind(); props->untie("controls/constants/elevation-coeff"); - props->untie("controls/constants/pitch-coeff"); + props->untie("controls/constants/pitch-coeff"); props->untie("position/ht-AGL-ft"); props->untie("hitch/rel-bearing-deg"); props->untie("hitch/tow-angle-deg"); @@ -149,6 +148,9 @@ bool FGAIGroundVehicle::init(bool search_in_AI_path) { invisible = false; _limit = 200; no_roll = true; + + props->setStringValue("controls/parent-name", _parent.c_str()); + setParentNode(); return true; } @@ -342,12 +344,15 @@ bool FGAIGroundVehicle::getPitch() { } - getGroundElev(pos); + //getGroundElev(pos); return true; } -void FGAIGroundVehicle::setParent() { +void FGAIGroundVehicle::setParentNode() { + + if(_parent == "") + return; const SGPropertyNode_ptr ai = fgGetNode("/ai/models", true); @@ -377,46 +382,50 @@ void FGAIGroundVehicle::setParent() { if (_selected_ac != 0){ const string name = _selected_ac->getStringValue("name"); - double lat = _selected_ac->getDoubleValue("position/latitude-deg"); - double lon = _selected_ac->getDoubleValue("position/longitude-deg"); - double elevation = _selected_ac->getDoubleValue("position/altitude-ft"); - double hitch_x_offset_m = _selected_ac->getDoubleValue("hitch/x-offset-ft") + _parent_x_offset = _selected_ac->getDoubleValue("hitch/x-offset-ft"); + _parent_y_offset = _selected_ac->getDoubleValue("hitch/y-offset-ft"); + _parent_z_offset = _selected_ac->getDoubleValue("hitch/z-offset-ft"); + _hitch_x_offset_m = _selected_ac->getDoubleValue("hitch/x-offset-ft") * SG_FEET_TO_METER; - double hitch_y_offset_m = _selected_ac->getDoubleValue("hitch/y-offset-ft") + _hitch_y_offset_m = _selected_ac->getDoubleValue("hitch/y-offset-ft") * SG_FEET_TO_METER; - double hitch_z_offset_m = _selected_ac->getDoubleValue("hitch/z-offset-ft") + _hitch_z_offset_m = _selected_ac->getDoubleValue("hitch/z-offset-ft") * SG_FEET_TO_METER; - - _selectedpos.setLatitudeDeg(lat); - _selectedpos.setLongitudeDeg(lon); - _selectedpos.setElevationFt(elevation); + setParent(); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "AIGroundVeh1cle: " << _name + << " parent not found: dying "); + setDie(true); + } - _parent_x_offset = _selected_ac->getDoubleValue("hitch/x-offset-ft"); - _parent_y_offset = _selected_ac->getDoubleValue("hitch/y-offset-ft"); - _parent_z_offset = _selected_ac->getDoubleValue("hitch/z-offset-ft"); +} - _parent_speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt"); +void FGAIGroundVehicle::setParent(){ - SGVec3d rear_hitch(-hitch_x_offset_m, hitch_y_offset_m, 0); - SGVec3d RearHitch = getCartHitchPosAt(rear_hitch); + double lat = _selected_ac->getDoubleValue("position/latitude-deg"); + double lon = _selected_ac->getDoubleValue("position/longitude-deg"); + double elevation = _selected_ac->getDoubleValue("position/altitude-ft"); - SGGeod rearpos = SGGeod::fromCart(RearHitch); + _selectedpos.setLatitudeDeg(lat); + _selectedpos.setLongitudeDeg(lon); + _selectedpos.setElevationFt(elevation); - double user_lat = rearpos.getLatitudeDeg(); - double user_lon = rearpos.getLongitudeDeg(); + _parent_speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt"); - double range, bearing; + SGVec3d rear_hitch(-_hitch_x_offset_m, _hitch_y_offset_m, 0); + SGVec3d RearHitch = getCartHitchPosAt(rear_hitch); - calcRangeBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), - user_lat, user_lon, range, bearing); - _range_ft = range * 6076.11549; - _relbrg = calcRelBearingDeg(bearing, hdg); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "AIGroundVeh1cle: " << _name - << " parent not found: dying "); - setDie(true); - } + SGGeod rearpos = SGGeod::fromCart(RearHitch); + + double user_lat = rearpos.getLatitudeDeg(); + double user_lon = rearpos.getLongitudeDeg(); + + double range, bearing; + calcRangeBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), + user_lat, user_lon, range, bearing); + _range_ft = range * 6076.11549; + _relbrg = calcRelBearingDeg(bearing, hdg); } void FGAIGroundVehicle::calcRangeBearing(double lat, double lon, double lat2, double lon2, diff --git a/src/AIModel/AIGroundVehicle.hxx b/src/AIModel/AIGroundVehicle.hxx index 721ebf303..8547e67d0 100644 --- a/src/AIModel/AIGroundVehicle.hxx +++ b/src/AIModel/AIGroundVehicle.hxx @@ -1,105 +1,107 @@ -// FGAIGroundVehicle - FGAIShip-derived class creates an AI Ground Vehicle -// by adding a ground following utility -// -// Written by Vivian Meazza, started August 2009. -// - vivian.meazza at lineone.net -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifndef _FG_AIGROUNDVEHICLE_HXX -#define _FG_AIGROUNDVEHICLE_HXX - -#include -#include -#include -#include - -#include "AIShip.hxx" - -#include "AIManager.hxx" -#include "AIBase.hxx" - -class FGAIGroundVehicle : public FGAIShip { -public: - FGAIGroundVehicle(); - virtual ~FGAIGroundVehicle(); - - virtual void readFromScenario(SGPropertyNode* scFileNode); - virtual void bind(); - virtual void unbind(); - virtual const char* getTypeString(void) const { return "groundvehicle"; } - - bool init(bool search_in_AI_path=false); - -private: - - virtual void reinit() { init(); } - virtual void update (double dt); - - void setNoRoll(bool nr); - void setContactX1offset(double x1); - void setContactX2offset(double x2); - void setXOffset(double x); - void setYOffset(double y); - void setZOffset(double z); - - void setPitchCoeff(double pc); - void setElevCoeff(double ec); - void setTowAngleGain(double g); - void setTowAngleLimit(double l); - void setElevation(double _elevation, double dt, double _elevation_coeff); - void setPitch(double _pitch, double dt, double _pitch_coeff); - void setTowAngle(double _relbrg, double dt, double _towangle_coeff); - void setParentName(const string& p); - void setTrainSpeed(double s, double dt, double coeff); - void setParent(); - void AdvanceFP(); - void setTowSpeed(); - void RunGroundVehicle(double dt); - - bool getGroundElev(SGGeod inpos); - bool getPitch(); - - SGVec3d getCartHitchPosAt(const SGVec3d& off) const; - - void calcRangeBearing(double lat, double lon, double lat2, double lon2, - double &range, double &bearing) const; - double calcRelBearingDeg(double bearing, double heading); - - SGGeod _selectedpos; - - bool _solid; // if true ground is solid for FDMs - double _load_resistance; // ground load resistanc N/m^2 - double _frictionFactor; // dimensionless modifier for Coefficient of Friction - double _elevation, _elevation_coeff; - double _tow_angle_gain, _tow_angle_limit; - double _ht_agl_ft; - double _contact_x1_offset, _contact_x2_offset, _contact_z_offset; - double _pitch, _pitch_coeff, _pitch_deg; - double _speed_coeff, _speed_kt; - double _x_offset, _y_offset; - double _range_ft; - double _relbrg; - double _parent_speed, _parent_x_offset, _parent_y_offset, _parent_z_offset; - double _dt_count, _next_run, _break_count; - - const SGMaterial* _material; - SGPropertyNode_ptr _selected_ac; - - string _parent; - -}; - -#endif // FG_AIGROUNDVEHICLE_HXX +// FGAIGroundVehicle - FGAIShip-derived class creates an AI Ground Vehicle +// by adding a ground following utility +// +// Written by Vivian Meazza, started August 2009. +// - vivian.meazza at lineone.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef _FG_AIGROUNDVEHICLE_HXX +#define _FG_AIGROUNDVEHICLE_HXX + +#include +#include +#include +#include + +#include "AIShip.hxx" + +#include "AIManager.hxx" +#include "AIBase.hxx" + +class FGAIGroundVehicle : public FGAIShip { +public: + FGAIGroundVehicle(); + virtual ~FGAIGroundVehicle(); + + virtual void readFromScenario(SGPropertyNode* scFileNode); + virtual void bind(); + virtual void unbind(); + virtual const char* getTypeString(void) const { return "groundvehicle"; } + + bool init(bool search_in_AI_path=false); + +private: + + virtual void reinit() { init(); } + virtual void update (double dt); + + void setNoRoll(bool nr); + void setContactX1offset(double x1); + void setContactX2offset(double x2); + void setXOffset(double x); + void setYOffset(double y); + void setZOffset(double z); + + void setPitchCoeff(double pc); + void setElevCoeff(double ec); + void setTowAngleGain(double g); + void setTowAngleLimit(double l); + void setElevation(double _elevation, double dt, double _elevation_coeff); + void setPitch(double _pitch, double dt, double _pitch_coeff); + void setTowAngle(double _relbrg, double dt, double _towangle_coeff); + void setParentName(const string& p); + void setTrainSpeed(double s, double dt, double coeff); + void setParent(); + void setParentNode(); + void AdvanceFP(); + void setTowSpeed(); + void RunGroundVehicle(double dt); + + bool getGroundElev(SGGeod inpos); + bool getPitch(); + + SGVec3d getCartHitchPosAt(const SGVec3d& off) const; + + void calcRangeBearing(double lat, double lon, double lat2, double lon2, + double &range, double &bearing) const; + double calcRelBearingDeg(double bearing, double heading); + + SGGeod _selectedpos; + + bool _solid; // if true ground is solid for FDMs + double _load_resistance; // ground load resistanc N/m^2 + double _frictionFactor; // dimensionless modifier for Coefficient of Friction + double _elevation, _elevation_coeff; + double _tow_angle_gain, _tow_angle_limit; + double _ht_agl_ft; + double _contact_x1_offset, _contact_x2_offset, _contact_z_offset; + double _pitch, _pitch_coeff, _pitch_deg; + double _speed_coeff, _speed_kt; + double _x_offset, _y_offset; + double _range_ft; + double _relbrg; + double _parent_speed, _parent_x_offset, _parent_y_offset, _parent_z_offset; + double _hitch_x_offset_m, _hitch_y_offset_m, _hitch_z_offset_m; + double _dt_count, _next_run, _break_count; + + const SGMaterial* _material; + SGPropertyNode_ptr _selected_ac; + + string _parent; + +}; + +#endif // FG_AIGROUNDVEHICLE_HXX diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index 41f09550e..b27b21d96 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -99,6 +99,7 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) { setRudderConstant(scFileNode->getDoubleValue("rudder-constant", 0.5)); setFixedTurnRadius(scFileNode->getDoubleValue("fixed-turn-radius-ft", 500)); setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5)); + setSMPath(scFileNode->getStringValue("submodel-path", "")); if (!flightplan.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name ); @@ -250,12 +251,12 @@ void FGAIShip::update(double dt) { // Update the velocity information stored in those nodes. // Transform that one to the horizontal local coordinate system. SGQuatd ec2hl = SGQuatd::fromLonLat(pos); - // The orientation of the carrier wrt the horizontal local frame + // The orientation of the ship wrt the horizontal local frame SGQuatd hl2body = SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); // and postrotate the orientation of the AIModel wrt the horizontal // local frame SGQuatd ec2body = ec2hl*hl2body; - // The cartesian position of the carrier in the wgs84 world + // The cartesian position of the ship in the wgs84 world SGVec3d cartPos = SGVec3d::fromGeod(pos); // The simulation time this transform is meant for @@ -680,7 +681,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { if (_next_name == "TUNNEL"){ _tunnel = !_tunnel; - SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " " << sp_turn_radius_nm ); + SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " " << sp_turn_radius_nm ); fp->IncrementWaypoint(false); next = fp->getNextWaypoint(); @@ -697,7 +698,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { }else if(_next_name == "END" || fp->getNextWaypoint() == 0) { if (_repeat) { - SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << " Flightplan repeating "); + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: "<< _name << " Flightplan repeating "); fp->restart(); prev = curr; curr = fp->getCurrentWaypoint(); @@ -711,7 +712,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { _lead_angle = 0; AccelTo(prev->speed); } else if (_restart){ - SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan restarting "); + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " Flightplan restarting "); _missed_count = 0; initFlightPlan(); } else { @@ -755,7 +756,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { _until_time = next->time; setUntilTime(next->time); if (until_time_sec > time_sec) { - SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " " + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " " << curr->name << " waiting until: " << _until_time << " " << until_time_sec << " now " << time_sec ); setSpeed(0); @@ -763,7 +764,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { _waiting = true; return; } else { - SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " + SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " wait until done: getting new waypoints "); setUntilTime(""); fp->IncrementWaypoint(false); diff --git a/src/AIModel/AIWingman.cxx b/src/AIModel/AIWingman.cxx index 39c20bbc6..2bc8e2c0f 100644 --- a/src/AIModel/AIWingman.cxx +++ b/src/AIModel/AIWingman.cxx @@ -75,6 +75,11 @@ void FGAIWingman::bind() { &FGAIBase::_getLongitude, &FGAIBase::_setLongitude)); + props->tie("controls/formate-to-ac", + SGRawValueMethods + (*this, &FGAIBallistic::getFormate, &FGAIBallistic::setFormate)); + + props->tie("orientation/pitch-deg", SGRawValuePointer(&pitch)); props->tie("orientation/roll-deg", SGRawValuePointer(&roll)); props->tie("orientation/true-heading-deg", SGRawValuePointer(&hdg)); @@ -122,6 +127,8 @@ void FGAIWingman::unbind() { props->untie("orientation/roll-deg"); props->untie("orientation/true-heading-deg"); + props->untie("controls/formate-to-ac"); + props->untie("submodels/serviceable"); props->untie("velocities/true-airspeed-kt"); -- 2.39.2