Add support for tunnel, y-offset and limit update rate
Signed-off-by: vmeazza <vivian.meazza@lineone.net>
This commit is contained in:
parent
949981a6d7
commit
5c7d8c7b68
5 changed files with 340 additions and 250 deletions
|
@ -37,11 +37,16 @@ FGAIShip(otGroundVehicle),
|
||||||
_pitch(0),
|
_pitch(0),
|
||||||
_pitch_deg(0),
|
_pitch_deg(0),
|
||||||
_speed_kt(0),
|
_speed_kt(0),
|
||||||
|
_selected_ac(0),
|
||||||
_range_ft(0),
|
_range_ft(0),
|
||||||
_relbrg (0),
|
_relbrg (0),
|
||||||
_parent_speed(0),
|
_parent_speed(0),
|
||||||
|
_dt_count(0),
|
||||||
|
_next_run(0),
|
||||||
_parent_x_offset(0),
|
_parent_x_offset(0),
|
||||||
_selected_ac(0)
|
_parent_y_offset(0),
|
||||||
|
_parent("")
|
||||||
|
|
||||||
{
|
{
|
||||||
invisible = false;
|
invisible = false;
|
||||||
}
|
}
|
||||||
|
@ -57,14 +62,15 @@ void FGAIGroundVehicle::readFromScenario(SGPropertyNode* scFileNode) {
|
||||||
setNoRoll(scFileNode->getBoolValue("no-roll", true));
|
setNoRoll(scFileNode->getBoolValue("no-roll", true));
|
||||||
setName(scFileNode->getStringValue("name", "groundvehicle"));
|
setName(scFileNode->getStringValue("name", "groundvehicle"));
|
||||||
setSMPath(scFileNode->getStringValue("submodel-path", ""));
|
setSMPath(scFileNode->getStringValue("submodel-path", ""));
|
||||||
setContactX1offset(scFileNode->getDoubleValue("contact_x1_offset", 0.0));
|
setContactX1offset(scFileNode->getDoubleValue("contact-x1-offset", 0.0));
|
||||||
setContactX2offset(scFileNode->getDoubleValue("contact_x2_offset", 0.0));
|
setContactX2offset(scFileNode->getDoubleValue("contact-x2-offset", 0.0));
|
||||||
setXOffset(scFileNode->getDoubleValue("hitch-x-offset", 38.55));
|
setXOffset(scFileNode->getDoubleValue("hitch-x-offset", 38.55));
|
||||||
|
setYOffset(scFileNode->getDoubleValue("hitch-y-offset", 0.0));
|
||||||
setPitchoffset(scFileNode->getDoubleValue("pitch-offset", 0.0));
|
setPitchoffset(scFileNode->getDoubleValue("pitch-offset", 0.0));
|
||||||
setRolloffset(scFileNode->getDoubleValue("roll-offset", 0.0));
|
setRolloffset(scFileNode->getDoubleValue("roll-offset", 0.0));
|
||||||
setYawoffset(scFileNode->getDoubleValue("yaw-offset", 0.0));
|
setYawoffset(scFileNode->getDoubleValue("yaw-offset", 0.0));
|
||||||
setPitchCoeff(scFileNode->getDoubleValue("pitch-coefficient", 0.5));
|
setPitchCoeff(scFileNode->getDoubleValue("pitch-coefficient", 0.1));
|
||||||
setElevCoeff(scFileNode->getDoubleValue("elevation-coefficient", 0.5));
|
setElevCoeff(scFileNode->getDoubleValue("elevation-coefficient", 0.25));
|
||||||
setParentName(scFileNode->getStringValue("parent", ""));
|
setParentName(scFileNode->getStringValue("parent", ""));
|
||||||
setTowAngleGain(scFileNode->getDoubleValue("tow-angle-gain", 2.0));
|
setTowAngleGain(scFileNode->getDoubleValue("tow-angle-gain", 2.0));
|
||||||
setTowAngleLimit(scFileNode->getDoubleValue("tow-angle-limit-deg", 2.0));
|
setTowAngleLimit(scFileNode->getDoubleValue("tow-angle-limit-deg", 2.0));
|
||||||
|
@ -91,29 +97,20 @@ void FGAIGroundVehicle::bind() {
|
||||||
SGRawValuePointer<double>(&_range_ft));
|
SGRawValuePointer<double>(&_range_ft));
|
||||||
props->tie("hitch/x-offset-ft",
|
props->tie("hitch/x-offset-ft",
|
||||||
SGRawValuePointer<double>(&_x_offset));
|
SGRawValuePointer<double>(&_x_offset));
|
||||||
|
props->tie("hitch/y-offset-ft",
|
||||||
|
SGRawValuePointer<double>(&_y_offset));
|
||||||
props->tie("hitch/parent-x-offset-ft",
|
props->tie("hitch/parent-x-offset-ft",
|
||||||
SGRawValuePointer<double>(&_parent_x_offset));
|
SGRawValuePointer<double>(&_parent_x_offset));
|
||||||
|
props->tie("hitch/parent-y-offset-ft",
|
||||||
|
SGRawValuePointer<double>(&_parent_y_offset));
|
||||||
props->tie("controls/constants/tow-angle/gain",
|
props->tie("controls/constants/tow-angle/gain",
|
||||||
SGRawValuePointer<double>(&_tow_angle_gain));
|
SGRawValuePointer<double>(&_tow_angle_gain));
|
||||||
props->tie("controls/constants/tow-angle/limit-deg",
|
props->tie("controls/constants/tow-angle/limit-deg",
|
||||||
SGRawValuePointer<double>(&_tow_angle_limit));
|
SGRawValuePointer<double>(&_tow_angle_limit));
|
||||||
|
props->tie("controls/contact-x1-offset-ft",
|
||||||
|
SGRawValuePointer<double>(&_contact_x1_offset));
|
||||||
//we may need these later for towed vehicles
|
props->tie("controls/contact-x2-offset-ft",
|
||||||
|
SGRawValuePointer<double>(&_contact_x2_offset));
|
||||||
// (*this, &FGAIBallistic::getElevHitchToUser));
|
|
||||||
//props->tie("position/x-offset",
|
|
||||||
// SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getXOffset, &FGAIBase::setXoffset));
|
|
||||||
//props->tie("position/y-offset",
|
|
||||||
// SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getYOffset, &FGAIBase::setYoffset));
|
|
||||||
//props->tie("position/z-offset",
|
|
||||||
// SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getZOffset, &FGAIBase::setZoffset));
|
|
||||||
//props->tie("position/tgt-x-offset",
|
|
||||||
// SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtXOffset, &FGAIWingman::setTgtXOffset));
|
|
||||||
//props->tie("position/tgt-y-offset",
|
|
||||||
// SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtYOffset, &FGAIWingman::setTgtYOffset));
|
|
||||||
//props->tie("position/tgt-z-offset",
|
|
||||||
// SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtZOffset, &FGAIWingman::setTgtZOffset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIGroundVehicle::unbind() {
|
void FGAIGroundVehicle::unbind() {
|
||||||
|
@ -126,20 +123,13 @@ void FGAIGroundVehicle::unbind() {
|
||||||
props->untie("hitch/tow-angle-deg");
|
props->untie("hitch/tow-angle-deg");
|
||||||
props->untie("hitch/range-ft");
|
props->untie("hitch/range-ft");
|
||||||
props->untie("hitch/x-offset-ft");
|
props->untie("hitch/x-offset-ft");
|
||||||
|
props->untie("hitch/y-offset-ft");
|
||||||
props->untie("hitch/parent-x-offset-ft");
|
props->untie("hitch/parent-x-offset-ft");
|
||||||
|
props->untie("hitch/parent-y-offset-ft");
|
||||||
props->untie("controls/constants/tow-angle/gain");
|
props->untie("controls/constants/tow-angle/gain");
|
||||||
props->untie("controls/constants/tow-angle/limit-deg");
|
props->untie("controls/constants/tow-angle/limit-deg");
|
||||||
|
props->untie("controls/contact-x1-offset-ft");
|
||||||
//we may need these later for towed vehicles
|
props->untie("controls/contact-x2-offset-ft");
|
||||||
//props->untie("load/rel-brg-to-user-deg");
|
|
||||||
//props->untie("load/elev-to-user-deg");
|
|
||||||
//props->untie("velocities/vertical-speed-fps");
|
|
||||||
//props->untie("position/x-offset");
|
|
||||||
//props->untie("position/y-offset");
|
|
||||||
//props->untie("position/z-offset");
|
|
||||||
//props->untie("position/tgt-x-offset");
|
|
||||||
//props->untie("position/tgt-y-offset");
|
|
||||||
//props->untie("position/tgt-z-offset");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAIGroundVehicle::init(bool search_in_AI_path) {
|
bool FGAIGroundVehicle::init(bool search_in_AI_path) {
|
||||||
|
@ -147,7 +137,6 @@ bool FGAIGroundVehicle::init(bool search_in_AI_path) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
invisible = false;
|
invisible = false;
|
||||||
|
|
||||||
_limit = 200;
|
_limit = 200;
|
||||||
no_roll = true;
|
no_roll = true;
|
||||||
|
|
||||||
|
@ -157,77 +146,8 @@ bool FGAIGroundVehicle::init(bool search_in_AI_path) {
|
||||||
void FGAIGroundVehicle::update(double dt) {
|
void FGAIGroundVehicle::update(double dt) {
|
||||||
// SG_LOG(SG_GENERAL, SG_ALERT, "updating GroundVehicle: " << _name );
|
// SG_LOG(SG_GENERAL, SG_ALERT, "updating GroundVehicle: " << _name );
|
||||||
|
|
||||||
if (getPitch()){
|
RunGroundVehicle(dt);
|
||||||
setElevation(_elevation, dt, _elevation_coeff);
|
// FGAIShip::update(dt);
|
||||||
ClimbTo(_elevation_ft);
|
|
||||||
setPitch(_pitch, dt, _pitch_coeff);
|
|
||||||
PitchTo(_pitch_deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_parent !=""){
|
|
||||||
setParent();
|
|
||||||
|
|
||||||
string parent_next_name = _selected_ac->getStringValue("waypoint/name-next");
|
|
||||||
bool parent_waiting = _selected_ac->getBoolValue("waypoint/waiting");
|
|
||||||
_parent_speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt");
|
|
||||||
|
|
||||||
if (parent_next_name == "END" && fp->getNextWaypoint()->name != "END" ){
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
|
||||||
<< " setting END: getting new waypoints ");
|
|
||||||
AdvanceFP();
|
|
||||||
setWPNames();
|
|
||||||
/*} else if (parent_next_name == "WAIT" && fp->getNextWaypoint()->name != "WAIT" ){*/
|
|
||||||
} else if (parent_waiting && !_waiting){
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
|
||||||
<< " setting WAIT/WAITUNTIL: getting new waypoints ");
|
|
||||||
AdvanceFP();
|
|
||||||
setWPNames();
|
|
||||||
_waiting = true;
|
|
||||||
} else if (parent_next_name != "WAIT" && fp->getNextWaypoint()->name == "WAIT"){
|
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
|
||||||
<< " wait done: getting new waypoints ");
|
|
||||||
_waiting = false;
|
|
||||||
_wait_count = 0;
|
|
||||||
fp->IncrementWaypoint(false);
|
|
||||||
next = fp->getNextWaypoint();
|
|
||||||
|
|
||||||
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|
|
||||||
|| next->name == "END"){
|
|
||||||
} else {
|
|
||||||
prev = curr;
|
|
||||||
fp->IncrementWaypoint(false);
|
|
||||||
curr = fp->getCurrentWaypoint();
|
|
||||||
next = fp->getNextWaypoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
setWPNames();
|
|
||||||
} else if (_range_ft > 1000){
|
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "AIGroundVeh1cle: " << _name
|
|
||||||
<< " rescue: reforming train " << _range_ft << " " << _x_offset * 15);
|
|
||||||
|
|
||||||
setTowAngle(0, dt, 1);
|
|
||||||
setSpeed(_parent_speed * 2);
|
|
||||||
|
|
||||||
} else if (_parent_speed > 1){
|
|
||||||
|
|
||||||
setTowSpeed();
|
|
||||||
setTowAngle(_relbrg, dt, 1);
|
|
||||||
|
|
||||||
} else if (_parent_speed < -1){
|
|
||||||
|
|
||||||
setTowSpeed();
|
|
||||||
|
|
||||||
if (_relbrg < 0)
|
|
||||||
setTowAngle(-(180 - (360 + _relbrg)), dt, 1);
|
|
||||||
else
|
|
||||||
setTowAngle(-(180 - _relbrg), dt, 1);
|
|
||||||
|
|
||||||
} else
|
|
||||||
setSpeed(_parent_speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
FGAIShip::update(dt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIGroundVehicle::setNoRoll(bool nr) {
|
void FGAIGroundVehicle::setNoRoll(bool nr) {
|
||||||
|
@ -246,6 +166,10 @@ void FGAIGroundVehicle::setXOffset(double x) {
|
||||||
_x_offset = x;
|
_x_offset = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGAIGroundVehicle::setYOffset(double y) {
|
||||||
|
_y_offset = y;
|
||||||
|
}
|
||||||
|
|
||||||
void FGAIGroundVehicle::setPitchCoeff(double pc) {
|
void FGAIGroundVehicle::setPitchCoeff(double pc) {
|
||||||
_pitch_coeff = pc;
|
_pitch_coeff = pc;
|
||||||
}
|
}
|
||||||
|
@ -277,26 +201,22 @@ void FGAIGroundVehicle::setParentName(const string& p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIGroundVehicle::setTowAngle(double ta, double dt, double coeff){
|
void FGAIGroundVehicle::setTowAngle(double ta, double dt, double coeff){
|
||||||
ta *= _tow_angle_gain;
|
//_tow_angle = ta * _tow_angle_gain;
|
||||||
//_tow_angle = pow(ta,2) * sign(ta);
|
_tow_angle = pow(ta,2) * sign(ta);
|
||||||
//if (_tow_angle > _tow_angle_limit) _tow_angle = _tow_angle_limit;
|
|
||||||
//if (_tow_angle < -_tow_angle_limit) _tow_angle = -_tow_angle_limit;
|
|
||||||
SG_CLAMP_RANGE(_tow_angle, -_tow_angle_limit, _tow_angle_limit);
|
SG_CLAMP_RANGE(_tow_angle, -_tow_angle_limit, _tow_angle_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAIGroundVehicle::getGroundElev(SGGeod inpos) {
|
bool FGAIGroundVehicle::getGroundElev(SGGeod inpos) {
|
||||||
|
|
||||||
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 10000),
|
double height_m ;
|
||||||
_elevation_m, &_material)){
|
|
||||||
_ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET;
|
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 10000), height_m, &_material,0)){
|
||||||
|
_ht_agl_ft = inpos.getElevationFt() - height_m * SG_METER_TO_FEET;
|
||||||
|
|
||||||
if (_material) {
|
if (_material) {
|
||||||
const vector<string>& names = _material->get_names();
|
const vector<string>& names = _material->get_names();
|
||||||
|
|
||||||
_solid = _material->get_solid();
|
_solid = _material->get_solid();
|
||||||
_load_resistance = _material->get_load_resistance();
|
|
||||||
_frictionFactor =_material->get_friction_factor();
|
|
||||||
_elevation = _elevation_m * SG_METER_TO_FEET;
|
|
||||||
|
|
||||||
if (!names.empty())
|
if (!names.empty())
|
||||||
props->setStringValue("material/name", names[0].c_str());
|
props->setStringValue("material/name", names[0].c_str());
|
||||||
|
@ -321,58 +241,89 @@ bool FGAIGroundVehicle::getGroundElev(SGGeod inpos) {
|
||||||
|
|
||||||
bool FGAIGroundVehicle::getPitch() {
|
bool FGAIGroundVehicle::getPitch() {
|
||||||
|
|
||||||
double vel = props->getDoubleValue("velocities/true-airspeed-kt", 0);
|
if (!_tunnel){
|
||||||
double contact_offset_x1_m = _contact_x1_offset * SG_FEET_TO_METER;
|
|
||||||
double contact_offset_x2_m = _contact_x2_offset * SG_FEET_TO_METER;
|
|
||||||
|
|
||||||
SGVec3d front(-contact_offset_x1_m, 0, 0);
|
double vel = props->getDoubleValue("velocities/true-airspeed-kt", 0);
|
||||||
SGVec3d rear(-contact_offset_x2_m, 0, 0);
|
double contact_offset_x1_m = _contact_x1_offset * SG_FEET_TO_METER;
|
||||||
SGVec3d Front = getCartPosAt(front);
|
double contact_offset_x2_m = _contact_x2_offset * SG_FEET_TO_METER;
|
||||||
SGVec3d Rear = getCartPosAt(rear);
|
|
||||||
|
|
||||||
SGGeod geodFront = SGGeod::fromCart(Front);
|
SGVec3d front(-contact_offset_x1_m, 0, 0);
|
||||||
SGGeod geodRear = SGGeod::fromCart(Rear);
|
SGVec3d rear(-contact_offset_x2_m, 0, 0);
|
||||||
|
SGVec3d Front = getCartPosAt(front);
|
||||||
|
SGVec3d Rear = getCartPosAt(rear);
|
||||||
|
|
||||||
double front_elev_m = 0;
|
SGGeod geodFront = SGGeod::fromCart(Front);
|
||||||
double rear_elev_m = 0;
|
SGGeod geodRear = SGGeod::fromCart(Rear);
|
||||||
double elev_front = 0;
|
|
||||||
double elev_rear = 0;
|
|
||||||
|
|
||||||
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(geodFront, 10000),
|
double front_elev_m = 0;
|
||||||
elev_front, &_material)){
|
double rear_elev_m = 0;
|
||||||
|
double elev_front = 0;
|
||||||
|
double elev_rear = 0;
|
||||||
|
double max_alt = 10000;
|
||||||
|
|
||||||
front_elev_m = elev_front;
|
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(geodFront, 10000), elev_front,
|
||||||
|
&_material, 0)){
|
||||||
|
front_elev_m = elev_front;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
//if (_material) {
|
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(geodRear, 10000),
|
||||||
//
|
elev_rear, &_material,0)){
|
||||||
//}
|
rear_elev_m = elev_rear;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
} else
|
if (vel >= 0){
|
||||||
return false;
|
double diff = front_elev_m - rear_elev_m;
|
||||||
|
_pitch = atan2 (diff,
|
||||||
|
fabs(contact_offset_x1_m) + fabs(contact_offset_x2_m)) * SG_RADIANS_TO_DEGREES;
|
||||||
|
_elevation = (rear_elev_m + diff/2) * SG_METER_TO_FEET;
|
||||||
|
} else {
|
||||||
|
double diff = rear_elev_m - front_elev_m;
|
||||||
|
_pitch = atan2 (diff,
|
||||||
|
fabs(contact_offset_x1_m) + fabs(contact_offset_x2_m)) * SG_RADIANS_TO_DEGREES;
|
||||||
|
_elevation = (front_elev_m + diff/2) * SG_METER_TO_FEET;
|
||||||
|
_pitch = -_pitch;
|
||||||
|
}
|
||||||
|
|
||||||
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(geodRear, 10000),
|
|
||||||
elev_rear, &_material)){
|
|
||||||
rear_elev_m = elev_rear;
|
|
||||||
//if (_material) {
|
|
||||||
// rear_elev_m = elev_rear;
|
|
||||||
//}
|
|
||||||
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (vel >= 0){
|
|
||||||
double diff = front_elev_m - rear_elev_m;
|
|
||||||
_pitch = atan2 (diff,
|
|
||||||
fabs(contact_offset_x1_m) + fabs(contact_offset_x2_m)) * SG_RADIANS_TO_DEGREES;
|
|
||||||
_elevation = (rear_elev_m + diff/2) * SG_METER_TO_FEET;
|
|
||||||
} else {
|
} else {
|
||||||
double diff = rear_elev_m - front_elev_m;
|
|
||||||
_pitch = atan2 (diff,
|
if (prev->altitude == 0 || curr->altitude == 0) return false;
|
||||||
fabs(contact_offset_x1_m) + fabs(contact_offset_x2_m)) * SG_RADIANS_TO_DEGREES;
|
|
||||||
_elevation = (front_elev_m + diff/2) * SG_METER_TO_FEET;
|
static double distance;
|
||||||
_pitch = -_pitch;
|
static double d_alt;
|
||||||
|
static double curr_alt;
|
||||||
|
static double prev_alt;
|
||||||
|
|
||||||
|
if (_new_waypoint){
|
||||||
|
curr_alt = curr->altitude * SG_METER_TO_FEET;
|
||||||
|
prev_alt = prev->altitude * SG_METER_TO_FEET;
|
||||||
|
d_alt = curr_alt - prev_alt;
|
||||||
|
|
||||||
|
distance = SGGeodesy::distanceM(SGGeod::fromDeg(prev->longitude, prev->latitude),
|
||||||
|
SGGeod::fromDeg(curr->longitude, curr->latitude));
|
||||||
|
|
||||||
|
_pitch = atan2(d_alt, distance * SG_METER_TO_FEET) * SG_RADIANS_TO_DEGREES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double distance_to_go = SGGeodesy::distanceM(SGGeod::fromDeg(pos.getLongitudeDeg(), pos.getLatitudeDeg()),
|
||||||
|
SGGeod::fromDeg(curr->longitude, curr->latitude));
|
||||||
|
|
||||||
|
//cout << "distance curr & prev " << prev->name << " " << curr->name << " " << distance * SG_METER_TO_FEET
|
||||||
|
// << " distance to go " << distance_to_go * SG_METER_TO_FEET
|
||||||
|
// << " d_alt ft " << d_alt
|
||||||
|
// << endl;
|
||||||
|
|
||||||
|
if (distance_to_go > distance)
|
||||||
|
_elevation = prev_alt;
|
||||||
|
else
|
||||||
|
_elevation = curr_alt - (tan(_pitch * SG_DEGREES_TO_RADIANS) * distance_to_go * SG_METER_TO_FEET);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getGroundElev(pos);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,6 +338,7 @@ void FGAIGroundVehicle::setParent() {
|
||||||
model = _selected_ac;
|
model = _selected_ac;
|
||||||
} else {
|
} else {
|
||||||
model = ai->getChild(i);
|
model = ai->getChild(i);
|
||||||
|
string path = ai->getPath();
|
||||||
const string name = model->getStringValue("name");
|
const string name = model->getStringValue("name");
|
||||||
|
|
||||||
if (!model->nChildren()){
|
if (!model->nChildren()){
|
||||||
|
@ -408,12 +360,20 @@ void FGAIGroundVehicle::setParent() {
|
||||||
double lat = _selected_ac->getDoubleValue("position/latitude-deg");
|
double lat = _selected_ac->getDoubleValue("position/latitude-deg");
|
||||||
double lon = _selected_ac->getDoubleValue("position/longitude-deg");
|
double lon = _selected_ac->getDoubleValue("position/longitude-deg");
|
||||||
double elevation = _selected_ac->getDoubleValue("position/altitude-ft");
|
double elevation = _selected_ac->getDoubleValue("position/altitude-ft");
|
||||||
double hitch_offset_m = _x_offset * SG_FEET_TO_METER;
|
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;
|
||||||
|
|
||||||
_selectedpos.setLatitudeDeg(lat);
|
_selectedpos.setLatitudeDeg(lat);
|
||||||
_selectedpos.setLongitudeDeg(lon);
|
_selectedpos.setLongitudeDeg(lon);
|
||||||
_selectedpos.setElevationFt(elevation);
|
_selectedpos.setElevationFt(elevation);
|
||||||
|
|
||||||
SGVec3d rear_hitch(-hitch_offset_m, 0, 0);
|
_parent_x_offset = _selected_ac->getDoubleValue("hitch/x-offset-ft");
|
||||||
|
_parent_y_offset = _selected_ac->getDoubleValue("hitch/y-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);
|
SGVec3d RearHitch = getCartHitchPosAt(rear_hitch);
|
||||||
|
|
||||||
SGGeod rearpos = SGGeod::fromCart(RearHitch);
|
SGGeod rearpos = SGGeod::fromCart(RearHitch);
|
||||||
|
@ -441,15 +401,13 @@ void FGAIGroundVehicle::calcRangeBearing(double lat, double lon, double lat2, do
|
||||||
// calculate the bearing and range of the second pos from the first
|
// calculate the bearing and range of the second pos from the first
|
||||||
double az2, distance;
|
double az2, distance;
|
||||||
geo_inverse_wgs_84(lat, lon, lat2, lon2, &bearing, &az2, &distance);
|
geo_inverse_wgs_84(lat, lon, lat2, lon2, &bearing, &az2, &distance);
|
||||||
range = distance *= SG_METER_TO_NM;
|
range = distance * SG_METER_TO_NM;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGAIGroundVehicle::calcRelBearingDeg(double bearing, double heading)
|
double FGAIGroundVehicle::calcRelBearingDeg(double bearing, double heading)
|
||||||
{
|
{
|
||||||
double angle = bearing - heading;
|
double angle = bearing - heading;
|
||||||
|
|
||||||
SG_NORMALIZE_RANGE(angle, -180.0, 180.0);
|
SG_NORMALIZE_RANGE(angle, -180.0, 180.0);
|
||||||
|
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,9 +493,7 @@ void FGAIGroundVehicle::AdvanceFP(){
|
||||||
|
|
||||||
void FGAIGroundVehicle::setTowSpeed(){
|
void FGAIGroundVehicle::setTowSpeed(){
|
||||||
|
|
||||||
_parent_x_offset = _selected_ac->getDoubleValue("hitch/x-offset-ft");
|
double diff = _range_ft - _x_offset;
|
||||||
|
|
||||||
// double diff = _range_ft - _parent_x_offset;
|
|
||||||
double x = 0;
|
double x = 0;
|
||||||
|
|
||||||
if (_range_ft > _x_offset * 3) x = 50;
|
if (_range_ft > _x_offset * 3) x = 50;
|
||||||
|
@ -545,11 +501,11 @@ void FGAIGroundVehicle::setTowSpeed(){
|
||||||
if (_relbrg < -90 || _relbrg > 90){
|
if (_relbrg < -90 || _relbrg > 90){
|
||||||
setSpeed(_parent_speed - 5 - x);
|
setSpeed(_parent_speed - 5 - x);
|
||||||
//cout << _name << " case 1r _relbrg spd - 5 " << _relbrg << " " << diff << endl;
|
//cout << _name << " case 1r _relbrg spd - 5 " << _relbrg << " " << diff << endl;
|
||||||
}else if (_range_ft > _parent_x_offset + 0.25 && _relbrg >= -90 && _relbrg <= 90){
|
}else if (_range_ft > _x_offset + 0.25 && _relbrg >= -90 && _relbrg <= 90){
|
||||||
setSpeed(_parent_speed + 1 + x);
|
setSpeed(_parent_speed + 1 + x);
|
||||||
//cout << _name << " case 2r _relbrg spd + 1 " << _relbrg << " "
|
//cout << _name << " case 2r _relbrg spd + 1 " << _relbrg << " "
|
||||||
// << diff << " range " << _range_ft << endl;
|
// << diff << " range " << _range_ft << endl;
|
||||||
} else if (_range_ft < _parent_x_offset - 0.25 && _relbrg >= -90 && _relbrg <= 90){
|
} else if (_range_ft < _x_offset - 0.25 && _relbrg >= -90 && _relbrg <= 90){
|
||||||
setSpeed(_parent_speed - 1 - x);
|
setSpeed(_parent_speed - 1 - x);
|
||||||
//cout << _name << " case 3r _relbrg spd - 2 " << _relbrg << " "
|
//cout << _name << " case 3r _relbrg spd - 2 " << _relbrg << " "
|
||||||
// << diff << " " << _range_ft << endl;
|
// << diff << " " << _range_ft << endl;
|
||||||
|
@ -559,4 +515,99 @@ void FGAIGroundVehicle::setTowSpeed(){
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGAIGroundVehicle::RunGroundVehicle(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.
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//cout << "_start_sec " << _start_sec << " time_sec " << time_sec << endl;
|
||||||
|
if (_dt_count < _next_run)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_next_run = 0.055 + (0.015 * sg_random());
|
||||||
|
|
||||||
|
if (getPitch()){
|
||||||
|
setElevation(_elevation, _dt_count, _elevation_coeff);
|
||||||
|
ClimbTo(_elevation_ft);
|
||||||
|
setPitch(_pitch, _dt_count, _pitch_coeff);
|
||||||
|
PitchTo(_pitch_deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_parent == ""){
|
||||||
|
AccelTo(prev->speed);
|
||||||
|
FGAIShip::update(_dt_count);
|
||||||
|
_dt_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParent();
|
||||||
|
|
||||||
|
string parent_next_name = _selected_ac->getStringValue("waypoint/name-next");
|
||||||
|
bool parent_waiting = _selected_ac->getBoolValue("waypoint/waiting");
|
||||||
|
|
||||||
|
if (parent_next_name == "END" && fp->getNextWaypoint()->name != "END" ){
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
||||||
|
<< " setting END: getting new waypoints ");
|
||||||
|
AdvanceFP();
|
||||||
|
setWPNames();
|
||||||
|
/*} else if (parent_next_name == "WAIT" && fp->getNextWaypoint()->name != "WAIT" ){*/
|
||||||
|
} else if (parent_waiting && !_waiting){
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
||||||
|
<< " setting WAIT/WAITUNTIL: getting new waypoints ");
|
||||||
|
AdvanceFP();
|
||||||
|
setWPNames();
|
||||||
|
_waiting = true;
|
||||||
|
} else if (parent_next_name != "WAIT" && fp->getNextWaypoint()->name == "WAIT"){
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
|
||||||
|
<< " wait done: getting new waypoints ");
|
||||||
|
_waiting = false;
|
||||||
|
_wait_count = 0;
|
||||||
|
fp->IncrementWaypoint(false);
|
||||||
|
next = fp->getNextWaypoint();
|
||||||
|
|
||||||
|
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|
||||||
|
|| next->name == "END"){
|
||||||
|
} else {
|
||||||
|
prev = curr;
|
||||||
|
fp->IncrementWaypoint(false);
|
||||||
|
curr = fp->getCurrentWaypoint();
|
||||||
|
next = fp->getNextWaypoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
setWPNames();
|
||||||
|
} else if (_range_ft > _parent_x_offset * 4){
|
||||||
|
SG_LOG(SG_GENERAL, SG_INFO, "AIGroundVeh1cle: " << _name
|
||||||
|
<< " rescue: reforming train " << _range_ft << " " << _x_offset * 15);
|
||||||
|
|
||||||
|
setTowAngle(0, dt, 1);
|
||||||
|
setSpeed(_parent_speed * 2);
|
||||||
|
|
||||||
|
} else if (_parent_speed > 1){
|
||||||
|
|
||||||
|
setTowSpeed();
|
||||||
|
setTowAngle(_relbrg, dt, 1);
|
||||||
|
|
||||||
|
} else if (_parent_speed < -1){
|
||||||
|
|
||||||
|
setTowSpeed();
|
||||||
|
|
||||||
|
if (_relbrg < 0)
|
||||||
|
setTowAngle(-(180 - (360 + _relbrg)), dt, 1);
|
||||||
|
else
|
||||||
|
setTowAngle(-(180 - _relbrg), dt, 1);
|
||||||
|
|
||||||
|
} else
|
||||||
|
setSpeed(_parent_speed);
|
||||||
|
|
||||||
|
FGAIShip::update(_dt_count);
|
||||||
|
_dt_count = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// end AIGroundvehicle
|
// end AIGroundvehicle
|
||||||
|
|
|
@ -52,6 +52,7 @@ private:
|
||||||
void setContactX1offset(double x1);
|
void setContactX1offset(double x1);
|
||||||
void setContactX2offset(double x2);
|
void setContactX2offset(double x2);
|
||||||
void setXOffset(double x);
|
void setXOffset(double x);
|
||||||
|
void setYOffset(double y);
|
||||||
|
|
||||||
void setPitchCoeff(double pc);
|
void setPitchCoeff(double pc);
|
||||||
void setElevCoeff(double ec);
|
void setElevCoeff(double ec);
|
||||||
|
@ -65,6 +66,7 @@ private:
|
||||||
void setParent();
|
void setParent();
|
||||||
void AdvanceFP();
|
void AdvanceFP();
|
||||||
void setTowSpeed();
|
void setTowSpeed();
|
||||||
|
void RunGroundVehicle(double dt);
|
||||||
|
|
||||||
bool getGroundElev(SGGeod inpos);
|
bool getGroundElev(SGGeod inpos);
|
||||||
bool getPitch();
|
bool getPitch();
|
||||||
|
@ -86,10 +88,11 @@ private:
|
||||||
double _contact_x1_offset, _contact_x2_offset, _contact_z_offset;
|
double _contact_x1_offset, _contact_x2_offset, _contact_z_offset;
|
||||||
double _pitch, _pitch_coeff, _pitch_deg;
|
double _pitch, _pitch_coeff, _pitch_deg;
|
||||||
double _speed_coeff, _speed_kt;
|
double _speed_coeff, _speed_kt;
|
||||||
double _x_offset;
|
double _x_offset, _y_offset;
|
||||||
double _range_ft;
|
double _range_ft;
|
||||||
double _relbrg;
|
double _relbrg;
|
||||||
double _parent_speed, _parent_x_offset;
|
double _parent_speed, _parent_x_offset, _parent_y_offset;
|
||||||
|
double _dt_count, _next_run;
|
||||||
|
|
||||||
const SGMaterial* _material;
|
const SGMaterial* _material;
|
||||||
const SGPropertyNode *_selected_ac;
|
const SGPropertyNode *_selected_ac;
|
||||||
|
|
|
@ -281,8 +281,8 @@ FGAIManager::processScenario( const string &filename ) {
|
||||||
continue;
|
continue;
|
||||||
std::string type = scEntry->getStringValue("type", "aircraft");
|
std::string type = scEntry->getStringValue("type", "aircraft");
|
||||||
|
|
||||||
if (type == "tanker") { // refueling scenarios
|
if (type == "tanker") { // refueling scenarios
|
||||||
FGAITanker* tanker = new FGAITanker;
|
FGAITanker* tanker = new FGAITanker;
|
||||||
tanker->readFromScenario(scEntry);
|
tanker->readFromScenario(scEntry);
|
||||||
attach(tanker);
|
attach(tanker);
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ FGAIManager::processScenario( const string &filename ) {
|
||||||
wingman->readFromScenario(scEntry);
|
wingman->readFromScenario(scEntry);
|
||||||
attach(wingman);
|
attach(wingman);
|
||||||
|
|
||||||
} else if (type == "aircraft") {
|
} else if (type == "aircraft") {
|
||||||
FGAIAircraft* aircraft = new FGAIAircraft;
|
FGAIAircraft* aircraft = new FGAIAircraft;
|
||||||
aircraft->readFromScenario(scEntry);
|
aircraft->readFromScenario(scEntry);
|
||||||
attach(aircraft);
|
attach(aircraft);
|
||||||
|
@ -406,14 +406,14 @@ FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range
|
||||||
tgt_ht[type] += fuse_range;
|
tgt_ht[type] += fuse_range;
|
||||||
|
|
||||||
if (fabs(tgt_alt - alt) > tgt_ht[type] || type == FGAIBase::otBallistic
|
if (fabs(tgt_alt - alt) > tgt_ht[type] || type == FGAIBase::otBallistic
|
||||||
|| type == FGAIBase::otStorm || type == FGAIBase::otThermal ) {
|
|| type == FGAIBase::otStorm || type == FGAIBase::otThermal ) {
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: skipping "
|
SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: skipping "
|
||||||
<< fabs(tgt_alt - alt)
|
<< fabs(tgt_alt - alt)
|
||||||
<< " "
|
<< " "
|
||||||
<< type
|
<< type
|
||||||
);
|
);
|
||||||
++ai_list_itr;
|
++ai_list_itr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double tgt_lat = (*ai_list_itr)->_getLatitude();
|
double tgt_lat = (*ai_list_itr)->_getLatitude();
|
||||||
|
|
|
@ -42,17 +42,36 @@
|
||||||
|
|
||||||
|
|
||||||
FGAIShip::FGAIShip(object_type ot) :
|
FGAIShip::FGAIShip(object_type ot) :
|
||||||
FGAIBase(ot),
|
FGAIBase(ot),
|
||||||
_limit(40),
|
_limit(40),
|
||||||
_elevation_m(0),
|
_elevation_m(0),
|
||||||
_elevation_ft(0),
|
_elevation_ft(0),
|
||||||
_tow_angle(0),
|
_tow_angle(0),
|
||||||
_dt_count(0),
|
_dt_count(0),
|
||||||
_next_run(0),
|
_next_run(0),
|
||||||
_lead_angle(0),
|
_lead_angle(0),
|
||||||
_xtrack_error(0)
|
_xtrack_error(0),
|
||||||
|
_tunnel(false),
|
||||||
|
_curr_alt(0),
|
||||||
|
_prev_alt(0),
|
||||||
|
_until_time(""),
|
||||||
|
_fp_init(false),
|
||||||
|
_missed(false),
|
||||||
|
_waiting(false),
|
||||||
|
_new_waypoint(true),
|
||||||
|
_missed_count(0),
|
||||||
|
_wait_count(0),
|
||||||
|
_missed_time_sec(30),
|
||||||
|
_day(86400),
|
||||||
|
_wp_range(0),
|
||||||
|
_old_range(0),
|
||||||
|
_range_rate(0),
|
||||||
|
_roll_constant(0.001),
|
||||||
|
_hdg_constant(0.01),
|
||||||
|
_roll_factor(-0.0083335)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
invisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGAIShip::~FGAIShip() {
|
FGAIShip::~FGAIShip() {
|
||||||
|
@ -79,7 +98,7 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) {
|
||||||
setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5));
|
setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5));
|
||||||
|
|
||||||
if (!flightplan.empty()) {
|
if (!flightplan.empty()) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name );
|
SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name );
|
||||||
|
|
||||||
FGAIFlightPlan* fp = new FGAIFlightPlan(flightplan);
|
FGAIFlightPlan* fp = new FGAIFlightPlan(flightplan);
|
||||||
setFlightPlan(fp);
|
setFlightPlan(fp);
|
||||||
|
@ -92,8 +111,6 @@ bool FGAIShip::init(bool search_in_AI_path) {
|
||||||
curr = 0; // the one ahead
|
curr = 0; // the one ahead
|
||||||
next = 0; // the next plus 1
|
next = 0; // the next plus 1
|
||||||
|
|
||||||
_until_time = "";
|
|
||||||
|
|
||||||
props->setStringValue("name", _name.c_str());
|
props->setStringValue("name", _name.c_str());
|
||||||
props->setStringValue("waypoint/name-prev", _prev_name.c_str());
|
props->setStringValue("waypoint/name-prev", _prev_name.c_str());
|
||||||
props->setStringValue("waypoint/name-curr", _curr_name.c_str());
|
props->setStringValue("waypoint/name-curr", _curr_name.c_str());
|
||||||
|
@ -106,27 +123,8 @@ bool FGAIShip::init(bool search_in_AI_path) {
|
||||||
_rudder = 0.0;
|
_rudder = 0.0;
|
||||||
no_roll = false;
|
no_roll = false;
|
||||||
|
|
||||||
_roll_constant = 0.001;
|
|
||||||
_hdg_constant = 0.01;
|
|
||||||
_roll_factor = -0.0083335;
|
|
||||||
|
|
||||||
_rd_turn_radius_ft = _sp_turn_radius_ft = turn_radius_ft;
|
_rd_turn_radius_ft = _sp_turn_radius_ft = turn_radius_ft;
|
||||||
|
|
||||||
_fp_init = false;
|
|
||||||
_missed = false;
|
|
||||||
_waiting = false;
|
|
||||||
_new_waypoint = true;
|
|
||||||
|
|
||||||
_missed_count = 0;
|
|
||||||
_wait_count = 0;
|
|
||||||
_missed_time_sec = 30;
|
|
||||||
|
|
||||||
_day = 86400;
|
|
||||||
|
|
||||||
|
|
||||||
_wp_range = _old_range = 0;
|
|
||||||
_range_rate = 0;
|
|
||||||
|
|
||||||
if (fp)
|
if (fp)
|
||||||
_fp_init = initFlightPlan();
|
_fp_init = initFlightPlan();
|
||||||
|
|
||||||
|
@ -178,6 +176,12 @@ void FGAIShip::bind() {
|
||||||
SGRawValuePointer<bool>(&_waiting));
|
SGRawValuePointer<bool>(&_waiting));
|
||||||
props->tie("waypoint/lead-angle-deg",
|
props->tie("waypoint/lead-angle-deg",
|
||||||
SGRawValuePointer<double>(&_lead_angle));
|
SGRawValuePointer<double>(&_lead_angle));
|
||||||
|
props->tie("waypoint/tunnel",
|
||||||
|
SGRawValuePointer<bool>(&_tunnel));
|
||||||
|
props->tie("waypoint/alt-curr-m",
|
||||||
|
SGRawValuePointer<double>(&_curr_alt));
|
||||||
|
props->tie("waypoint/alt-prev-m",
|
||||||
|
SGRawValuePointer<double>(&_prev_alt));
|
||||||
props->tie("submodels/serviceable",
|
props->tie("submodels/serviceable",
|
||||||
SGRawValuePointer<bool>(&_serviceable));
|
SGRawValuePointer<bool>(&_serviceable));
|
||||||
props->tie("controls/turn-radius-ft",
|
props->tie("controls/turn-radius-ft",
|
||||||
|
@ -216,6 +220,9 @@ void FGAIShip::unbind() {
|
||||||
props->untie("waypoint/lead-angle-deg");
|
props->untie("waypoint/lead-angle-deg");
|
||||||
props->untie("waypoint/xtrack-error-ft");
|
props->untie("waypoint/xtrack-error-ft");
|
||||||
props->untie("waypoint/waiting");
|
props->untie("waypoint/waiting");
|
||||||
|
props->untie("waypoint/tunnel");
|
||||||
|
props->untie("waypoint/alt-curr-m");
|
||||||
|
props->untie("waypoint/alt-prev-m");
|
||||||
props->untie("submodels/serviceable");
|
props->untie("submodels/serviceable");
|
||||||
props->untie("controls/turn-radius-ft");
|
props->untie("controls/turn-radius-ft");
|
||||||
props->untie("controls/turn-radius-corrected-ft");
|
props->untie("controls/turn-radius-corrected-ft");
|
||||||
|
@ -257,7 +264,7 @@ void FGAIShip::update(double dt) {
|
||||||
// Only change these values if we are able to compute them safely
|
// Only change these values if we are able to compute them safely
|
||||||
if (SGLimits<double>::min() < dt) {
|
if (SGLimits<double>::min() < dt) {
|
||||||
// Now here is the finite difference ...
|
// Now here is the finite difference ...
|
||||||
|
|
||||||
// Transform that one to the horizontal local coordinate system.
|
// Transform that one to the horizontal local coordinate system.
|
||||||
SGQuatd ec2hlNew = SGQuatd::fromLonLat(pos);
|
SGQuatd ec2hlNew = SGQuatd::fromLonLat(pos);
|
||||||
// compute the new orientation
|
// compute the new orientation
|
||||||
|
@ -268,7 +275,7 @@ void FGAIShip::update(double dt) {
|
||||||
dOr.getAngleAxis(dOrAngleAxis);
|
dOr.getAngleAxis(dOrAngleAxis);
|
||||||
// divided by the time difference provides a rotation speed vector
|
// divided by the time difference provides a rotation speed vector
|
||||||
dOrAngleAxis /= dt;
|
dOrAngleAxis /= dt;
|
||||||
|
|
||||||
aip.setBodyAngularVelocity(dOrAngleAxis);
|
aip.setBodyAngularVelocity(dOrAngleAxis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,7 +338,7 @@ void FGAIShip::Run(double dt) {
|
||||||
// adjust turn radius for speed. The equation is very approximate.
|
// adjust turn radius for speed. The equation is very approximate.
|
||||||
// we need to allow for negative speeds
|
// we need to allow for negative speeds
|
||||||
if (type == "ship")
|
if (type == "ship")
|
||||||
_sp_turn_radius_ft = 10 * pow ((fabs(speed) - 15), 2) + turn_radius_ft;
|
_sp_turn_radius_ft = 10 * pow ((fabs(speed) - 15), 2) + turn_radius_ft;
|
||||||
else
|
else
|
||||||
_sp_turn_radius_ft = turn_radius_ft;
|
_sp_turn_radius_ft = turn_radius_ft;
|
||||||
|
|
||||||
|
@ -399,10 +406,10 @@ void FGAIShip::Run(double dt) {
|
||||||
// set the _rudder limit by speed
|
// set the _rudder limit by speed
|
||||||
if (type == "ship"){
|
if (type == "ship"){
|
||||||
|
|
||||||
if (speed <= 40)
|
if (speed <= 40)
|
||||||
rudder_limit = (-0.825 * speed) + 35;
|
rudder_limit = (-0.825 * speed) + 35;
|
||||||
else
|
else
|
||||||
rudder_limit = 2;
|
rudder_limit = 2;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
rudder_limit = 20;
|
rudder_limit = 20;
|
||||||
|
@ -549,7 +556,7 @@ void FGAIShip::setWPNames() {
|
||||||
setPrevName("");
|
setPrevName("");
|
||||||
|
|
||||||
if (curr != 0)
|
if (curr != 0)
|
||||||
setCurrName(curr->name);
|
setCurrName(curr->name);
|
||||||
else{
|
else{
|
||||||
setCurrName("");
|
setCurrName("");
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
|
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
|
||||||
|
@ -594,9 +601,7 @@ double FGAIShip::getCourse(double lat, double lon, double lat2, double lon2) con
|
||||||
void FGAIShip::ProcessFlightPlan(double dt) {
|
void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
|
|
||||||
double time_sec = getDaySeconds();
|
double time_sec = getDaySeconds();
|
||||||
double until_time_sec = 0;
|
|
||||||
|
|
||||||
_missed = false;
|
|
||||||
_dt_count += dt;
|
_dt_count += dt;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -611,6 +616,9 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
|
|
||||||
_next_run = 1.0 + (0.5 * sg_random());
|
_next_run = 1.0 + (0.5 * sg_random());
|
||||||
|
|
||||||
|
double until_time_sec = 0;
|
||||||
|
_missed = false;
|
||||||
|
|
||||||
// check to see if we've reached the point for our next turn
|
// check to see if we've reached the point for our next turn
|
||||||
// if the range to the waypoint is less than the calculated turn
|
// if the range to the waypoint is less than the calculated turn
|
||||||
// radius we can start the turn to the next leg
|
// radius we can start the turn to the next leg
|
||||||
|
@ -646,7 +654,24 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
|
|
||||||
if ((_wp_range < (sp_turn_radius_nm * 1.25)) || _missed || (_waiting && !_new_waypoint)) {
|
if ((_wp_range < (sp_turn_radius_nm * 1.25)) || _missed || (_waiting && !_new_waypoint)) {
|
||||||
|
|
||||||
if (_next_name == "END" || fp->getNextWaypoint() == 0) {
|
if (_next_name == "TUNNEL"){
|
||||||
|
_tunnel = !_tunnel;
|
||||||
|
|
||||||
|
//SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " TUNNEL ");
|
||||||
|
|
||||||
|
fp->IncrementWaypoint(false);
|
||||||
|
next = fp->getNextWaypoint();
|
||||||
|
|
||||||
|
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|
||||||
|
|| next->name == "END" || next->name == "TUNNEL")
|
||||||
|
return;
|
||||||
|
|
||||||
|
prev = curr;
|
||||||
|
fp->IncrementWaypoint(false);
|
||||||
|
curr = fp->getCurrentWaypoint();
|
||||||
|
next = fp->getNextWaypoint();
|
||||||
|
|
||||||
|
}else if(_next_name == "END" || fp->getNextWaypoint() == 0) {
|
||||||
|
|
||||||
if (_repeat) {
|
if (_repeat) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << "Flightplan restarting ");
|
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << "Flightplan restarting ");
|
||||||
|
@ -688,7 +713,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
next = fp->getNextWaypoint();
|
next = fp->getNextWaypoint();
|
||||||
|
|
||||||
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|
||||||
|| next->name == "END")
|
|| next->name == "END" || next->name == "TUNNEL")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prev = curr;
|
prev = curr;
|
||||||
|
@ -703,7 +728,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
_until_time = next->time;
|
_until_time = next->time;
|
||||||
setUntilTime(next->time);
|
setUntilTime(next->time);
|
||||||
if (until_time_sec > time_sec) {
|
if (until_time_sec > time_sec) {
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " "
|
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " "
|
||||||
<< curr->name << " waiting until: "
|
<< curr->name << " waiting until: "
|
||||||
<< _until_time << " " << until_time_sec << " now " << time_sec );
|
<< _until_time << " " << until_time_sec << " now " << time_sec );
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
|
@ -748,7 +773,13 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
_wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
|
_wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
|
||||||
_old_range = _wp_range;
|
_old_range = _wp_range;
|
||||||
setWPPos();
|
setWPPos();
|
||||||
AccelTo(prev->speed);
|
object_type type = getType();
|
||||||
|
|
||||||
|
if (type != 10)
|
||||||
|
AccelTo(prev->speed);
|
||||||
|
|
||||||
|
_curr_alt = curr->altitude;
|
||||||
|
_prev_alt = prev->altitude;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_new_waypoint = false;
|
_new_waypoint = false;
|
||||||
|
@ -762,7 +793,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
|
||||||
else
|
else
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: Bearing or Range is not a finite number");
|
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: Bearing or Range is not a finite number");
|
||||||
|
|
||||||
_dt_count = 0;
|
_dt_count = 0;
|
||||||
} // end Processing FlightPlan
|
} // end Processing FlightPlan
|
||||||
|
|
||||||
bool FGAIShip::initFlightPlan() {
|
bool FGAIShip::initFlightPlan() {
|
||||||
|
@ -770,7 +801,6 @@ bool FGAIShip::initFlightPlan() {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " initializing waypoints ");
|
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " initializing waypoints ");
|
||||||
|
|
||||||
bool init = false;
|
bool init = false;
|
||||||
|
|
||||||
_start_sec = 0;
|
_start_sec = 0;
|
||||||
|
|
||||||
fp->restart();
|
fp->restart();
|
||||||
|
@ -785,7 +815,7 @@ bool FGAIShip::initFlightPlan() {
|
||||||
fp->IncrementWaypoint(false);
|
fp->IncrementWaypoint(false);
|
||||||
curr = fp->getCurrentWaypoint();
|
curr = fp->getCurrentWaypoint();
|
||||||
next = fp->getNextWaypoint();
|
next = fp->getNextWaypoint();
|
||||||
}
|
} // end while loop
|
||||||
|
|
||||||
if (!_start_time.empty()){
|
if (!_start_time.empty()){
|
||||||
_start_sec = processTimeString(_start_time);
|
_start_sec = processTimeString(_start_time);
|
||||||
|
@ -814,9 +844,9 @@ bool FGAIShip::initFlightPlan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setLatitude(prev->latitude);
|
setLatitude(prev->latitude);
|
||||||
setLongitude(prev->longitude);
|
setLongitude(prev->longitude);
|
||||||
setSpeed(prev->speed);
|
setSpeed(prev->speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
setWPNames();
|
setWPNames();
|
||||||
|
@ -907,11 +937,11 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
|
||||||
next = fp->getNextWaypoint();
|
next = fp->getNextWaypoint();
|
||||||
|
|
||||||
if (next->name != "WAITUNTIL" && next->name != "WAIT"
|
if (next->name != "WAITUNTIL" && next->name != "WAIT"
|
||||||
&& next->name != "END") {
|
&& next->name != "END") {
|
||||||
prev = curr;
|
prev = curr;
|
||||||
fp->IncrementWaypoint(false);
|
fp->IncrementWaypoint(false);
|
||||||
curr = fp->getCurrentWaypoint();
|
curr = fp->getCurrentWaypoint();
|
||||||
next = fp->getNextWaypoint();
|
next = fp->getNextWaypoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (next->name == "WAITUNTIL") {
|
} else if (next->name == "WAITUNTIL") {
|
||||||
|
@ -958,8 +988,8 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
|
||||||
// so we will calculate the distance back up the track from the current waypoint
|
// so we will calculate the distance back up the track from the current waypoint
|
||||||
// then calculate the lat and lon.
|
// then calculate the lat and lon.
|
||||||
|
|
||||||
/*cout << "advancing flight plan done elapsed_sec: " << elapsed_sec
|
//cout << "advancing flight plan done elapsed_sec: " << elapsed_sec
|
||||||
<< " " << day_sec << endl;*/
|
// << " " << day_sec << endl;
|
||||||
|
|
||||||
double time_diff = elapsed_sec - day_sec;
|
double time_diff = elapsed_sec - day_sec;
|
||||||
double lat, lon, recip;
|
double lat, lon, recip;
|
||||||
|
@ -1002,15 +1032,16 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
|
||||||
|
|
||||||
void FGAIShip::setWPPos() {
|
void FGAIShip::setWPPos() {
|
||||||
|
|
||||||
if (curr->name == "END" || curr->name == "WAIT" || curr->name == "WAITUNTIL"){
|
if (curr->name == "END" || curr->name == "WAIT"
|
||||||
cout<< curr->name << endl;
|
|| curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){
|
||||||
return;
|
//cout << curr->name << " returning" << endl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double elevation_m = 0;
|
double elevation_m = 0;
|
||||||
wppos.setLatitudeDeg(curr->latitude);
|
wppos.setLatitudeDeg(curr->latitude);
|
||||||
wppos.setLongitudeDeg(curr->longitude);
|
wppos.setLongitudeDeg(curr->longitude);
|
||||||
wppos.setElevationFt(0);
|
wppos.setElevationM(0);
|
||||||
|
|
||||||
if (curr->on_ground){
|
if (curr->on_ground){
|
||||||
|
|
||||||
|
@ -1019,10 +1050,15 @@ void FGAIShip::setWPPos() {
|
||||||
wppos.setElevationM(elevation_m);
|
wppos.setElevationM(elevation_m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//cout << curr->name << " setting measured elev " << elevation_m << endl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
wppos.setElevationFt(curr->altitude);
|
wppos.setElevationM(curr->altitude);
|
||||||
|
//cout << curr->name << " setting FP elev " << elevation_m << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curr->altitude = wppos.getElevationM();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIShip::setXTrackError() {
|
void FGAIShip::setXTrackError() {
|
||||||
|
@ -1033,7 +1069,6 @@ void FGAIShip::setXTrackError() {
|
||||||
curr->latitude, curr->longitude);
|
curr->latitude, curr->longitude);
|
||||||
double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range;
|
double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range;
|
||||||
|
|
||||||
//if (_wp_range > _sp_turn_radius_ft / (2 * 6076.1155)){
|
|
||||||
if (_wp_range > 0){
|
if (_wp_range > 0){
|
||||||
_lead_angle = atan2(xtrack_error_nm,(_wp_range * _proportion)) * SG_RADIANS_TO_DEGREES;
|
_lead_angle = atan2(xtrack_error_nm,(_wp_range * _proportion)) * SG_RADIANS_TO_DEGREES;
|
||||||
} else
|
} else
|
||||||
|
@ -1042,9 +1077,6 @@ void FGAIShip::setXTrackError() {
|
||||||
_lead_angle *= _lead_angle_gain;
|
_lead_angle *= _lead_angle_gain;
|
||||||
_xtrack_error = xtrack_error_nm * 6076.1155;
|
_xtrack_error = xtrack_error_nm * 6076.1155;
|
||||||
|
|
||||||
if (_lead_angle<= -_lead_angle_limit)
|
SG_CLAMP_RANGE(_lead_angle, -_lead_angle_limit, _lead_angle_limit);
|
||||||
_lead_angle = -_lead_angle_limit;
|
|
||||||
else if (_lead_angle >= _lead_angle_limit)
|
|
||||||
_lead_angle = _lead_angle_limit;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,17 +62,20 @@ public:
|
||||||
void setSpeedConstant(double sc);
|
void setSpeedConstant(double sc);
|
||||||
void setFixedTurnRadius(double ft);
|
void setFixedTurnRadius(double ft);
|
||||||
void setWPNames();
|
void setWPNames();
|
||||||
|
void setWPPos();
|
||||||
double sign(double x);
|
double sign(double x);
|
||||||
|
|
||||||
bool _hdg_lock;
|
bool _hdg_lock;
|
||||||
bool _serviceable;
|
bool _serviceable;
|
||||||
bool _waiting;
|
bool _waiting;
|
||||||
bool _new_waypoint;
|
bool _new_waypoint;
|
||||||
|
bool _tunnel;
|
||||||
|
|
||||||
|
|
||||||
virtual const char* getTypeString(void) const { return "ship"; }
|
virtual const char* getTypeString(void) const { return "ship"; }
|
||||||
double _rudder_constant, _speed_constant, _hdg_constant, _limit ;
|
double _rudder_constant, _speed_constant, _hdg_constant, _limit ;
|
||||||
double _elevation_m, _elevation_ft;
|
double _elevation_m, _elevation_ft;
|
||||||
double _missed_range, _tow_angle, _wait_count;
|
double _missed_range, _tow_angle, _wait_count, _wp_range;
|
||||||
|
|
||||||
FGAIFlightPlan::waypoint* prev; // the one behind you
|
FGAIFlightPlan::waypoint* prev; // the one behind you
|
||||||
FGAIFlightPlan::waypoint* curr; // the one ahead
|
FGAIFlightPlan::waypoint* curr; // the one ahead
|
||||||
|
@ -95,7 +98,7 @@ private:
|
||||||
void Run(double dt);
|
void Run(double dt);
|
||||||
void setStartTime(const string&);
|
void setStartTime(const string&);
|
||||||
void setUntilTime(const string&);
|
void setUntilTime(const string&);
|
||||||
void setWPPos();
|
//void setWPPos();
|
||||||
void setWPAlt();
|
void setWPAlt();
|
||||||
void setXTrackError();
|
void setXTrackError();
|
||||||
|
|
||||||
|
@ -115,7 +118,7 @@ private:
|
||||||
|
|
||||||
double _roll_constant, _roll_factor;
|
double _roll_constant, _roll_factor;
|
||||||
double _sp_turn_radius_ft, _rd_turn_radius_ft, _fixed_turn_radius;
|
double _sp_turn_radius_ft, _rd_turn_radius_ft, _fixed_turn_radius;
|
||||||
double _wp_range, _old_range, _range_rate;
|
double _old_range, _range_rate;
|
||||||
double _dt_count, _missed_count;
|
double _dt_count, _missed_count;
|
||||||
double _next_run;
|
double _next_run;
|
||||||
double _missed_time_sec;
|
double _missed_time_sec;
|
||||||
|
@ -125,6 +128,7 @@ private:
|
||||||
double _lead_angle_gain, _lead_angle_limit, _proportion;
|
double _lead_angle_gain, _lead_angle_limit, _proportion;
|
||||||
double _course;
|
double _course;
|
||||||
double _xtrack_error;
|
double _xtrack_error;
|
||||||
|
double _curr_alt, _prev_alt;
|
||||||
|
|
||||||
string _prev_name, _curr_name, _next_name;
|
string _prev_name, _curr_name, _next_name;
|
||||||
string _path;
|
string _path;
|
||||||
|
|
Loading…
Add table
Reference in a new issue