X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAIModel%2FAIEscort.cxx;h=9a816675597d88283aad6a25b43bb5b28472840c;hb=9d995907db00728da7eac9297ecbab93ed8a7400;hp=5ef8485357d04686fb48c5f79eefa41b4282ce55;hpb=bc12f0be21d703653620743b6bf86db7c78a69cd;p=flightgear.git diff --git a/src/AIModel/AIEscort.cxx b/src/AIModel/AIEscort.cxx index 5ef848535..9a8166755 100644 --- a/src/AIModel/AIEscort.cxx +++ b/src/AIModel/AIEscort.cxx @@ -1,483 +1,382 @@ -// 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 +// 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 "AIEscort.hxx" + +using std::string; + +FGAIEscort::FGAIEscort() : +FGAIShip(otEscort), + +_relbrg (0), +_parent_speed(0), +_interval(0), +_stn_truebrg(0), +_stn_height(0), +_stn_speed(0), +_stn_angle_limit(0), +_stn_limit(0), +_max_speed(0), +_MPControl(false), +_patrol(false), +_stn_deg_true(false) + +{ + 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(); + + tie("station/rel-bearing-deg", + SGRawValuePointer(&_stn_relbrg)); + tie("station/true-bearing-deg", + SGRawValuePointer(&_stn_truebrg)); + tie("station/range-nm", + SGRawValuePointer(&_stn_range)); + tie("station/range-limit-nm", + SGRawValuePointer(&_stn_limit)); + tie("station/angle-limit-deg", + SGRawValuePointer(&_stn_angle_limit)); + tie("station/speed-kts", + SGRawValuePointer(&_stn_speed)); + tie("station/height-ft", + SGRawValuePointer(&_stn_height)); + tie("controls/update-interval-sec", + SGRawValuePointer(&_interval)); + tie("controls/parent-mp-control", + SGRawValuePointer(&_MPControl)); + tie("station/target-range-nm", + SGRawValuePointer(&_tgtrange)); + tie("station/target-brg-deg-t", + SGRawValuePointer(&_tgtbrg)); + tie("station/patrol", + SGRawValuePointer(&_patrol)); +} + +bool FGAIEscort::init(bool search_in_AI_path) { + if (!FGAIShip::init(search_in_AI_path)) + return false; + reinit(); + return true; +} + +void FGAIEscort::reinit() { + invisible = false; + no_roll = false; + + props->setStringValue("controls/parent-name", _parent.c_str()); + + if (setParentNode()){ + setParent(); + pos = _tgtpos; + speed = _parent_speed; + hdg = _parent_hdg; + } + + FGAIShip::reinit(); +} + +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; +} + +bool FGAIEscort::getGroundElev(SGGeod inpos) { + + double height_m ; + + const simgear::BVHMaterial* mat = 0; + if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 3000), height_m, &mat, 0)){ + const SGMaterial* material = dynamic_cast(mat); + _ht_agl_ft = inpos.getElevationFt() - height_m * SG_METER_TO_FEET; + + if (material) { + const std::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() +{ + 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_AI, 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(); + + _dt_count = 0; + +} + +// end AIEscort