29#include <simgear/sg_inlines.h>
30#include <simgear/math/sg_geodesy.hxx>
31#include <simgear/math/sg_random.hxx>
55 setName(scFileNode->getStringValue(
"name",
"Escort"));
56 setSMPath(scFileNode->getStringValue(
"submodel-path",
""));
57 setStnRange(scFileNode->getDoubleValue(
"station/range-nm", 1));
58 setStnBrg(scFileNode->getDoubleValue(
"station/brg-deg", 0.0));
59 setStnLimit(scFileNode->getDoubleValue(
"station/range-limit-nm", 0.2));
60 setStnAngleLimit(scFileNode->getDoubleValue(
"station/angle-limit-deg", 15.0));
61 setStnSpeed(scFileNode->getDoubleValue(
"station/speed-kts", 2.5));
62 setStnPatrol(scFileNode->getBoolValue(
"station/patrol",
false));
63 setStnHtFt(scFileNode->getDoubleValue(
"station/height-ft", 0.0));
64 setStnDegTrue(scFileNode->getBoolValue(
"station/deg-true",
false));
65 setParentName(scFileNode->getStringValue(
"station/parent",
""));
66 setMaxSpeed(scFileNode->getDoubleValue(
"max-speed-kts", 30.0));
67 setUpdateInterval(scFileNode->getDoubleValue(
"update-interval-sec", 10.0));
68 setCallSign(scFileNode->getStringValue(
"callsign",
""));
78 tie(
"station/rel-bearing-deg",
79 SGRawValuePointer<double>(&_stn_relbrg));
80 tie(
"station/true-bearing-deg",
81 SGRawValuePointer<double>(&_stn_truebrg));
82 tie(
"station/range-nm",
83 SGRawValuePointer<double>(&_stn_range));
84 tie(
"station/range-limit-nm",
85 SGRawValuePointer<double>(&_stn_limit));
86 tie(
"station/angle-limit-deg",
87 SGRawValuePointer<double>(&_stn_angle_limit));
88 tie(
"station/speed-kts",
89 SGRawValuePointer<double>(&_stn_speed));
90 tie(
"station/height-ft",
91 SGRawValuePointer<double>(&_stn_height));
92 tie(
"controls/update-interval-sec",
93 SGRawValuePointer<double>(&_interval));
94 tie(
"controls/parent-mp-control",
95 SGRawValuePointer<bool>(&_MPControl));
96 tie(
"station/target-range-nm",
97 SGRawValuePointer<double>(&_tgtrange));
98 tie(
"station/target-brg-deg-t",
99 SGRawValuePointer<double>(&_tgtbrg));
100 tie(
"station/patrol",
101 SGRawValuePointer<bool>(&_patrol));
115 props->setStringValue(
"controls/parent-name",
_parent.c_str());
120 speed = _parent_speed;
133void FGAIEscort::setStnRange(
double r) {
137void FGAIEscort::setStnBrg(
double b) {
141void FGAIEscort::setStnLimit(
double l) {
145void FGAIEscort::setStnAngleLimit(
double al) {
146 _stn_angle_limit = al;
149void FGAIEscort::setStnSpeed(
double s) {
153void FGAIEscort::setStnHtFt(
double h) {
157void FGAIEscort::setStnDegTrue(
bool t) {
161void FGAIEscort::setMaxSpeed(
double m) {
165void FGAIEscort::setUpdateInterval(
double i) {
169void FGAIEscort::setStnPatrol(
bool p) {
173bool FGAIEscort::getGroundElev(SGGeod inpos) {
177 const simgear::BVHMaterial* mat = 0;
179 const SGMaterial* material =
dynamic_cast<const SGMaterial*
>(mat);
180 _ht_agl_ft = inpos.getElevationFt() - height_m * SG_METER_TO_FEET;
183 const std::vector<std::string>& names = material->get_names();
185 _solid = material->get_solid();
188 props->setStringValue(
"material/name", names[0].c_str());
190 props->setStringValue(
"material/name",
"");
208void FGAIEscort::setParent()
210 double lat =
_selected_ac->getDoubleValue(
"position/latitude-deg");
211 double lon =
_selected_ac->getDoubleValue(
"position/longitude-deg");
213 _MPControl =
_selected_ac->getBoolValue(
"controls/mp-control");
215 _selectedpos.setLatitudeDeg(lat);
216 _selectedpos.setLongitudeDeg(lon);
219 _parent_speed =
_selected_ac->getDoubleValue(
"velocities/speed-kts");
220 _parent_hdg =
_selected_ac->getDoubleValue(
"orientation/true-heading-deg");
223 _stn_truebrg = calcTrueBearingDeg(_stn_brg, _parent_hdg);
224 _stn_relbrg = _stn_brg;
227 _stn_truebrg = _stn_brg;
234 SGGeodesy::direct( _selectedpos, _stn_truebrg, _stn_range * SG_NM_TO_METER,
237 _tgtpos.setElevationFt(_stn_height);
239 calcRangeBearing(
pos.getLatitudeDeg(),
pos.getLongitudeDeg(),
240 _tgtpos.getLatitudeDeg(), _tgtpos.getLongitudeDeg(), _tgtrange, _tgtbrg);
246void FGAIEscort::calcRangeBearing(
double lat,
double lon,
double lat2,
double lon2,
247 double &range,
double &bearing)
const
250 double az2, distance;
251 geo_inverse_wgs_84(lat, lon, lat2, lon2, &
bearing, &az2, &distance);
252 range = distance * SG_METER_TO_NM;
255double FGAIEscort::calcTrueBearingDeg(
double bearing,
double heading)
257 double angle =
bearing + heading;
258 SG_NORMALIZE_RANGE(angle, 0.0, 360.0);
262SGVec3d FGAIEscort::getCartHitchPosAt(
const SGVec3d& _off)
const {
263 double hdg =
_selected_ac->getDoubleValue(
"orientation/true-heading-deg");
268 SGQuatd hlTrans = SGQuatd::fromLonLat(_selectedpos);
272 hlTrans *= SGQuatd::fromYawPitchRollDeg(
hdg,
pitch,
roll);
276 SGVec3d off = hlTrans.backTransform(_off);
279 SGVec3d cartPos = SGVec3d::fromGeod(_selectedpos);
281 return cartPos + off;
285void FGAIEscort::setStationSpeed(){
292 if (_MPControl && _tgtrange > 4.0 * _stn_limit) {
293 SG_LOG(SG_AI, SG_ALERT,
"AIEscort: " <<
_name
294 <<
" re-aligning to MP pos");
298 }
else if ((_relbrg < -90.0 || _relbrg > 90.0) && _tgtrange > _stn_limit) {
301 if(_tgtrange > 4.0 * _stn_limit)
302 speed = 4.0 * -_stn_speed;
306 }
else if ((_relbrg >= -90.0 && _relbrg <= 90.0) && _tgtrange > _stn_limit) {
309 if(_tgtrange > 4.0 * _stn_limit)
310 speed = 4.0 * _stn_speed;
316 angle = 15.0 * sg_random();
317 speed = 5.0 * sg_random();
324 double station_speed = _parent_speed +
speed;
326 SG_CLAMP_RANGE(station_speed, 5.0,
_max_speed);
327 SG_CLAMP_RANGE(angle, -_stn_angle_limit, _stn_angle_limit);
330 TurnTo(_parent_hdg + angle);
334void FGAIEscort::RunEscort(
double dt){
void setName(const std::string &n)
void setCallSign(const std::string &)
void setParentName(const std::string &p)
SGPropertyNode_ptr _selected_ac
void setSMPath(const std::string &p)
double calcRelBearingDeg(double bearing, double heading)
void tie(const char *aRelPath, const SGRawValue< T > &aRawValue)
Tied-properties helper, record nodes which are tied for easy un-tie-ing.
bool init(ModelSearchOrder searchOrder) override
void readFromScenario(SGPropertyNode *scFileNode) override
void update(double dt) override
void readFromScenario(SGPropertyNode *scFileNode) override
void ClimbTo(double altitude)
void update(double dt) override
void TurnTo(double heading)
void AccelTo(double speed)
FGAIShip(object_type ot=object_type::otShip)
bool init(ModelSearchOrder searchOrder) override
FGScenery * get_scenery() const
bool get_elevation_m(const SGGeod &geod, double &alt, const simgear::BVHMaterial **material, const osg::Node *butNotFrom=0)
Compute the elevation of the scenery at geodetic latitude lat, geodetic longitude lon and not higher ...