#include "AIBallistic.hxx"
+
FGAIBallistic::FGAIBallistic(FGAIManager* mgr) {
manager = mgr;
_type_str = "ballistic";
_otype = otBallistic;
drag_area = 0.007;
life_timer = 0.0;
- gravity = 32;
-// buoyancy = 64;
+ gravity = 32;
+// buoyancy = 64;
no_roll = false;
- }
+}
FGAIBallistic::~FGAIBallistic() {
}
void FGAIBallistic::setWind(bool val) {
wind = val;
}
-void FGAIBallistic::Run(double dt) {
+void FGAIBallistic::setCd(double c) {
+ Cd = c;
+}
+
+void FGAIBallistic::setWeight(double w) {
+ weight = w;
+}
+
+void FGAIBallistic::Run(double dt) {
life_timer += dt;
if (life_timer > life) setDie(true);
double speed_east_deg_sec;
double wind_speed_from_north_deg_sec;
double wind_speed_from_east_deg_sec;
+ double mass;
- // the two drag calculations below assume sea-level density,
- // mass of 0.03 slugs, drag coeff of 0.295
- // adjust speed due to drag
- speed -= 0.0116918 * drag_area * speed * speed * dt;
+ // the drag calculations below assume sea-level density,
+ // rho = 0.023780 slugs/ft3
+ // calculate mass
+ mass = weight * lbs_to_slugs;
+
+ // drag = Cd * 0.5 * rho * speed * speed * drag_area;
+ // acceleration = drag/mass;
+ // adjust speed by drag
+ speed -= (Cd * 0.5 * rho * speed * speed * drag_area/mass) * dt;
+
+ // don't let speed become negative
if ( speed < 0.0 ) speed = 0.0;
+
+ // calculate vertical and horizontal speed components
vs = sin( pitch * SG_DEGREES_TO_RADIANS ) * speed;
hs = cos( pitch * SG_DEGREES_TO_RADIANS ) * speed;
speed_north_deg_sec = cos(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lat;
speed_east_deg_sec = sin(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lon;
- // convert wind speed (fps) to degrees per second
-
+ // if wind not required, set to zero
if (!wind){
wind_from_north = 0;
wind_from_east = 0;
- }
-
+ }
+
+ // convert wind speed (fps) to degrees per second
wind_speed_from_north_deg_sec = wind_from_north / ft_per_deg_lat;
wind_speed_from_east_deg_sec = wind_from_east / ft_per_deg_lon;
-
- // set new position
-// pos.setlat( pos.lat() + (speed_north_deg_sec * dt) );
-// pos.setlon( pos.lon() + (speed_east_deg_sec * dt) );
-
-
// set new position
-
pos.setlat( pos.lat() + (speed_north_deg_sec - wind_speed_from_north_deg_sec) * dt );
pos.setlon( pos.lon() + (speed_east_deg_sec - wind_speed_from_east_deg_sec) * dt );
- // adjust vertical speed for acceleration of gravity
+ // adjust vertical speed for acceleration of gravity and buoyancy
vs -= (gravity - buoyancy) * dt;
// adjust altitude (feet)
// set destruction flag if altitude less than sea level -1000
if (altitude < -1000.0) setDie(true);
-}
+} // end Run
double FGAIBallistic::_getTime() const {
return life_timer;
}
-// end AIBallistic
\ No newline at end of file
+// end AIBallistic
class FGAIBallistic : public FGAIBase {
-
+
public:
-
+
FGAIBallistic(FGAIManager* mgr);
~FGAIBallistic();
-
+
bool init();
virtual void bind();
virtual void unbind();
void setAzimuth( double az );
void setElevation( double el );
- void setRoll( double rl );
+ void setRoll( double rl );
void setStabilization( bool val );
void setDragArea( double a );
void setLife( double seconds );
void setWind_from_east( double fps );
void setWind_from_north( double fps );
void setWind( bool val );
+ void setCd( double c );
+ void setWeight( double w );
double _getTime() const;
-
+
private:
double azimuth; // degrees true
double elevation; // degrees
- double rotation; // degrees
+ double rotation; // degrees
double hs; // horizontal speed (fps)
bool aero_stabilized; // if true, object will point where it's going
double drag_area; // equivalent drag area in ft2
double wind_from_east; // fps
double wind_from_north; // fps
bool wind; // if true, local wind will be applied to object
-
+ double Cd; // drag coefficient
+ double weight; // lbs
+
void Run(double dt);
};
#include "AIBase.hxx"
#include "AIManager.hxx"
+
+const double FGAIBase::rho = 0.023780; // sea level air density slugs/ft3
+const double FGAIBase::lbs_to_slugs = 0.031080950172; //conversion factor
+
+
FGAIBase::FGAIBase()
: fp( NULL ),
model( NULL ),
-// FGAIBase - abstract base class for AI objects
+// FGAIBase.hxx - abstract base class for AI objects
// Written by David Culp, started Nov 2003, based on
// David Luff's FGAIEntity class.
// - davidculp2@comcast.net
double buoyancy; // acceleration in ft per sec2
double wind_from_east; // in feet per second
double wind_from_north; // in feet per second
- bool wind;
+ double cd; // coefficient of drag
+ bool wind; // if true, model reacts to parent wind
+ double weight; // in lbs
} FGAIModelEntity;
double _getY_shift() const;
double _getRotation() const;
+ static const double rho;
+ static const double lbs_to_slugs;
+
int _getID() const;
inline double _getRange() { return range; };
ai_ballistic->setWind_from_north(entity->wind_from_north);
ai_ballistic->setWind(entity->wind);
ai_ballistic->setRoll(entity->roll);
+ ai_ballistic->setCd(entity->cd);
+ ai_ballistic->setWeight(entity->weight);
ai_ballistic->init();
ai_ballistic->bind();
return ai_ballistic;
delete s;
}
+//end AIManager.cxx
-// FGAIScenario - class for loading an AI scenario
+// FGAIScenario.cxx - class for loading an AI scenario
// Written by David Culp, started May 2004
// - davidculp2@comcast.net
//
en->wind_from_east = entry_node->getDoubleValue("wind_from_east", 0);
en->wind_from_north = entry_node->getDoubleValue("wind_from_north", 0);
en->wind = entry_node->getBoolValue("wind", false);
+ en->cd = entry_node->getDoubleValue ("cd", 0.029);
+ en->weight = entry_node->getDoubleValue ("weight", 0.030);
en->fp = NULL;
}
return entries.size();
}
-
+// end scenario.cxx
#include <AIModel/AIManager.hxx>
+const double SubmodelSystem::lbs_to_slugs = 0.031080950172;
+
SubmodelSystem::SubmodelSystem ()
{
_user_speed_down_fps_node = fgGetNode("/velocities/speed-down-fps",true);
_user_speed_east_fps_node = fgGetNode("/velocities/speed-east-fps",true);
- _user_speed_north_fps_node = fgGetNode("/velocities/speed-north-fps",true);
-
+ _user_speed_north_fps_node = fgGetNode("/velocities/speed-north-fps",true);
+
ai = (FGAIManager*)globals->get_subsystem("ai_model");
entity.wind_from_east = IC.wind_from_east;
entity.wind_from_north = IC.wind_from_north;
entity.wind = sm->wind;
+ entity.cd = sm->cd;
+ entity.weight = sm->weight;
ai->createBallistic( &entity );
if (sm->count > 0) (sm->count)--;
sm->trigger = fgGetNode(entry_node->getStringValue("trigger", "none"), true);
sm->name = entry_node->getStringValue("name", "none_defined");
sm->model = entry_node->getStringValue("model", "Models/Geometry/rocket.ac");
- sm->speed = entry_node->getDoubleValue("speed", 0.0);
+ sm->speed = entry_node->getDoubleValue("speed", 2329.4 );
sm->repeat = entry_node->getBoolValue ("repeat", false);
sm->delay = entry_node->getDoubleValue("delay", 0.25);
sm->count = entry_node->getIntValue ("count", 1);
sm->z_offset = entry_node->getDoubleValue("z-offset", 0.0);
sm->yaw_offset = entry_node->getDoubleValue("yaw-offset", 0.0);
sm->pitch_offset = entry_node->getDoubleValue("pitch-offset", 0.0);
- sm->drag_area = entry_node->getDoubleValue("eda", 0.007);
+ sm->drag_area = entry_node->getDoubleValue("eda", 0.034);
sm->life = entry_node->getDoubleValue("life", 900.0);
sm->buoyancy = entry_node->getDoubleValue("buoyancy", 0);
sm->wind = entry_node->getBoolValue ("wind", false);
sm->first_time = false;
+ sm->cd = entry_node->getDoubleValue("cd", 0.295);
+ sm->weight = entry_node->getDoubleValue("weight", 0.25);
sm->trigger->setBoolValue(false);
sm->timer = sm->delay;
// get initial conditions
IC.lat = _user_lat_node->getDoubleValue();
- IC.lon = _user_lon_node->getDoubleValue();
+ IC.lon = _user_lon_node->getDoubleValue();
IC.alt = _user_alt_node->getDoubleValue();
IC.roll = _user_roll_node->getDoubleValue(); // rotation about x axis
IC.elevation = _user_pitch_node->getDoubleValue(); // rotation about y axis
in[0] = sm->x_offset;
in[1] = sm->y_offset;
in[2] = sm->z_offset;
-
+
+ IC.mass = sm->weight * lbs_to_slugs;
+
// pre-process the trig functions
cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS);
// re-calculate speed, elevation and azimuth
IC.speed = sqrt( IC.total_speed_north * IC.total_speed_north +
- IC.total_speed_east * IC.total_speed_east +
- IC.total_speed_down * IC.total_speed_down);
-
+ IC.total_speed_east * IC.total_speed_east +
+ IC.total_speed_down * IC.total_speed_down);
+
IC.azimuth = atan(IC.total_speed_east/IC.total_speed_north) * SG_RADIANS_TO_DEGREES;
// rationalise the output
if (IC.total_speed_north <= 0){
IC.azimuth = 180 + IC.azimuth;
- }
+ }
else{
if(IC.total_speed_east <= 0){
IC.azimuth = 360 + IC.azimuth;
- }
+ }
}
-
+
IC.elevation = -atan(IC.total_speed_down/sqrt(IC.total_speed_north *
IC.total_speed_north +
IC.total_speed_east * IC.total_speed_east)) * SG_RADIANS_TO_DEGREES;
typedef struct {
SGPropertyNode* trigger;
SGPropertyNode* prop;
+
string name;
string model;
double speed;
double buoyancy;
bool wind;
bool first_time;
+ double cd;
+ double weight;
+// double mass;
} submodel;
typedef struct {
double total_speed_down;
double total_speed_east;
double total_speed_north;
+ double mass;
} IC_struct;
SubmodelSystem ();
double x_offset, y_offset, z_offset;
double pitch_offset, yaw_offset;
+ static const double lbs_to_slugs; //conversion factor
+
SGPropertyNode* _serviceable_node;
SGPropertyNode* _user_lat_node;
SGPropertyNode* _user_lon_node;
SGPropertyNode* _user_speed_node;
SGPropertyNode* _user_wind_from_east_node;
SGPropertyNode* _user_wind_from_north_node;
- SGPropertyNode* _user_speed_down_fps_node;
- SGPropertyNode* _user_speed_east_fps_node;
- SGPropertyNode* _user_speed_north_fps_node;
-
+ SGPropertyNode* _user_speed_down_fps_node;
+ SGPropertyNode* _user_speed_east_fps_node;
+ SGPropertyNode* _user_speed_north_fps_node;
+
FGAIManager* ai;
IC_struct IC;
#endif // __SYSTEMS_SUBMODEL_HXX
+