1
0
Fork 0

Add "expiry" parameter and other changes to implement persistent contrails using Ballistic objects

Signed-off-by: Vivian Meazza <vivian.meazza@lineone.net>
This commit is contained in:
Vivian Meazza 2010-07-28 22:20:50 +01:00
parent 6310fdd9c5
commit adf17287ab
5 changed files with 211 additions and 100 deletions

View file

@ -65,7 +65,8 @@ FGAIBallistic::FGAIBallistic(object_type ot) :
_report_impact(false), _report_impact(false),
_external_force(false), _external_force(false),
_impact_report_node(fgGetNode("/ai/models/model-impact", true)), _impact_report_node(fgGetNode("/ai/models/model-impact", true)),
_old_height(0) _old_height(0),
_elapsed_time(0)
{ {
no_roll = false; no_roll = false;
@ -82,6 +83,7 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
FGAIBase::readFromScenario(scFileNode); FGAIBase::readFromScenario(scFileNode);
//setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac")); //setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac"));
setRandom(scFileNode->getBoolValue("random", false));
setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0)); setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0));
setElevation(scFileNode->getDoubleValue("elevation", 0)); setElevation(scFileNode->getDoubleValue("elevation", 0));
setDragArea(scFileNode->getDoubleValue("eda", 0.007)); setDragArea(scFileNode->getDoubleValue("eda", 0.007));
@ -94,10 +96,11 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
setCd(scFileNode->getDoubleValue("cd", 0.029)); setCd(scFileNode->getDoubleValue("cd", 0.029));
//setMass(scFileNode->getDoubleValue("mass", 0.007)); //setMass(scFileNode->getDoubleValue("mass", 0.007));
setWeight(scFileNode->getDoubleValue("weight", 0.25)); setWeight(scFileNode->getDoubleValue("weight", 0.25));
setStabilisation(scFileNode->getBoolValue("aero-stabilized", false)); setStabilisation(scFileNode->getBoolValue("aero-stabilised", false));
setNoRoll(scFileNode->getBoolValue("no-roll", false)); setNoRoll(scFileNode->getBoolValue("no-roll", false));
setRandom(scFileNode->getBoolValue("random", false));
setImpact(scFileNode->getBoolValue("impact", false)); setImpact(scFileNode->getBoolValue("impact", false));
setExpiry(scFileNode->getBoolValue("expiry", false));
setCollision(scFileNode->getBoolValue("collision", false));
setImpactReportNode(scFileNode->getStringValue("impact-reports")); setImpactReportNode(scFileNode->getStringValue("impact-reports"));
setName(scFileNode->getStringValue("name", "Rocket")); setName(scFileNode->getStringValue("name", "Rocket"));
setFuseRange(scFileNode->getDoubleValue("fuse-range", 0.0)); setFuseRange(scFileNode->getDoubleValue("fuse-range", 0.0));
@ -105,7 +108,7 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
setSubID(scFileNode->getIntValue("SubID", 0)); setSubID(scFileNode->getIntValue("SubID", 0));
setExternalForce(scFileNode->getBoolValue("external-force", false)); setExternalForce(scFileNode->getBoolValue("external-force", false));
setForcePath(scFileNode->getStringValue("force-path", "")); setForcePath(scFileNode->getStringValue("force-path", ""));
setForceStabilisation(scFileNode->getBoolValue("force-stabilized", false)); setForceStabilisation(scFileNode->getBoolValue("force-stabilised", false));
setXoffset(scFileNode->getDoubleValue("x-offset", 0.0)); setXoffset(scFileNode->getDoubleValue("x-offset", 0.0));
setYoffset(scFileNode->getDoubleValue("y-offset", 0.0)); setYoffset(scFileNode->getDoubleValue("y-offset", 0.0));
setZoffset(scFileNode->getDoubleValue("z-offset", 0.0)); setZoffset(scFileNode->getDoubleValue("z-offset", 0.0));
@ -117,7 +120,6 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
setSlaved(scFileNode->getBoolValue("slaved", false)); setSlaved(scFileNode->getBoolValue("slaved", false));
setSlavedLoad(scFileNode->getBoolValue("slaved-load", false)); setSlavedLoad(scFileNode->getBoolValue("slaved-load", false));
setContentsNode(scFileNode->getStringValue("contents")); setContentsNode(scFileNode->getStringValue("contents"));
setRandom(scFileNode->getBoolValue("random", false));
} }
bool FGAIBallistic::init(bool search_in_AI_path) { bool FGAIBallistic::init(bool search_in_AI_path) {
@ -125,6 +127,16 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
_impact_reported = false; _impact_reported = false;
_collision_reported = false; _collision_reported = false;
_expiry_reported = false;
_impact_lat = 0;
_impact_lon = 0;
_impact_elev = 0;
_impact_hdg = 0;
_impact_pitch = 0;
_impact_roll = 0;
_impact_speed = 0;
invisible = false; invisible = false;
_elapsed_time += (sg_random() * 100); _elapsed_time += (sg_random() * 100);
@ -132,6 +144,8 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
props->setStringValue("material/name", ""); props->setStringValue("material/name", "");
props->setStringValue("name", _name.c_str()); props->setStringValue("name", _name.c_str());
props->setStringValue("submodels/path", _submodel.c_str()); props->setStringValue("submodels/path", _submodel.c_str());
props->setStringValue("force/path", _force_path.c_str());
//props->setStringValue("vector/path", _vector_path.c_str());
// start with high value so that animations don't trigger yet // start with high value so that animations don't trigger yet
_ht_agl_ft = 1e10; _ht_agl_ft = 1e10;
@ -264,7 +278,14 @@ void FGAIBallistic::update(double dt) {
} }
void FGAIBallistic::setAzimuth(double az) { void FGAIBallistic::setAzimuth(double az) {
if (_random)
hdg = _azimuth = (az - 5 ) + (10 * sg_random());
else
hdg = _azimuth = az; hdg = _azimuth = az;
//cout << _name << " init hdg " << hdg << " random " << _random << endl;
} }
void FGAIBallistic::setElevation(double el) { void FGAIBallistic::setElevation(double el) {
@ -292,6 +313,11 @@ void FGAIBallistic::setDragArea(double a) {
} }
void FGAIBallistic::setLife(double seconds) { void FGAIBallistic::setLife(double seconds) {
if (_random){
life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random());
//cout << "life " << life << endl;
} else
life = seconds; life = seconds;
} }
@ -323,6 +349,10 @@ void FGAIBallistic::setWeight(double w) {
_weight_lb = w; _weight_lb = w;
} }
void FGAIBallistic::setRandomness(double r) {
_randomness = r;
}
void FGAIBallistic::setRandom(bool r) { void FGAIBallistic::setRandom(bool r) {
_random = r; _random = r;
} }
@ -546,6 +576,7 @@ void FGAIBallistic::Run(double dt) {
if (_life_timer > life && life != -1){ if (_life_timer > life && life != -1){
if (_report_expiry && !_expiry_reported){ if (_report_expiry && !_expiry_reported){
//cout<<"AIBallistic: expiry"<< endl;
handle_expiry(); handle_expiry();
} else } else
setDie(true); setDie(true);
@ -555,9 +586,9 @@ void FGAIBallistic::Run(double dt) {
//set the contents in the appropriate tank or other property in the parent to zero //set the contents in the appropriate tank or other property in the parent to zero
setContents(0); setContents(0);
//randomise Cd by +- 5% //randomise Cd by +- 10%
if (_random) if (_random)
_Cd = _Cd * 0.95 + (0.05 * sg_random()); _Cd = _Cd * 0.90 + (0.10 * sg_random());
// Adjust Cd by Mach number. The equations are based on curves // Adjust Cd by Mach number. The equations are based on curves
// for a conventional shell/bullet (no boat-tail). // for a conventional shell/bullet (no boat-tail).
@ -631,6 +662,7 @@ void FGAIBallistic::Run(double dt) {
double force_elevation_deg = 0; double force_elevation_deg = 0;
if (_external_force) { if (_external_force) {
SGPropertyNode *n = fgGetNode(_force_path.c_str(), true); SGPropertyNode *n = fgGetNode(_force_path.c_str(), true);
double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue(); double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue(); force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
@ -764,13 +796,18 @@ void FGAIBallistic::Run(double dt) {
if (_azimuth < 0) if (_azimuth < 0)
_azimuth += 360; _azimuth += 360;
//cout << "_azimuth " << _azimuth << " hdg "<< hdg << endl;
if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter
cout<< "_aero_stabilised "<< endl;
const double coeff = 0.9; const double coeff = 0.9;
// we assume a symetrical MI about the pitch and yaw axis // we assume a symetrical MI about the pitch and yaw axis
setPch(_elevation, dt, coeff); setPch(_elevation, dt, coeff);
setHdg(_azimuth, dt, coeff); setHdg(_azimuth, dt, coeff);
} else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter } else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter
//cout<< "_force_stabilised "<< endl;
const double coeff = 0.9; const double coeff = 0.9;
double ratio = h_force_lbs/(_mass * slugs_to_lbs); double ratio = h_force_lbs/(_mass * slugs_to_lbs);
@ -824,10 +861,11 @@ void FGAIBallistic::handle_impact() {
void FGAIBallistic::handle_expiry() { void FGAIBallistic::handle_expiry() {
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
report_impact(pos.getElevationM()); report_impact(pos.getElevationM());
_expiry_reported = true; _expiry_reported = true;
SG_LOG(SG_GENERAL, SG_ALERT, "AIBallistic: expiry");
//if (life == -1){ //if (life == -1){
// invisible = true; // invisible = true;
//} else if (_subID == 0) // kill the AIObject if there is no subsubmodel //} else if (_subID == 0) // kill the AIObject if there is no subsubmodel
@ -883,7 +921,7 @@ SGVec3d FGAIBallistic::getCartHitchPos() const{
// convert geodetic positions to geocentered // convert geodetic positions to geocentered
SGVec3d cartuserPos = getCartUserPos(); SGVec3d cartuserPos = getCartUserPos();
SGVec3d cartPos = getCartPos(); //SGVec3d cartPos = getCartPos();
// Transform to the right coordinate frame, configuration is done in // Transform to the right coordinate frame, configuration is done in
// the x-forward, y-right, z-up coordinates (feet), computation // the x-forward, y-right, z-up coordinates (feet), computation

View file

@ -68,6 +68,7 @@ public:
void setWeight( double w ); void setWeight( double w );
void setNoRoll( bool nr ); void setNoRoll( bool nr );
void setRandom( bool r ); void setRandom( bool r );
void setRandomness( double r );
void setName(const string&); void setName(const string&);
void setCollision(bool c); void setCollision(bool c);
void setExpiry(bool e); void setExpiry(bool e);
@ -151,7 +152,8 @@ private:
bool _wind; // if true, local wind will be applied to object bool _wind; // if true, local wind will be applied to object
double _Cd; // drag coefficient double _Cd; // drag coefficient
double _mass; // slugs double _mass; // slugs
bool _random; // modifier for Cd bool _random; // modifier for Cd, life, az
double _randomness; // dimension for _random
double _load_resistance; // ground load resistanc N/m^2 double _load_resistance; // ground load resistanc N/m^2
double _frictionFactor; // dimensionless modifier for Coefficient of Friction double _frictionFactor; // dimensionless modifier for Coefficient of Friction
bool _solid; // if true ground is solid for FDMs bool _solid; // if true ground is solid for FDMs
@ -195,13 +197,13 @@ private:
double getDistanceLoadToHitch() const; double getDistanceLoadToHitch() const;
double getElevLoadToHitch() const; double getElevLoadToHitch() const;
double getBearingLoadToHitch() const; double getBearingLoadToHitch() const;
double getRecip(double az); double getRecip(double az);
double getMass() const; double getMass() const;
double hs; double hs;
double _ground_offset; double _ground_offset;
double _load_offset; double _load_offset;
double _force;
double _old_height; double _old_height;
SGVec3d _oldcarthitchPos; SGVec3d _oldcarthitchPos;

View file

@ -81,6 +81,8 @@ FGAIBase::FGAIBase(object_type ot) :
delete_me = false; delete_me = false;
_impact_reported = false; _impact_reported = false;
_collision_reported = false; _collision_reported = false;
_expiry_reported = false;
_subID = 0; _subID = 0;
_x_offset = 0; _x_offset = 0;

View file

@ -127,7 +127,8 @@ void FGSubmodelMgr::update(double dt)
continue; // so we can continue continue; // so we can continue
if (_impact || _hit || _expiry) { if (_impact || _hit || _expiry) {
//SG_LOG(SG_GENERAL, SG_DEBUG, "Submodel: Impact " << _impact << " hit! " << _hit ); // SG_LOG(SG_GENERAL, SG_ALERT, "Submodel: Impact " << _impact << " hit! " << _hit
//<< " exipiry :-( " << _expiry );
submodel_iterator = submodels.begin(); submodel_iterator = submodels.begin();
@ -144,9 +145,11 @@ void FGSubmodelMgr::update(double dt)
_parent_roll = (*sm_list_itr)->_getImpactRoll(); _parent_roll = (*sm_list_itr)->_getImpactRoll();
_parent_speed = (*sm_list_itr)->_getImpactSpeed(); _parent_speed = (*sm_list_itr)->_getImpactSpeed();
(*submodel_iterator)->first_time = true; (*submodel_iterator)->first_time = true;
//cout << "Impact: parent SubID = child_ID elev " << _parent_elev << endl;
if (release(*submodel_iterator, dt)) if (release(*submodel_iterator, dt))
(*sm_list_itr)->setDie(true); (*sm_list_itr)->setDie(true);
} }
++submodel_iterator; ++submodel_iterator;
@ -174,7 +177,7 @@ void FGSubmodelMgr::update(double dt)
if ((*submodel_iterator)->trigger_node != 0) { if ((*submodel_iterator)->trigger_node != 0) {
_trigger_node = (*submodel_iterator)->trigger_node; _trigger_node = (*submodel_iterator)->trigger_node;
trigger = _trigger_node->getBoolValue(); trigger = _trigger_node->getBoolValue();
//cout << "trigger node found " << trigger << endl; //cout << (*submodel_iterator)->name << "trigger node found " << trigger << endl;
} else { } else {
trigger = true; trigger = true;
//cout << (*submodel_iterator)->name << "trigger node not found " << trigger << endl; //cout << (*submodel_iterator)->name << "trigger node not found " << trigger << endl;
@ -182,8 +185,8 @@ void FGSubmodelMgr::update(double dt)
if (trigger && (*submodel_iterator)->count != 0) { if (trigger && (*submodel_iterator)->count != 0) {
//int id = (*submodel_iterator)->id; int id = (*submodel_iterator)->id;
//string name = (*submodel_iterator)->name; string name = (*submodel_iterator)->name;
/*SG_LOG(SG_GENERAL, SG_DEBUG, /*SG_LOG(SG_GENERAL, SG_DEBUG,
"Submodels end: " << (*submodel_iterator)->id "Submodels end: " << (*submodel_iterator)->id
<< " name " << (*submodel_iterator)->name << " name " << (*submodel_iterator)->name
@ -217,6 +220,8 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
return false; return false;
} }
//cout << "released timer: " << sm->timer << " delay " << sm->delay << endl;
sm->timer = 0.0; sm->timer = 0.0;
if (sm->first_time) { if (sm->first_time) {
@ -228,9 +233,12 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
FGAIBallistic* ballist = new FGAIBallistic; FGAIBallistic* ballist = new FGAIBallistic;
ballist->setPath(sm->model.c_str()); ballist->setPath(sm->model.c_str());
ballist->setLatitude(IC.lat); ballist->setName(sm->name);
ballist->setLongitude(IC.lon); ballist->setRandom(sm->random);
ballist->setAltitude(IC.alt); ballist->setRandomness(sm->randomness);
ballist->setLatitude(offsetpos.getLatitudeDeg());
ballist->setLongitude(offsetpos.getLongitudeDeg());
ballist->setAltitude(offsetpos.getElevationFt());
ballist->setAzimuth(IC.azimuth); ballist->setAzimuth(IC.azimuth);
ballist->setElevation(IC.elevation); ballist->setElevation(IC.elevation);
ballist->setRoll(IC.roll); ballist->setRoll(IC.roll);
@ -245,7 +253,6 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
ballist->setCd(sm->cd); ballist->setCd(sm->cd);
ballist->setStabilisation(sm->aero_stabilised); ballist->setStabilisation(sm->aero_stabilised);
ballist->setNoRoll(sm->no_roll); ballist->setNoRoll(sm->no_roll);
ballist->setName(sm->name);
ballist->setCollision(sm->collision); ballist->setCollision(sm->collision);
ballist->setExpiry(sm->expiry); ballist->setExpiry(sm->expiry);
ballist->setImpact(sm->impact); ballist->setImpact(sm->impact);
@ -260,7 +267,6 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
if (sm->count > 0) if (sm->count > 0)
sm->count--; sm->count--;
return true; return true;
} }
@ -305,7 +311,9 @@ void FGSubmodelMgr::transform(submodel *sm)
//cout << " name " << name << " id " << id << " sub id" << sub_id << endl; //cout << " name " << name << " id " << id << " sub id" << sub_id << endl;
if (_impact || _hit) { // set the Initial Conditions for the types of submodel parent
if (_impact || _hit || _expiry) {
// set the data for a submodel tied to a submodel // set the data for a submodel tied to a submodel
_count++; _count++;
//cout << "Submodels: release sub sub " << _count<< endl; //cout << "Submodels: release sub sub " << _count<< endl;
@ -380,12 +388,22 @@ void FGSubmodelMgr::transform(submodel *sm)
cout << "speed north " << IC.speed_north_fps << endl ; cout << "speed north " << IC.speed_north_fps << endl ;
cout << "parent speed fps in" << IC.speed << "sm speed in " << sm->speed << endl ;*/ cout << "parent speed fps in" << IC.speed << "sm speed in " << sm->speed << endl ;*/
// Set the Initial Conditions that are common to all types of parent
IC.wind_from_east = _user_wind_from_east_node->getDoubleValue(); IC.wind_from_east = _user_wind_from_east_node->getDoubleValue();
IC.wind_from_north = _user_wind_from_north_node->getDoubleValue(); IC.wind_from_north = _user_wind_from_north_node->getDoubleValue();
in[0] = sm->x_offset; userpos.setLatitudeDeg(IC.lat);
in[1] = sm->y_offset; userpos.setLongitudeDeg(IC.lon);
in[2] = sm->z_offset; userpos.setElevationFt(IC.alt);
_x_offset = sm->x_offset;
_y_offset = sm->y_offset;
_z_offset = sm->z_offset;
setOffsetPos();
//IC.elevation += sm->pitch_offset;
//IC.azimuth += sm->yaw_offset ;
// pre-process the trig functions // pre-process the trig functions
cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS); cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS);
@ -395,35 +413,35 @@ void FGSubmodelMgr::transform(submodel *sm)
cosRz = cos(IC.azimuth * SG_DEGREES_TO_RADIANS); cosRz = cos(IC.azimuth * SG_DEGREES_TO_RADIANS);
sinRz = sin(IC.azimuth * SG_DEGREES_TO_RADIANS); sinRz = sin(IC.azimuth * SG_DEGREES_TO_RADIANS);
// set up the transform matrix //// set up the transform matrix
trans[0][0] = cosRy * cosRz; //trans[0][0] = cosRy * cosRz;
trans[0][1] = -1 * cosRx * sinRz + sinRx * sinRy * cosRz ; //trans[0][1] = -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
trans[0][2] = sinRx * sinRz + cosRx * sinRy * cosRz; //trans[0][2] = sinRx * sinRz + cosRx * sinRy * cosRz;
trans[1][0] = cosRy * sinRz; //trans[1][0] = cosRy * sinRz;
trans[1][1] = cosRx * cosRz + sinRx * sinRy * sinRz; //trans[1][1] = cosRx * cosRz + sinRx * sinRy * sinRz;
trans[1][2] = -1 * sinRx * cosRx + cosRx * sinRy * sinRz; //trans[1][2] = -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
trans[2][0] = -1 * sinRy; //trans[2][0] = -1 * sinRy;
trans[2][1] = sinRx * cosRy; //trans[2][1] = sinRx * cosRy;
trans[2][2] = cosRx * cosRy; //trans[2][2] = cosRx * cosRy;
// multiply the input and transform matrices //// multiply the input and transform matrices
out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2]; //out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2]; //out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2]; //out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
// convert ft to degrees of latitude //// convert ft to degrees of latitude
out[0] = out[0] / (366468.96 - 3717.12 * cos(IC.lat * SG_DEGREES_TO_RADIANS)); //out[0] = out[0] / (366468.96 - 3717.12 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
// convert ft to degrees of longitude //// convert ft to degrees of longitude
out[1] = out[1] / (365228.16 * cos(IC.lat * SG_DEGREES_TO_RADIANS)); //out[1] = out[1] / (365228.16 * cos(IC.lat * SG_DEGREES_TO_RADIANS));
// set submodel initial position //// set submodel initial position
IC.lat += out[0]; //IC.lat += out[0];
IC.lon += out[1]; //IC.lon += out[1];
IC.alt += out[2]; //IC.alt += out[2];
// get aircraft velocity vector angles in XZ and XY planes // get aircraft velocity vector angles in XZ and XY planes
//double alpha = _user_alpha_node->getDoubleValue(); //double alpha = _user_alpha_node->getDoubleValue();
@ -431,7 +449,7 @@ void FGSubmodelMgr::transform(submodel *sm)
//double velXY = IC.azimuth - (IC.elevation - alpha * sinRx); //double velXY = IC.azimuth - (IC.elevation - alpha * sinRx);
// Get submodel initial velocity vector angles in XZ and XY planes. // Get submodel initial velocity vector angles in XZ and XY planes.
// This needs to be fixed. This vector should be added to aircraft's vector. // This vector should be added to aircraft's vector.
IC.elevation += (sm->yaw_offset * sinRx) + (sm->pitch_offset * cosRx); IC.elevation += (sm->yaw_offset * sinRx) + (sm->pitch_offset * cosRx);
IC.azimuth += (sm->yaw_offset * cosRx) - (sm->pitch_offset * sinRx); IC.azimuth += (sm->yaw_offset * cosRx) - (sm->pitch_offset * sinRx);
@ -454,7 +472,7 @@ void FGSubmodelMgr::transform(submodel *sm)
// if speeds are low this calculation can become unreliable // if speeds are low this calculation can become unreliable
if (IC.speed > 1) { if (IC.speed > 1) {
IC.azimuth = atan2(IC.total_speed_east , IC.total_speed_north) * SG_RADIANS_TO_DEGREES; //IC.azimuth = atan2(IC.total_speed_east, IC.total_speed_north) * SG_RADIANS_TO_DEGREES;
// cout << "azimuth1 " << IC.azimuth<<endl; // cout << "azimuth1 " << IC.azimuth<<endl;
// rationalise the output // rationalise the output
@ -506,15 +524,6 @@ void FGSubmodelMgr::loadAI()
} }
double FGSubmodelMgr::getRange(double lat, double lon, double lat2, double lon2) const
{
double course, distance, az2;
//calculate the bearing and range of the second pos from the first
geo_inverse_wgs_84(lat, lon, lat2, lon2, &course, &az2, &distance);
distance *= SG_METER_TO_NM;
return distance;
}
void FGSubmodelMgr::setData(int id, string& path, bool serviceable) void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
{ {
@ -572,6 +581,10 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false); sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
sm->ext_force = entry_node->getBoolValue("external-force", false); sm->ext_force = entry_node->getBoolValue("external-force", false);
sm->force_path = entry_node->getStringValue("force-path", ""); sm->force_path = entry_node->getStringValue("force-path", "");
sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
//cout << "sm->contents_node " << sm->contents_node << endl; //cout << "sm->contents_node " << sm->contents_node << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
sm->contents = sm->contents_node->getDoubleValue(); sm->contents = sm->contents_node->getDoubleValue();
@ -594,11 +607,13 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
sm->sub_id = 0; sm->sub_id = 0;
sm->prop = fgGetNode("/ai/submodels/submodel", index, true); sm->prop = fgGetNode("/ai/submodels/submodel", index, true);
sm->prop->tie("delay", SGRawValuePointer<double>(&(sm->delay)));
sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count))); sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count)));
sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat))); sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat)));
sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id))); sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id))); sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable))); sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
string name = sm->name; string name = sm->name;
sm->prop->setStringValue("name", name.c_str()); sm->prop->setStringValue("name", name.c_str());
@ -608,7 +623,7 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
string force_path = sm->force_path; string force_path = sm->force_path;
sm->prop->setStringValue("force_path", force_path.c_str()); sm->prop->setStringValue("force_path", force_path.c_str());
//cout << "set force_path " << force_path << endl; //cout << "set force_path Sub " << force_path << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents))); sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
@ -673,8 +688,11 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false); sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false);
sm->speed_node = fgGetNode(entry_node->getStringValue("speed-node", "none"), false); sm->speed_node = fgGetNode(entry_node->getStringValue("speed-node", "none"), false);
sm->submodel = entry_node->getStringValue("submodel-path", ""); sm->submodel = entry_node->getStringValue("submodel-path", "");
sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
sm->ext_force = entry_node->getBoolValue("external-force", false); sm->ext_force = entry_node->getBoolValue("external-force", false);
sm->force_path = entry_node->getStringValue("force-path", ""); sm->force_path = entry_node->getStringValue("force-path", "");
sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
//cout << "sm->contents_node " << sm->contents_node << endl; //cout << "sm->contents_node " << sm->contents_node << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
@ -703,16 +721,17 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id))); sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id))); sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable))); sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
string name = sm->name; string name = sm->name;
sm->prop->setStringValue("name", name.c_str()); sm->prop->setStringValue("name", name.c_str());
string submodel = sm->submodel; string submodel = sm->submodel;
sm->prop->setStringValue("submodel", submodel.c_str()); sm->prop->setStringValue("submodel", submodel.c_str());
// cout << " set submodel path " << submodel<< endl; // cout << " set submodel path AI" << submodel<< endl;
string force_path = sm->force_path; string force_path = sm->force_path;
sm->prop->setStringValue("force_path", force_path.c_str()); sm->prop->setStringValue("force_path", force_path.c_str());
//cout << "set force_path " << force_path << endl; cout << "set force_path AI" << force_path << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents))); sm->prop->tie("contents-lbs", SGRawValuePointer<double>(&(sm->contents)));
@ -772,4 +791,44 @@ void FGSubmodelMgr::loadSubmodels()
//} //}
} }
SGVec3d FGSubmodelMgr::getCartOffsetPos() const{
// convert geodetic positions to geocentered
SGVec3d cartuserPos = SGVec3d::fromGeod(userpos);
// Transform to the right coordinate frame, configuration is done in
// the x-forward, y-right, z-up coordinates (feet), computation
// in the simulation usual body x-forward, y-right, z-down coordinates
// (meters) )
SGVec3d _off(_x_offset * SG_FEET_TO_METER,
_y_offset * SG_FEET_TO_METER,
-_z_offset * SG_FEET_TO_METER);
// Transform the user position to the horizontal local coordinate system.
SGQuatd hlTrans = SGQuatd::fromLonLat(userpos);
// and postrotate the orientation of the user model wrt the horizontal
// local frame
hlTrans *= SGQuatd::fromYawPitchRollDeg(
IC.azimuth,
IC.elevation,
IC.roll);
// The offset converted to the usual body fixed coordinate system
// rotated to the earth-fixed coordinates axis
SGVec3d off = hlTrans.backTransform(_off);
// Add the position offset of the user model to get the geocentered position
SGVec3d offsetPos = cartuserPos + off;
return offsetPos;
}
void FGSubmodelMgr::setOffsetPos(){
// convert the offset geocentered position to geodetic
SGVec3d cartoffsetPos = getCartOffsetPos();
SGGeodesy::SGCartToGeod(cartoffsetPos, offsetpos);
}
// end of submodel.cxx // end of submodel.cxx

View file

@ -53,6 +53,7 @@ public:
double drag_area; double drag_area;
double life; double life;
double buoyancy; double buoyancy;
double randomness;
bool wind; bool wind;
bool first_time; bool first_time;
double cd; double cd;
@ -62,6 +63,7 @@ public:
int id; int id;
bool no_roll; bool no_roll;
bool serviceable; bool serviceable;
bool random;
bool collision; bool collision;
bool expiry; bool expiry;
bool impact; bool impact;
@ -142,6 +144,10 @@ private:
double _parent_pitch; double _parent_pitch;
double _parent_roll; double _parent_roll;
double _parent_speed; double _parent_speed;
double _x_offset;
double _y_offset;
double _z_offset;
static const double lbs_to_slugs; //conversion factor static const double lbs_to_slugs; //conversion factor
@ -193,10 +199,14 @@ private:
bool release(submodel *, double dt); bool release(submodel *, double dt);
double getRange(double lat, double lon, double lat2, double lon2) const;
int _count; int _count;
SGGeod userpos;
SGGeod offsetpos;
SGVec3d getCartOffsetPos() const;
void setOffsetPos();
}; };
#endif // __SYSTEMS_SUBMODEL_HXX #endif // __SYSTEMS_SUBMODEL_HXX