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 <vivian.meazza@lineone.net>
This commit is contained in:
parent
792cb2701f
commit
bc12f0be21
8 changed files with 763 additions and 698 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"; }
|
||||
|
|
|
@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <math.h>
|
||||
#include <Main/util.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
|
||||
#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<double>(&_stn_relbrg));
|
||||
props->tie("station/true-bearing-deg",
|
||||
SGRawValuePointer<double>(&_stn_truebrg));
|
||||
props->tie("station/range-nm",
|
||||
SGRawValuePointer<double>(&_stn_range));
|
||||
props->tie("station/range-limit-nm",
|
||||
SGRawValuePointer<double>(&_stn_limit));
|
||||
props->tie("station/angle-limit-deg",
|
||||
SGRawValuePointer<double>(&_stn_angle_limit));
|
||||
props->tie("station/speed-kts",
|
||||
SGRawValuePointer<double>(&_stn_speed));
|
||||
props->tie("station/height-ft",
|
||||
SGRawValuePointer<double>(&_stn_height));
|
||||
props->tie("controls/update-interval-sec",
|
||||
SGRawValuePointer<double>(&_interval));
|
||||
props->tie("controls/parent-mp-control",
|
||||
SGRawValuePointer<bool>(&_MPControl));
|
||||
props->tie("station/target-range-nm",
|
||||
SGRawValuePointer<double>(&_tgtrange));
|
||||
props->tie("station/target-brg-deg-t",
|
||||
SGRawValuePointer<double>(&_tgtbrg));
|
||||
props->tie("station/patrol",
|
||||
SGRawValuePointer<bool>(&_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<string>& 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"<<endl;
|
||||
} else {
|
||||
_stn_truebrg = _stn_brg;
|
||||
_stn_relbrg = calcRelBearingDeg(_stn_brg, _parent_hdg);
|
||||
//cout << _name << " set true"<<endl;
|
||||
}
|
||||
|
||||
double course2;
|
||||
|
||||
SGGeodesy::direct( _selectedpos, _stn_truebrg, _stn_range * SG_NM_TO_METER,
|
||||
_tgtpos, course2);
|
||||
|
||||
_tgtpos.setElevationFt(_stn_height);
|
||||
|
||||
calcRangeBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
|
||||
_tgtpos.getLatitudeDeg(), _tgtpos.getLongitudeDeg(), _tgtrange, _tgtbrg);
|
||||
|
||||
_relbrg = calcRelBearingDeg(_tgtbrg, hdg);
|
||||
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIEscort: " << _name
|
||||
<< " parent not found: dying ");
|
||||
setDie(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FGAIEscort::calcRangeBearing(double lat, double lon, double lat2, double lon2,
|
||||
double &range, double &bearing) const
|
||||
{
|
||||
// calculate the bearing and range of the second pos from the first
|
||||
double az2, distance;
|
||||
geo_inverse_wgs_84(lat, lon, lat2, lon2, &bearing, &az2, &distance);
|
||||
range = distance * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcRelBearingDeg(double bearing, double heading)
|
||||
{
|
||||
double angle = bearing - heading;
|
||||
SG_NORMALIZE_RANGE(angle, -180.0, 180.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcTrueBearingDeg(double bearing, double heading)
|
||||
{
|
||||
double angle = bearing + heading;
|
||||
SG_NORMALIZE_RANGE(angle, 0.0, 360.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcRecipBearingDeg(double bearing)
|
||||
{
|
||||
double angle = bearing - 180;
|
||||
SG_NORMALIZE_RANGE(angle, 0.0, 360.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
SGVec3d FGAIEscort::getCartHitchPosAt(const SGVec3d& _off) const {
|
||||
double hdg = _selected_ac->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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <math.h>
|
||||
#include <Main/util.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
|
||||
#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<double>(&_stn_relbrg));
|
||||
props->tie("station/true-bearing-deg",
|
||||
SGRawValuePointer<double>(&_stn_truebrg));
|
||||
props->tie("station/range-nm",
|
||||
SGRawValuePointer<double>(&_stn_range));
|
||||
props->tie("station/range-limit-nm",
|
||||
SGRawValuePointer<double>(&_stn_limit));
|
||||
props->tie("station/angle-limit-deg",
|
||||
SGRawValuePointer<double>(&_stn_angle_limit));
|
||||
props->tie("station/speed-kts",
|
||||
SGRawValuePointer<double>(&_stn_speed));
|
||||
props->tie("station/height-ft",
|
||||
SGRawValuePointer<double>(&_stn_height));
|
||||
props->tie("controls/update-interval-sec",
|
||||
SGRawValuePointer<double>(&_interval));
|
||||
props->tie("controls/parent-mp-control",
|
||||
SGRawValuePointer<bool>(&_MPControl));
|
||||
props->tie("station/target-range-nm",
|
||||
SGRawValuePointer<double>(&_tgtrange));
|
||||
props->tie("station/target-brg-deg-t",
|
||||
SGRawValuePointer<double>(&_tgtbrg));
|
||||
props->tie("station/patrol",
|
||||
SGRawValuePointer<bool>(&_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<string>& 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"<<endl;
|
||||
//} else {
|
||||
// _stn_truebrg = _stn_brg;
|
||||
// _stn_relbrg = calcRelBearingDeg(_stn_brg, _parent_hdg);
|
||||
// //cout << _name << " set true"<<endl;
|
||||
//}
|
||||
|
||||
//double course2;
|
||||
|
||||
//SGGeodesy::direct( _selectedpos, _stn_truebrg, _stn_range * SG_NM_TO_METER,
|
||||
// _tgtpos, course2);
|
||||
|
||||
//_tgtpos.setElevationFt(_stn_height);
|
||||
|
||||
//calcRangeBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
|
||||
// _tgtpos.getLatitudeDeg(), _tgtpos.getLongitudeDeg(), _tgtrange, _tgtbrg);
|
||||
|
||||
//_relbrg = calcRelBearingDeg(_tgtbrg, hdg);
|
||||
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIEscort: " << _name
|
||||
<< " parent not found: dying ");
|
||||
setDie(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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"<<endl;
|
||||
} else {
|
||||
_stn_truebrg = _stn_brg;
|
||||
_stn_relbrg = calcRelBearingDeg(_stn_brg, _parent_hdg);
|
||||
//cout << _name << " set true"<<endl;
|
||||
}
|
||||
|
||||
double course2;
|
||||
|
||||
SGGeodesy::direct( _selectedpos, _stn_truebrg, _stn_range * SG_NM_TO_METER,
|
||||
_tgtpos, course2);
|
||||
|
||||
_tgtpos.setElevationFt(_stn_height);
|
||||
|
||||
calcRangeBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
|
||||
_tgtpos.getLatitudeDeg(), _tgtpos.getLongitudeDeg(), _tgtrange, _tgtbrg);
|
||||
|
||||
_relbrg = calcRelBearingDeg(_tgtbrg, hdg);
|
||||
|
||||
}
|
||||
|
||||
void FGAIEscort::calcRangeBearing(double lat, double lon, double lat2, double lon2,
|
||||
double &range, double &bearing) const
|
||||
{
|
||||
// calculate the bearing and range of the second pos from the first
|
||||
double az2, distance;
|
||||
geo_inverse_wgs_84(lat, lon, lat2, lon2, &bearing, &az2, &distance);
|
||||
range = distance * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcRelBearingDeg(double bearing, double heading)
|
||||
{
|
||||
double angle = bearing - heading;
|
||||
SG_NORMALIZE_RANGE(angle, -180.0, 180.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcTrueBearingDeg(double bearing, double heading)
|
||||
{
|
||||
double angle = bearing + heading;
|
||||
SG_NORMALIZE_RANGE(angle, 0.0, 360.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
double FGAIEscort::calcRecipBearingDeg(double bearing)
|
||||
{
|
||||
double angle = bearing - 180;
|
||||
SG_NORMALIZE_RANGE(angle, 0.0, 360.0);
|
||||
return angle;
|
||||
}
|
||||
|
||||
SGVec3d FGAIEscort::getCartHitchPosAt(const SGVec3d& _off) const {
|
||||
double hdg = _selected_ac->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
|
||||
|
|
|
@ -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 <string>
|
||||
#include <list>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#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 <string>
|
||||
#include <list>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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,40 +382,16 @@ 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")
|
||||
* SG_FEET_TO_METER;
|
||||
double 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")
|
||||
* SG_FEET_TO_METER;
|
||||
|
||||
_selectedpos.setLatitudeDeg(lat);
|
||||
_selectedpos.setLongitudeDeg(lon);
|
||||
_selectedpos.setElevationFt(elevation);
|
||||
|
||||
_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");
|
||||
|
||||
SGVec3d rear_hitch(-hitch_x_offset_m, hitch_y_offset_m, 0);
|
||||
SGVec3d RearHitch = getCartHitchPosAt(rear_hitch);
|
||||
|
||||
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);
|
||||
_hitch_x_offset_m = _selected_ac->getDoubleValue("hitch/x-offset-ft")
|
||||
* SG_FEET_TO_METER;
|
||||
_hitch_y_offset_m = _selected_ac->getDoubleValue("hitch/y-offset-ft")
|
||||
* SG_FEET_TO_METER;
|
||||
_hitch_z_offset_m = _selected_ac->getDoubleValue("hitch/z-offset-ft")
|
||||
* SG_FEET_TO_METER;
|
||||
setParent();
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIGroundVeh1cle: " << _name
|
||||
<< " parent not found: dying ");
|
||||
|
@ -419,6 +400,34 @@ void FGAIGroundVehicle::setParent() {
|
|||
|
||||
}
|
||||
|
||||
void FGAIGroundVehicle::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");
|
||||
|
||||
_selectedpos.setLatitudeDeg(lat);
|
||||
_selectedpos.setLongitudeDeg(lon);
|
||||
_selectedpos.setElevationFt(elevation);
|
||||
|
||||
_parent_speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt");
|
||||
|
||||
SGVec3d rear_hitch(-_hitch_x_offset_m, _hitch_y_offset_m, 0);
|
||||
SGVec3d RearHitch = getCartHitchPosAt(rear_hitch);
|
||||
|
||||
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,
|
||||
double &range, double &bearing) const
|
||||
{
|
||||
|
|
|
@ -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 <math.h>
|
||||
#include <vector>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
||||
#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 <math.h>
|
||||
#include <vector>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -75,6 +75,11 @@ void FGAIWingman::bind() {
|
|||
&FGAIBase::_getLongitude,
|
||||
&FGAIBase::_setLongitude));
|
||||
|
||||
props->tie("controls/formate-to-ac",
|
||||
SGRawValueMethods<FGAIBallistic,bool>
|
||||
(*this, &FGAIBallistic::getFormate, &FGAIBallistic::setFormate));
|
||||
|
||||
|
||||
props->tie("orientation/pitch-deg", SGRawValuePointer<double>(&pitch));
|
||||
props->tie("orientation/roll-deg", SGRawValuePointer<double>(&roll));
|
||||
props->tie("orientation/true-heading-deg", SGRawValuePointer<double>(&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");
|
||||
|
|
Loading…
Add table
Reference in a new issue