diff --git a/src/AIModel/AIGroundVehicle.cxx b/src/AIModel/AIGroundVehicle.cxx index 75f18b9c7..82901e527 100644 --- a/src/AIModel/AIGroundVehicle.cxx +++ b/src/AIModel/AIGroundVehicle.cxx @@ -37,11 +37,16 @@ FGAIShip(otGroundVehicle), _pitch(0), _pitch_deg(0), _speed_kt(0), +_selected_ac(0), _range_ft(0), _relbrg (0), _parent_speed(0), +_dt_count(0), +_next_run(0), _parent_x_offset(0), -_selected_ac(0) +_parent_y_offset(0), +_parent("") + { invisible = false; } @@ -57,14 +62,15 @@ void FGAIGroundVehicle::readFromScenario(SGPropertyNode* scFileNode) { setNoRoll(scFileNode->getBoolValue("no-roll", true)); setName(scFileNode->getStringValue("name", "groundvehicle")); setSMPath(scFileNode->getStringValue("submodel-path", "")); - setContactX1offset(scFileNode->getDoubleValue("contact_x1_offset", 0.0)); - setContactX2offset(scFileNode->getDoubleValue("contact_x2_offset", 0.0)); + setContactX1offset(scFileNode->getDoubleValue("contact-x1-offset", 0.0)); + setContactX2offset(scFileNode->getDoubleValue("contact-x2-offset", 0.0)); setXOffset(scFileNode->getDoubleValue("hitch-x-offset", 38.55)); + setYOffset(scFileNode->getDoubleValue("hitch-y-offset", 0.0)); setPitchoffset(scFileNode->getDoubleValue("pitch-offset", 0.0)); setRolloffset(scFileNode->getDoubleValue("roll-offset", 0.0)); setYawoffset(scFileNode->getDoubleValue("yaw-offset", 0.0)); - setPitchCoeff(scFileNode->getDoubleValue("pitch-coefficient", 0.5)); - setElevCoeff(scFileNode->getDoubleValue("elevation-coefficient", 0.5)); + setPitchCoeff(scFileNode->getDoubleValue("pitch-coefficient", 0.1)); + setElevCoeff(scFileNode->getDoubleValue("elevation-coefficient", 0.25)); setParentName(scFileNode->getStringValue("parent", "")); setTowAngleGain(scFileNode->getDoubleValue("tow-angle-gain", 2.0)); setTowAngleLimit(scFileNode->getDoubleValue("tow-angle-limit-deg", 2.0)); @@ -91,29 +97,20 @@ void FGAIGroundVehicle::bind() { SGRawValuePointer(&_range_ft)); props->tie("hitch/x-offset-ft", SGRawValuePointer(&_x_offset)); + props->tie("hitch/y-offset-ft", + SGRawValuePointer(&_y_offset)); props->tie("hitch/parent-x-offset-ft", SGRawValuePointer(&_parent_x_offset)); + props->tie("hitch/parent-y-offset-ft", + SGRawValuePointer(&_parent_y_offset)); props->tie("controls/constants/tow-angle/gain", SGRawValuePointer(&_tow_angle_gain)); props->tie("controls/constants/tow-angle/limit-deg", SGRawValuePointer(&_tow_angle_limit)); - - - //we may need these later for towed vehicles - - // (*this, &FGAIBallistic::getElevHitchToUser)); - //props->tie("position/x-offset", - // SGRawValueMethods(*this, &FGAIBase::_getXOffset, &FGAIBase::setXoffset)); - //props->tie("position/y-offset", - // SGRawValueMethods(*this, &FGAIBase::_getYOffset, &FGAIBase::setYoffset)); - //props->tie("position/z-offset", - // SGRawValueMethods(*this, &FGAIBase::_getZOffset, &FGAIBase::setZoffset)); - //props->tie("position/tgt-x-offset", - // SGRawValueMethods(*this, &FGAIWingman::getTgtXOffset, &FGAIWingman::setTgtXOffset)); - //props->tie("position/tgt-y-offset", - // SGRawValueMethods(*this, &FGAIWingman::getTgtYOffset, &FGAIWingman::setTgtYOffset)); - //props->tie("position/tgt-z-offset", - // SGRawValueMethods(*this, &FGAIWingman::getTgtZOffset, &FGAIWingman::setTgtZOffset)); + props->tie("controls/contact-x1-offset-ft", + SGRawValuePointer(&_contact_x1_offset)); + props->tie("controls/contact-x2-offset-ft", + SGRawValuePointer(&_contact_x2_offset)); } void FGAIGroundVehicle::unbind() { @@ -126,20 +123,13 @@ void FGAIGroundVehicle::unbind() { props->untie("hitch/tow-angle-deg"); props->untie("hitch/range-ft"); props->untie("hitch/x-offset-ft"); + props->untie("hitch/y-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/limit-deg"); - - //we may need these later for towed vehicles - //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"); + props->untie("controls/contact-x1-offset-ft"); + props->untie("controls/contact-x2-offset-ft"); } bool FGAIGroundVehicle::init(bool search_in_AI_path) { @@ -147,7 +137,6 @@ bool FGAIGroundVehicle::init(bool search_in_AI_path) { return false; invisible = false; - _limit = 200; no_roll = true; @@ -157,77 +146,8 @@ bool FGAIGroundVehicle::init(bool search_in_AI_path) { void FGAIGroundVehicle::update(double dt) { // SG_LOG(SG_GENERAL, SG_ALERT, "updating GroundVehicle: " << _name ); - if (getPitch()){ - setElevation(_elevation, dt, _elevation_coeff); - 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); + RunGroundVehicle(dt); +// FGAIShip::update(dt); } void FGAIGroundVehicle::setNoRoll(bool nr) { @@ -246,6 +166,10 @@ void FGAIGroundVehicle::setXOffset(double x) { _x_offset = x; } +void FGAIGroundVehicle::setYOffset(double y) { + _y_offset = y; +} + void FGAIGroundVehicle::setPitchCoeff(double pc) { _pitch_coeff = pc; } @@ -277,26 +201,22 @@ void FGAIGroundVehicle::setParentName(const string& p) { } void FGAIGroundVehicle::setTowAngle(double ta, double dt, double coeff){ - ta *= _tow_angle_gain; - //_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; + //_tow_angle = ta * _tow_angle_gain; + _tow_angle = pow(ta,2) * sign(ta); SG_CLAMP_RANGE(_tow_angle, -_tow_angle_limit, _tow_angle_limit); } bool FGAIGroundVehicle::getGroundElev(SGGeod inpos) { - if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(inpos, 10000), - _elevation_m, &_material)){ - _ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET; + double height_m ; + + 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) { const vector& names = _material->get_names(); _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()) props->setStringValue("material/name", names[0].c_str()); @@ -321,58 +241,89 @@ bool FGAIGroundVehicle::getGroundElev(SGGeod inpos) { bool FGAIGroundVehicle::getPitch() { - double vel = props->getDoubleValue("velocities/true-airspeed-kt", 0); - double contact_offset_x1_m = _contact_x1_offset * SG_FEET_TO_METER; - double contact_offset_x2_m = _contact_x2_offset * SG_FEET_TO_METER; + if (!_tunnel){ - SGVec3d front(-contact_offset_x1_m, 0, 0); - SGVec3d rear(-contact_offset_x2_m, 0, 0); - SGVec3d Front = getCartPosAt(front); - SGVec3d Rear = getCartPosAt(rear); + double vel = props->getDoubleValue("velocities/true-airspeed-kt", 0); + double contact_offset_x1_m = _contact_x1_offset * SG_FEET_TO_METER; + double contact_offset_x2_m = _contact_x2_offset * SG_FEET_TO_METER; - SGGeod geodFront = SGGeod::fromCart(Front); - SGGeod geodRear = SGGeod::fromCart(Rear); + SGVec3d front(-contact_offset_x1_m, 0, 0); + SGVec3d rear(-contact_offset_x2_m, 0, 0); + SGVec3d Front = getCartPosAt(front); + SGVec3d Rear = getCartPosAt(rear); - double front_elev_m = 0; - double rear_elev_m = 0; - double elev_front = 0; - double elev_rear = 0; + SGGeod geodFront = SGGeod::fromCart(Front); + SGGeod geodRear = SGGeod::fromCart(Rear); - if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(geodFront, 10000), - elev_front, &_material)){ + double front_elev_m = 0; + 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 - 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 { + 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 { - 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 (prev->altitude == 0 || curr->altitude == 0) return false; + + static double distance; + 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; } @@ -387,6 +338,7 @@ void FGAIGroundVehicle::setParent() { model = _selected_ac; } else { model = ai->getChild(i); + string path = ai->getPath(); const string name = model->getStringValue("name"); if (!model->nChildren()){ @@ -408,12 +360,20 @@ 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"); - 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.setLongitudeDeg(lon); _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); 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 double 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 angle = bearing - heading; - SG_NORMALIZE_RANGE(angle, -180.0, 180.0); - return angle; } @@ -535,9 +493,7 @@ void FGAIGroundVehicle::AdvanceFP(){ void FGAIGroundVehicle::setTowSpeed(){ - _parent_x_offset = _selected_ac->getDoubleValue("hitch/x-offset-ft"); - - // double diff = _range_ft - _parent_x_offset; + double diff = _range_ft - _x_offset; double x = 0; if (_range_ft > _x_offset * 3) x = 50; @@ -545,11 +501,11 @@ void FGAIGroundVehicle::setTowSpeed(){ if (_relbrg < -90 || _relbrg > 90){ setSpeed(_parent_speed - 5 - x); //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); //cout << _name << " case 2r _relbrg spd + 1 " << _relbrg << " " // << 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); //cout << _name << " case 3r _relbrg spd - 2 " << _relbrg << " " // << 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 diff --git a/src/AIModel/AIGroundVehicle.hxx b/src/AIModel/AIGroundVehicle.hxx index c38a9b827..9be902c8a 100644 --- a/src/AIModel/AIGroundVehicle.hxx +++ b/src/AIModel/AIGroundVehicle.hxx @@ -52,6 +52,7 @@ private: void setContactX1offset(double x1); void setContactX2offset(double x2); void setXOffset(double x); + void setYOffset(double y); void setPitchCoeff(double pc); void setElevCoeff(double ec); @@ -65,6 +66,7 @@ private: void setParent(); void AdvanceFP(); void setTowSpeed(); + void RunGroundVehicle(double dt); bool getGroundElev(SGGeod inpos); bool getPitch(); @@ -86,10 +88,11 @@ private: double _contact_x1_offset, _contact_x2_offset, _contact_z_offset; double _pitch, _pitch_coeff, _pitch_deg; double _speed_coeff, _speed_kt; - double _x_offset; + double _x_offset, _y_offset; double _range_ft; 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 SGPropertyNode *_selected_ac; diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index c0a4517f9..9813b9dc2 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -281,8 +281,8 @@ FGAIManager::processScenario( const string &filename ) { continue; std::string type = scEntry->getStringValue("type", "aircraft"); - if (type == "tanker") { // refueling scenarios - FGAITanker* tanker = new FGAITanker; + if (type == "tanker") { // refueling scenarios + FGAITanker* tanker = new FGAITanker; tanker->readFromScenario(scEntry); attach(tanker); @@ -291,7 +291,7 @@ FGAIManager::processScenario( const string &filename ) { wingman->readFromScenario(scEntry); attach(wingman); - } else if (type == "aircraft") { + } else if (type == "aircraft") { FGAIAircraft* aircraft = new FGAIAircraft; aircraft->readFromScenario(scEntry); attach(aircraft); @@ -406,14 +406,14 @@ FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range tgt_ht[type] += fuse_range; if (fabs(tgt_alt - alt) > tgt_ht[type] || type == FGAIBase::otBallistic - || type == FGAIBase::otStorm || type == FGAIBase::otThermal ) { - SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: skipping " - << fabs(tgt_alt - alt) - << " " - << type - ); - ++ai_list_itr; - continue; + || type == FGAIBase::otStorm || type == FGAIBase::otThermal ) { + SG_LOG(SG_GENERAL, SG_DEBUG, "AIManager: skipping " + << fabs(tgt_alt - alt) + << " " + << type + ); + ++ai_list_itr; + continue; } double tgt_lat = (*ai_list_itr)->_getLatitude(); diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index f484b6ac7..3a2e83ec0 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -42,17 +42,36 @@ FGAIShip::FGAIShip(object_type ot) : - FGAIBase(ot), - _limit(40), - _elevation_m(0), - _elevation_ft(0), - _tow_angle(0), - _dt_count(0), - _next_run(0), - _lead_angle(0), - _xtrack_error(0) +FGAIBase(ot), +_limit(40), +_elevation_m(0), +_elevation_ft(0), +_tow_angle(0), +_dt_count(0), +_next_run(0), +_lead_angle(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() { @@ -79,7 +98,7 @@ void FGAIShip::readFromScenario(SGPropertyNode* scFileNode) { setSpeedConstant(scFileNode->getDoubleValue("speed-constant", 0.5)); 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); setFlightPlan(fp); @@ -92,8 +111,6 @@ bool FGAIShip::init(bool search_in_AI_path) { curr = 0; // the one ahead next = 0; // the next plus 1 - _until_time = ""; - props->setStringValue("name", _name.c_str()); props->setStringValue("waypoint/name-prev", _prev_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; 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; - _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) _fp_init = initFlightPlan(); @@ -178,6 +176,12 @@ void FGAIShip::bind() { SGRawValuePointer(&_waiting)); props->tie("waypoint/lead-angle-deg", SGRawValuePointer(&_lead_angle)); + props->tie("waypoint/tunnel", + SGRawValuePointer(&_tunnel)); + props->tie("waypoint/alt-curr-m", + SGRawValuePointer(&_curr_alt)); + props->tie("waypoint/alt-prev-m", + SGRawValuePointer(&_prev_alt)); props->tie("submodels/serviceable", SGRawValuePointer(&_serviceable)); props->tie("controls/turn-radius-ft", @@ -216,6 +220,9 @@ void FGAIShip::unbind() { props->untie("waypoint/lead-angle-deg"); props->untie("waypoint/xtrack-error-ft"); 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("controls/turn-radius-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 if (SGLimits::min() < dt) { // Now here is the finite difference ... - + // Transform that one to the horizontal local coordinate system. SGQuatd ec2hlNew = SGQuatd::fromLonLat(pos); // compute the new orientation @@ -268,7 +275,7 @@ void FGAIShip::update(double dt) { dOr.getAngleAxis(dOrAngleAxis); // divided by the time difference provides a rotation speed vector dOrAngleAxis /= dt; - + aip.setBodyAngularVelocity(dOrAngleAxis); } } @@ -331,7 +338,7 @@ void FGAIShip::Run(double dt) { // adjust turn radius for speed. The equation is very approximate. // we need to allow for negative speeds 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 _sp_turn_radius_ft = turn_radius_ft; @@ -399,10 +406,10 @@ void FGAIShip::Run(double dt) { // set the _rudder limit by speed if (type == "ship"){ - if (speed <= 40) - rudder_limit = (-0.825 * speed) + 35; - else - rudder_limit = 2; + if (speed <= 40) + rudder_limit = (-0.825 * speed) + 35; + else + rudder_limit = 2; } else rudder_limit = 20; @@ -549,7 +556,7 @@ void FGAIShip::setWPNames() { setPrevName(""); if (curr != 0) - setCurrName(curr->name); + setCurrName(curr->name); else{ setCurrName(""); 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) { double time_sec = getDaySeconds(); - double until_time_sec = 0; - _missed = false; _dt_count += dt; /////////////////////////////////////////////////////////////////////////// @@ -611,6 +616,9 @@ void FGAIShip::ProcessFlightPlan(double dt) { _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 // if the range to the waypoint is less than the calculated turn // 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 (_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) { SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << "Flightplan restarting "); @@ -688,7 +713,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { next = fp->getNextWaypoint(); if (next->name == "WAITUNTIL" || next->name == "WAIT" - || next->name == "END") + || next->name == "END" || next->name == "TUNNEL") return; prev = curr; @@ -703,7 +728,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { _until_time = next->time; setUntilTime(next->time); 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: " << _until_time << " " << until_time_sec << " now " << time_sec ); setSpeed(0); @@ -748,7 +773,13 @@ void FGAIShip::ProcessFlightPlan(double dt) { _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude); _old_range = _wp_range; setWPPos(); - AccelTo(prev->speed); + object_type type = getType(); + + if (type != 10) + AccelTo(prev->speed); + + _curr_alt = curr->altitude; + _prev_alt = prev->altitude; } else { _new_waypoint = false; @@ -762,7 +793,7 @@ void FGAIShip::ProcessFlightPlan(double dt) { else SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: Bearing or Range is not a finite number"); - _dt_count = 0; + _dt_count = 0; } // end Processing FlightPlan bool FGAIShip::initFlightPlan() { @@ -770,7 +801,6 @@ bool FGAIShip::initFlightPlan() { SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " initializing waypoints "); bool init = false; - _start_sec = 0; fp->restart(); @@ -785,7 +815,7 @@ bool FGAIShip::initFlightPlan() { fp->IncrementWaypoint(false); curr = fp->getCurrentWaypoint(); next = fp->getNextWaypoint(); - } + } // end while loop if (!_start_time.empty()){ _start_sec = processTimeString(_start_time); @@ -814,9 +844,9 @@ bool FGAIShip::initFlightPlan() { } } else { - setLatitude(prev->latitude); - setLongitude(prev->longitude); - setSpeed(prev->speed); + setLatitude(prev->latitude); + setLongitude(prev->longitude); + setSpeed(prev->speed); } setWPNames(); @@ -907,11 +937,11 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) { next = fp->getNextWaypoint(); if (next->name != "WAITUNTIL" && next->name != "WAIT" - && next->name != "END") { - prev = curr; - fp->IncrementWaypoint(false); - curr = fp->getCurrentWaypoint(); - next = fp->getNextWaypoint(); + && next->name != "END") { + prev = curr; + fp->IncrementWaypoint(false); + curr = fp->getCurrentWaypoint(); + next = fp->getNextWaypoint(); } } 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 // then calculate the lat and lon. - /*cout << "advancing flight plan done elapsed_sec: " << elapsed_sec - << " " << day_sec << endl;*/ + //cout << "advancing flight plan done elapsed_sec: " << elapsed_sec + // << " " << day_sec << endl; double time_diff = elapsed_sec - day_sec; double lat, lon, recip; @@ -1002,15 +1032,16 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) { void FGAIShip::setWPPos() { - if (curr->name == "END" || curr->name == "WAIT" || curr->name == "WAITUNTIL"){ - cout<< curr->name << endl; - return; + if (curr->name == "END" || curr->name == "WAIT" + || curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){ + //cout << curr->name << " returning" << endl; + return; } double elevation_m = 0; wppos.setLatitudeDeg(curr->latitude); wppos.setLongitudeDeg(curr->longitude); - wppos.setElevationFt(0); + wppos.setElevationM(0); if (curr->on_ground){ @@ -1019,10 +1050,15 @@ void FGAIShip::setWPPos() { wppos.setElevationM(elevation_m); } + //cout << curr->name << " setting measured elev " << elevation_m << endl; + } 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() { @@ -1033,7 +1069,6 @@ void FGAIShip::setXTrackError() { curr->latitude, curr->longitude); 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){ _lead_angle = atan2(xtrack_error_nm,(_wp_range * _proportion)) * SG_RADIANS_TO_DEGREES; } else @@ -1042,9 +1077,6 @@ void FGAIShip::setXTrackError() { _lead_angle *= _lead_angle_gain; _xtrack_error = xtrack_error_nm * 6076.1155; - if (_lead_angle<= -_lead_angle_limit) - _lead_angle = -_lead_angle_limit; - else if (_lead_angle >= _lead_angle_limit) - _lead_angle = _lead_angle_limit; + SG_CLAMP_RANGE(_lead_angle, -_lead_angle_limit, _lead_angle_limit); } diff --git a/src/AIModel/AIShip.hxx b/src/AIModel/AIShip.hxx index cf7f6c404..0526df32a 100644 --- a/src/AIModel/AIShip.hxx +++ b/src/AIModel/AIShip.hxx @@ -62,17 +62,20 @@ public: void setSpeedConstant(double sc); void setFixedTurnRadius(double ft); void setWPNames(); + void setWPPos(); double sign(double x); bool _hdg_lock; bool _serviceable; bool _waiting; bool _new_waypoint; + bool _tunnel; + virtual const char* getTypeString(void) const { return "ship"; } double _rudder_constant, _speed_constant, _hdg_constant, _limit ; 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* curr; // the one ahead @@ -95,7 +98,7 @@ private: void Run(double dt); void setStartTime(const string&); void setUntilTime(const string&); - void setWPPos(); + //void setWPPos(); void setWPAlt(); void setXTrackError(); @@ -115,7 +118,7 @@ private: double _roll_constant, _roll_factor; 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 _next_run; double _missed_time_sec; @@ -125,6 +128,7 @@ private: double _lead_angle_gain, _lead_angle_limit, _proportion; double _course; double _xtrack_error; + double _curr_alt, _prev_alt; string _prev_name, _curr_name, _next_name; string _path;