1 // FGAIBallistic - FGAIBase-derived class creates a ballistic object
3 // Written by David Culp, started November 2003.
4 // - davidculp2@comcast.net
6 // With major additions by Mathias Froehlich & Vivian Meazza 2004-2007
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <simgear/math/point3d.hxx>
27 #include <simgear/math/sg_random.h>
30 #include "AIBallistic.hxx"
33 FGAIBallistic::FGAIBallistic() : FGAIBase(otBallistic) {
39 aero_stabilised = false;
42 FGAIBallistic::~FGAIBallistic() {
45 void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
49 FGAIBase::readFromScenario(scFileNode);
51 setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0));
52 setElevation(scFileNode->getDoubleValue("elevation", 0.0));
53 setDragArea(scFileNode->getDoubleValue("eda", 0.007));
54 setLife(scFileNode->getDoubleValue("life", 900.0));
55 setBuoyancy(scFileNode->getDoubleValue("buoyancy", 0));
56 setWind_from_east(scFileNode->getDoubleValue("wind_from_east", 0));
57 setWind_from_north(scFileNode->getDoubleValue("wind_from_north", 0));
58 setWind(scFileNode->getBoolValue("wind", false));
59 setRoll(scFileNode->getDoubleValue("roll", 0.0));
60 setCd(scFileNode->getDoubleValue("cd", 0.029));
61 setMass(scFileNode->getDoubleValue("mass", 0.007));
62 setStabilisation(scFileNode->getBoolValue("aero_stabilized", false));
63 setNoRoll(scFileNode->getBoolValue("no-roll", false));
64 setRandom(scFileNode->getBoolValue("random", false));
67 bool FGAIBallistic::init(bool search_in_AI_path) {
68 FGAIBase::init(search_in_AI_path);
76 void FGAIBallistic::bind() {
78 props->tie("sim/time/elapsed-sec",
79 SGRawValueMethods<FGAIBallistic,double>(*this,
80 &FGAIBallistic::_getTime));
83 void FGAIBallistic::unbind() {
84 // FGAIBase::unbind();
85 props->untie("sim/time/elapsed-sec");
88 void FGAIBallistic::update(double dt) {
94 void FGAIBallistic::setAzimuth(double az) {
98 void FGAIBallistic::setElevation(double el) {
99 pitch = elevation = el;
102 void FGAIBallistic::setRoll(double rl) {
106 void FGAIBallistic::setStabilisation(bool val) {
107 aero_stabilised = val;
110 void FGAIBallistic::setNoRoll(bool nr) {
114 void FGAIBallistic::setDragArea(double a) {
118 void FGAIBallistic::setLife(double seconds) {
122 void FGAIBallistic::setBuoyancy(double fpss) {
126 void FGAIBallistic::setWind_from_east(double fps) {
127 wind_from_east = fps;
130 void FGAIBallistic::setWind_from_north(double fps) {
131 wind_from_north = fps;
134 void FGAIBallistic::setWind(bool val) {
138 void FGAIBallistic::setCd(double c) {
142 void FGAIBallistic::setMass(double m) {
146 void FGAIBallistic::setRandom(bool r) {
150 void FGAIBallistic::setName(const string& n) {
154 void FGAIBallistic::Run(double dt) {
156 // cout << "life timer 1" << life_timer << dt << endl;
157 if (life_timer > life) setDie(true);
159 double speed_north_deg_sec;
160 double speed_east_deg_sec;
161 double wind_speed_from_north_deg_sec;
162 double wind_speed_from_east_deg_sec;
163 double Cdm; // Cd adjusted by Mach Number
165 //randomise Cd by +- 5%
167 Cd = Cd * 0.95 + (0.05 * sg_random());
169 // Adjust Cd by Mach number. The equations are based on curves
170 // for a conventional shell/bullet (no boat-tail).
172 Cdm = 0.0125 * Mach + Cd;
173 else if ( 0.7 < Mach && Mach < 1.2 )
174 Cdm = 0.3742 * pow ( Mach, 2) - 0.252 * Mach + 0.0021 + Cd;
176 Cdm = 0.2965 * pow ( Mach, -1.1506 ) + Cd;
178 //cout << " Mach , " << Mach << " , Cdm , " << Cdm << " ballistic speed kts //"<< speed << endl;
180 // drag = Cd * 0.5 * rho * speed * speed * drag_area;
181 // rho is adjusted for altitude in void FGAIBase::update,
182 // using Standard Atmosphere (sealevel temperature 15C)
183 // acceleration = drag/mass;
184 // adjust speed by drag
185 speed -= (Cdm * 0.5 * rho * speed * speed * drag_area/mass) * dt;
187 // don't let speed become negative
191 double speed_fps = speed * SG_KT_TO_FPS;
193 // calculate vertical and horizontal speed components
194 vs = sin( pitch * SG_DEGREES_TO_RADIANS ) * speed_fps;
195 double hs = cos( pitch * SG_DEGREES_TO_RADIANS ) * speed_fps;
197 // convert horizontal speed (fps) to degrees per second
198 speed_north_deg_sec = cos(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lat;
199 speed_east_deg_sec = sin(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lon;
201 // if wind not required, set to zero
207 // convert wind speed (fps) to degrees per second
208 wind_speed_from_north_deg_sec = wind_from_north / ft_per_deg_lat;
209 wind_speed_from_east_deg_sec = wind_from_east / ft_per_deg_lon;
212 pos.setLatitudeDeg( pos.getLatitudeDeg()
213 + (speed_north_deg_sec - wind_speed_from_north_deg_sec) * dt );
214 pos.setLongitudeDeg( pos.getLongitudeDeg()
215 + (speed_east_deg_sec - wind_speed_from_east_deg_sec) * dt );
217 // adjust vertical speed for acceleration of gravity and buoyancy
218 vs -= (gravity - buoyancy) * dt;
220 // adjust altitude (feet)
221 altitude_ft += vs * dt;
222 pos.setElevationFt(altitude_ft);
224 // recalculate pitch (velocity vector) if aerostabilized
225 /*cout << name << ": " << "aero_stabilised " << aero_stabilised
226 << " pitch " << pitch <<" vs " << vs <<endl ;*/
229 pitch = atan2( vs, hs ) * SG_RADIANS_TO_DEGREES;
231 // recalculate total speed
232 speed = sqrt( vs * vs + hs * hs) / SG_KT_TO_FPS;
234 // set destruction flag if altitude less than sea level -1000
235 if (altitude_ft < -1000.0) setDie(true);
239 double FGAIBallistic::_getTime() const {
240 // cout << "life timer 2" << life_timer << endl;