FGAIShip::FGAIShip(object_type ot) :
-FGAIBase(ot),
+// allow HOT to be enabled
+FGAIBase(ot, true),
+
+
+_waiting(false),
+_new_waypoint(true),
+_tunnel(false),
+_initial_tunnel(false),
+_restart(false),
+_hdg_constant(0.01),
_limit(100),
_elevation_m(0),
_elevation_ft(0),
_tow_angle(0),
+_missed_count(0),
+_wp_range(0),
_dt_count(0),
_next_run(0),
+_roll_constant(0.001),
+_roll_factor(-0.0083335),
+_old_range(0),
+_range_rate(0),
+_missed_time_sec(30),
+_day(86400),
_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),
-_restart(false)
-
+_missed(false)
{
invisible = false;
}
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", ""));
+ setRollFactor(scFileNode->getDoubleValue("roll-factor", 1));
if (!flightplan.empty()) {
- SG_LOG(SG_GENERAL, SG_ALERT, "getting flightplan: " << _name );
+ SG_LOG(SG_AI, SG_ALERT, "getting flightplan: " << _name );
FGAIFlightPlan* fp = new FGAIFlightPlan(flightplan);
setFlightPlan(fp);
}
bool FGAIShip::init(bool search_in_AI_path) {
+ reinit();
+ return FGAIBase::init(search_in_AI_path);
+}
+
+void FGAIShip::reinit()
+{
prev = 0; // the one behind you
curr = 0; // the one ahead
next = 0; // the next plus 1
if (fp)
_fp_init = initFlightPlan();
- return FGAIBase::init(search_in_AI_path);
+ FGAIBase::reinit();
}
void FGAIShip::bind() {
props->untie("velocities/speed-kts");
}
+
void FGAIShip::update(double dt) {
- //SG_LOG(SG_GENERAL, SG_ALERT, "updating Ship: " << _name <<hdg<<pitch<<roll);
+ //SG_LOG(SG_AI, SG_ALERT, "updating Ship: " << _name <<hdg<<pitch<<roll);
// For computation of rotation speeds we just use finite differences here.
// That is perfectly valid since this thing is not driven by accelerations
// but by just apply discrete changes at its velocity variables.
// 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
- SGVec3d cartPos = SGVec3d::fromGeod(pos);
+ // The cartesian position of the ship in the wgs84 world
+ //SGVec3d cartPos = SGVec3d::fromGeod(pos);
// The simulation time this transform is meant for
aip.setReferenceTime(globals->get_sim_time_sec());
fp = f;
}
-void FGAIShip::setName(const string& n) {
- _name = n;
-}
-
void FGAIShip::setStartTime(const string& st) {
_start_time = st;
}
_fixed_turn_radius = ftr;
}
+void FGAIShip::setRollFactor(double rf) {
+ _roll_factor = rf * -0.0083335;
+}
+
void FGAIShip::setInitialTunnel(bool t) {
_initial_tunnel = t;
setTunnel(_initial_tunnel);
void FGAIShip::setWPNames() {
if (prev != 0)
- setPrevName(prev->name);
+ setPrevName(prev->getName());
else
setPrevName("");
if (curr != 0)
- setCurrName(curr->name);
+ setCurrName(curr->getName());
else{
setCurrName("");
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
+ SG_LOG(SG_AI, SG_ALERT, "AIShip: current wp name error" );
}
if (next != 0)
- setNextName(next->name);
+ setNextName(next->getName());
else
setNextName("");
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: prev wp name " << prev->name);
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: current wp name " << curr->name);
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: next wp name " << next->name);
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: prev wp name " << prev->getName());
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: current wp name " << curr->getName());
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: next wp name " << next->getName());
}
geo_inverse_wgs_84(lat, lon, lat2, lon2, &course, &recip, &distance);
if (tgt_speed >= 0) {
return course;
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: course " << course);
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: course " << course);
} else {
return recip;
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: recip " << recip);
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: recip " << recip);
}
}
void FGAIShip::ProcessFlightPlan(double dt) {
+ if ( dt < 0.00001 ) {
+ return;
+ }
+
double time_sec = getDaySeconds();
_dt_count += dt;
// 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
- _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
+ _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_range_rate = (_wp_range - _old_range) / _dt_count;
double sp_turn_radius_nm = _sp_turn_radius_ft / 6076.1155;
// we need to try to identify a _missed waypoint
if (_next_name == "TUNNEL"){
_tunnel = !_tunnel;
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " " << sp_turn_radius_nm );
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: " << _name << " " << sp_turn_radius_nm );
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
- if (next->name == "WAITUNTIL" || next->name == "WAIT"
- || next->name == "END" || next->name == "TUNNEL")
+ if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
+ || next->getName() == "END" || next->getName() == "TUNNEL")
return;
prev = curr;
}else if(_next_name == "END" || fp->getNextWaypoint() == 0) {
if (_repeat) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: "<< _name << " Flightplan repeating ");
+ SG_LOG(SG_AI, SG_INFO, "AIShip: "<< _name << " Flightplan repeating ");
fp->restart();
prev = curr;
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
setWPNames();
- _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
+ _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range;
_range_rate = 0;
_new_waypoint = true;
_missed_count = 0;
_lead_angle = 0;
- AccelTo(prev->speed);
+ AccelTo(prev->getSpeed());
} else if (_restart){
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan restarting ");
+ SG_LOG(SG_AI, SG_INFO, "AIShip: " << _name << " Flightplan restarting ");
_missed_count = 0;
initFlightPlan();
} else {
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " Flightplan dying ");
+ SG_LOG(SG_AI, SG_ALERT, "AIShip: " << _name << " Flightplan dying ");
setDie(true);
_dt_count = 0;
return;
} else if (_next_name == "WAIT") {
- if (_wait_count < next->time_sec) {
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " waiting ");
+ if (_wait_count < next->getTime_sec()) {
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: " << _name << " waiting ");
setSpeed(0);
_waiting = true;
_wait_count += _dt_count;
_lead_angle = 0;
return;
} else {
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: " << _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" || next->name == "TUNNEL")
+ if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
+ || next->getName() == "END" || next->getName() == "TUNNEL")
return;
prev = curr;
} else if (_next_name == "WAITUNTIL") {
time_sec = getDaySeconds();
- until_time_sec = processTimeString(next->time);
- _until_time = next->time;
- setUntilTime(next->time);
+ until_time_sec = processTimeString(next->getTime());
+ _until_time = next->getTime();
+ setUntilTime(next->getTime());
if (until_time_sec > time_sec) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " "
- << curr->name << " waiting until: "
+ SG_LOG(SG_AI, SG_INFO, "AIShip: " << _name << " "
+ << curr->getName() << " waiting until: "
<< _until_time << " " << until_time_sec << " now " << time_sec );
setSpeed(0);
_lead_angle = 0;
_waiting = true;
return;
} else {
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: "
+ SG_LOG(SG_AI, SG_INFO, "AIShip: "
<< _name << " wait until done: getting new waypoints ");
setUntilTime("");
fp->IncrementWaypoint(false);
- while (next->name == "WAITUNTIL") {
+ while (next->getName() == "WAITUNTIL") {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
}
- if (next->name == "WAIT")
+ if (next->getName() == "WAIT")
return;
prev = curr;
} else {
//now reorganise the waypoints, so that next becomes current and so on
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " getting new waypoints ");
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: " << _name << " getting new waypoints ");
fp->IncrementWaypoint(false);
prev = fp->getPreviousWaypoint(); //first waypoint
curr = fp->getCurrentWaypoint(); //second waypoint
_missed_count = 0;
_range_rate = 0;
_lead_angle = 0;
- _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
+ _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range;
setWPPos();
object_type type = getType();
if (type != 10)
- AccelTo(prev->speed);
+ AccelTo(prev->getSpeed());
- _curr_alt = curr->altitude;
- _prev_alt = prev->altitude;
+ _curr_alt = curr->getAltitude();
+ _prev_alt = prev->getAltitude();
} else {
_new_waypoint = false;
}
// now revise the required course for the next way point
- _course = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude);
+ _course = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
if (finite(_course))
TurnTo(_course);
else
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: Bearing or Range is not a finite number");
+ SG_LOG(SG_AI, SG_ALERT, "AIShip: Bearing or Range is not a finite number");
_dt_count = 0;
} // end Processing FlightPlan
bool FGAIShip::initFlightPlan() {
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " initializing waypoints ");
+ SG_LOG(SG_AI, SG_ALERT, "AIShip: " << _name << " initializing waypoints ");
bool init = false;
_start_sec = 0;
curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!)
- while (curr->name == "WAIT" || curr->name == "WAITUNTIL") { // don't wait when initialising
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " re-initializing waypoints ");
+ while (curr->getName() == "WAIT" || curr->getName() == "WAITUNTIL") { // don't wait when initialising
+ SG_LOG(SG_AI, SG_DEBUG, "AIShip: " << _name << " re-initializing waypoints ");
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
}
} else {
- setLatitude(prev->latitude);
- setLongitude(prev->longitude);
- setSpeed(prev->speed);
+ setLatitude(prev->getLatitude());
+ setLongitude(prev->getLongitude());
+ setSpeed(prev->getSpeed());
}
setWPNames();
- setHeading(getCourse(prev->latitude, prev->longitude, curr->latitude, curr->longitude));
- _wp_range = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude);
+ setHeading(getCourse(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude()));
+ _wp_range = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range;
_range_rate = 0;
_hdg_lock = true;
_missed_count = 0;
_new_waypoint = true;
- SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: " << _name << " done initialising waypoints " << _tunnel);
+ SG_LOG(SG_AI, SG_ALERT, "AIShip: " << _name << " done initialising waypoints " << _tunnel);
if (prev)
init = true;
while ( elapsed_sec < day_sec ) {
- if (next->name == "END" || fp->getNextWaypoint() == 0) {
+ if (next->getName() == "END" || fp->getNextWaypoint() == 0) {
if (_repeat ) {
//cout << _name << ": " << "restarting flightplan" << endl;
return false;
}
- } else if (next->name == "WAIT") {
+ } else if (next->getName() == "WAIT") {
//cout << _name << ": begin WAIT: " << prev->name << " ";
//cout << curr->name << " " << next->name << endl;
- elapsed_sec += next->time_sec;
+ elapsed_sec += next->getTime_sec();
if ( elapsed_sec >= day_sec)
continue;
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
- if (next->name != "WAITUNTIL" && next->name != "WAIT"
- && next->name != "END") {
+ if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT"
+ && next->getName() != "END") {
prev = curr;
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
}
- } else if (next->name == "WAITUNTIL") {
- double until_sec = processTimeString(next->time);
+ } else if (next->getName() == "WAITUNTIL") {
+ double until_sec = processTimeString(next->getTime());
if (until_sec > _start_sec && start_sec < 0)
until_sec -= _day;
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
- if (next->name != "WAITUNTIL" && next->name != "WAIT") {
+ if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT") {
prev = curr;
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
//cout << prev->name << " " << curr->name << " " << next->name << endl;
} else {
- distance_nm = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude);
- elapsed_sec += distance_nm * 60 * 60 / prev->speed;
+ distance_nm = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
+ elapsed_sec += distance_nm * 60 * 60 / prev->getSpeed();
if (elapsed_sec >= day_sec)
continue;
//cout << " time diff " << time_diff << endl;
- if (next->name == "WAIT" ){
+ if (next->getName() == "WAIT" ){
setSpeed(0);
- lat = curr->latitude;
- lon = curr->longitude;
+ lat = curr->getLatitude();
+ lon = curr->getLongitude();
_wait_count= time_diff;
_waiting = true;
- } else if (next->name == "WAITUNTIL") {
+ } else if (next->getName() == "WAITUNTIL") {
setSpeed(0);
- lat = curr->latitude;
- lon = curr->longitude;
+ lat = curr->getLatitude();
+ lon = curr->getLongitude();
_waiting = true;
} else {
- setSpeed(prev->speed);
+ setSpeed(prev->getSpeed());
distance_nm = speed * time_diff / (60 * 60);
- double brg = getCourse(curr->latitude, curr->longitude, prev->latitude, prev->longitude);
+ double brg = getCourse(curr->getLatitude(), curr->getLongitude(), prev->getLatitude(), prev->getLongitude());
//cout << " brg " << brg << " from " << curr->name << " to " << prev->name << " "
// << " lat " << curr->latitude << " lon " << curr->longitude
// << " distance m " << distance_nm * SG_NM_TO_METER << endl;
- lat = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg,
+ lat = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
- lon = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg,
+ lon = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
- recip = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg,
+ recip = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
}
void FGAIShip::setWPPos() {
- if (curr->name == "END" || curr->name == "WAIT"
- || curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){
+ if (curr->getName() == "END" || curr->getName() == "WAIT"
+ || curr->getName() == "WAITUNTIL" || curr->getName() == "TUNNEL"){
//cout << curr->name << " returning" << endl;
return;
}
double elevation_m = 0;
- wppos.setLatitudeDeg(curr->latitude);
- wppos.setLongitudeDeg(curr->longitude);
+ wppos.setLatitudeDeg(curr->getLatitude());
+ wppos.setLongitudeDeg(curr->getLongitude());
wppos.setElevationM(0);
- if (curr->on_ground){
+ if (curr->getOn_ground()){
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 3000),
elevation_m, &_material, 0)){
//cout << curr->name << " setting measured elev " << elevation_m << endl;
} else {
- wppos.setElevationM(curr->altitude);
+ wppos.setElevationM(curr->getAltitude());
//cout << curr->name << " setting FP elev " << elevation_m << endl;
}
- curr->altitude = wppos.getElevationM();
+ curr->setAltitude(wppos.getElevationM());
}
void FGAIShip::setXTrackError() {
- double course = getCourse(prev->latitude, prev->longitude,
- curr->latitude, curr->longitude);
+ double course = getCourse(prev->getLatitude(), prev->getLongitude(),
+ curr->getLatitude(), curr->getLongitude());
double brg = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
- curr->latitude, curr->longitude);
+ curr->getLatitude(), curr->getLongitude());
double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range;
double factor = -0.0045 * speed + 1;
double limit = _lead_angle_limit * factor;