]> git.mxchange.org Git - flightgear.git/blob - src/FDM/SP/BalloonSim.cpp
Merge branch 'master' of git://gitorious.org/fg/flightgear into next
[flightgear.git] / src / FDM / SP / BalloonSim.cpp
1 /*****************************************************************************
2
3  Module:       BalloonSim.cpp
4  Author:       Christian Mayer
5  Date started: 01.09.99
6  Called by:
7
8  -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 A hot air balloon simulator
30
31 HISTORY
32 ------------------------------------------------------------------------------
33 01.09.1999 Christian Mayer      Created
34 03.10.1999 Christian Mayer      cleaned  the code  by moveing  WeatherDatabase 
35                                 calls inside the update()
36 *****************************************************************************/
37
38 /****************************************************************************/
39 /* INCLUDES                                                                 */
40 /****************************************************************************/
41
42 #ifdef HAVE_CONFIG_H
43 #  include "config.h"
44 #endif
45
46 #include <stdio.h>
47 #include <math.h>
48
49 #include <simgear/constants.h>
50
51 #include "BalloonSim.h"
52
53 /****************************************************************************/
54 /********************************** CODE ************************************/
55 /****************************************************************************/
56
57 /****************************************************************************/
58 /*                                                                          */
59 /*  Constructor:                                                            */
60 /*  Set the balloon model to some values that seem reasonable as I haven't  */
61 /*  got much original values                                                */
62 /*                                                                          */
63 /****************************************************************************/
64 balloon::balloon()
65 {
66     dt = 0.1;
67     ground_level = 3400.0;
68
69     gravity_vector = SGVec3f(0.0, 0.0, -9.81);
70     velocity = SGVec3f(0.0, 0.0, 0.0);
71     position = SGVec3f(0.0, 0.0, 0.0);
72     hpr = SGVec3f(0.0, 0.0, 0.0);
73
74     /************************************************************************/
75     /* My balloon  has a  radius of  8.8 metres  as that  gives a  envelope */
76     /* volume of about 2854 m^3  which is  about 77000 ft^3,  a very common */
77     /* size for hot air balloons                                            */
78     /************************************************************************/
79
80     balloon_envelope_area = 4.0 * (8.8 * 8.8) * SGD_PI; 
81     balloon_envelope_volume = (4.0/3.0) * (8.8 * 8.8 * 8.8) * SGD_PI;
82
83     wind_facing_area_of_balloon = SGD_PI * (8.8 * 8.8);
84     wind_facing_area_of_basket = 2.0;   //guessed: 2 m^2
85     
86     cw_envelope=0.45;                   //a sphere in this case
87     cw_basket=0.8;
88
89     weight_of_total_fuel = 40.0;        //big guess
90     weight_of_envelope = 200.0;         //big guess
91     weight_of_basket = 40.0;            //big guess
92     weight_of_cargo = 750.0;            //big guess
93
94     fuel_left=1.0;
95     max_flow_of_fuel_per_second=10.0*1.0/3600.0; //assuming 10% of one hour of total burn time
96     current_burner_strength = 0.0;      //the throttle
97
98     lambda = 0.15;                      //for plasic
99     l_of_the_envelope = 1.0/1000.0;     //the thickness of the envelope (in m): 1mm
100
101     T = 273.16 + 130.6;                 //Temperature in the envelope => still at ground level
102 }
103
104 void balloon::update()
105 {
106     /************************************************************************/
107     /* I'm  simplifying  the  balloon by  reducing the  simulation  to  two */
108     /* points:                                                              */  
109     /* the center of the basket (CB) and the center of the envelope (CE)    */
110     /*                                                                      */
111     /*                                 ce                                   */
112     /*                                 I                                    */
113     /*                                 I                                    */
114     /*                                 cg (=center of gravity)              */
115     /*                                 I                                    */
116     /*                                 cb                                   */
117     /*                                                                      */
118     /* On each center  are forces acting:  gravity and  wind resitance.  CE */
119     /* additionally got the lift  (=> I need to calculate the weight of the */
120     /* air inside, too)                                                     */
121     /*                                                                      */
122     /* The weight of the air  in the envelope is  dependant of the tempera- */
123     /* ture. This temperature is decreasing over the time that is dependant */
124     /* of the insulation  of the envelope  material (lambda),  the gas used */
125     /* (air) and the wind speed. For a plane surface it's for air:          */
126     /*                                                                      */
127     /*    alpha = 4.8 + 3.4*v   with v < 5.0 m/s                            */
128     /*                                                                      */
129     /* The value k that takes all of that into account is defined as:       */
130     /*                                                                      */
131     /*    1 / k = 1 / alpha1 + 1 / alpha2 + l / lambda                      */
132     /*                                                                      */
133     /* with 'l' beeing the 'length' i.e. thickness of the insulator, alpha1 */
134     /* the air inside and alpha2 the air outside of the envelope.  So our k */
135     /* is:                                                                  */
136     /*                                                                      */
137     /*    k = 1 / [1/4.8 + 1/(4.8+3.4v) + l/lambda]                         */
138     /*                                                                      */
139     /* The energy lost by this process is defined as:                       */
140     /*                                                                      */
141     /*    dQ = k * A * t * dT                                               */
142     /*                                                                      */
143     /* with Q being  the energy,  k that value  defined above,  A the total */
144     /* area of the envelope,  t the time (in hours)  and dT the temperature */
145     /* difference between the inside and the outside.                       */
146     /* To get the temperature of the air in the inside I need the formula:  */
147     /*                                                                      */
148     /*    dQ = cAir * m * dT                                                */
149     /*                                                                      */
150     /* with cAir being the specific heat capacity(?)  of air (= 1.00 kcal / */
151     /* kg * degree),  m the mass of the air and  dT the temperature change. */
152     /* As the envelope is open I'm  assuming that the  same air pressure is */
153     /* inside and  outside of  it  (practical there  should  be  a slightly */
154     /* higher air pressure  in the inside or the envelope  would collapse). */
155     /* So it's easy to calculate the density of the air inside:             */
156     /*                                                                      */
157     /*    rho = p / R * T                                                   */
158     /*                                                                      */
159     /* with p being  the pressure,  R the gas constant(?)  which is for air */
160     /* 287.14 N * m / kg * K and T the absolute temperature.                */
161     /*                                                                      */
162     /* The value returned by this function is the displacement of the CB    */
163     /************************************************************************/
164
165     /************************************************************************/
166     /* NOTE:  This is the simplified version:  I'm assuming that  the whole */
167     /* balloon consists only of the envelope.I will improove the simulation */
168     /* later, but currently was my main concern to get it going...          */
169     /************************************************************************/
170
171    // I realy don't think there is a solution for this without WeatherCM
172    // but this is a hack, and it's working -- EMH
173    double mAir = 1;
174    float Q = 0;
175
176     // gain of energy by heating:
177     if (fuel_left > 0.0)        //but only with some fuel left ;-)
178     {
179         float fuel_burning = current_burner_strength * max_flow_of_fuel_per_second * dt * weight_of_total_fuel; //in kg
180     
181         //convert to cubemetres (I'm wrongly assuming 'normal' conditions; but that's correct for my special case)
182         float cube_metres_burned = fuel_burning / 2.2;  //2.2 is the density for propane
183
184         fuel_left -= fuel_burning / weight_of_total_fuel;
185
186         // get energy through burning. 
187         Q += 22250.0 * cube_metres_burned;  //22250 for propan, 29500 would be butane and if you dare: 2580 would be hydrogen...
188     }
189
190     // calculate the new temperature in the inside:
191     T += Q / (1.00 * mAir);
192
193     //calculate the masses of the envelope and the basket
194     float mEnvelope = mAir + weight_of_envelope;
195     float mBasket   = weight_of_total_fuel*fuel_left + weight_of_basket + weight_of_cargo;
196
197     float mTotal = mEnvelope + mBasket;
198
199     //calulate the forces
200     SGVec3f fTotal, fFriction, fLift;
201
202     fTotal = mTotal*gravity_vector;
203    
204     // fTotal += fLift;     //FIXME: uninitialized fLift 
205     // fTotal += fFriction; //FIXME: uninitialized fFriction
206     
207     //claculate acceleration: a = F / m
208     SGVec3f aTotal, vTotal, dTotal;
209
210     aTotal = (1.0 / mTotal)*fTotal;
211
212     //integrate the displacement: d = 0.5 * a * dt**2 + v * dt + d
213     vTotal = dt*velocity; 
214     dTotal = (0.5*dt*dt)*aTotal; dTotal += vTotal;
215
216     //integrate the velocity to 'velocity': v = a * dt + v
217     vTotal = dt*aTotal; velocity += vTotal;
218
219     /************************************************************************/
220     /* VERY WRONG STUFF: it's just here to get some results to start with   */  
221     /************************************************************************/
222
223     // care for the ground
224     if (position[2] < (ground_level+0.001) )
225         position[2] = ground_level;
226
227     //return results
228     position += dTotal;
229
230     //cout << "BallonSim: T: " << (T-273.16) << " alt: " << position[2] << " ground: " << ground_level << " throttle: " << current_burner_strength << "\n";
231 }
232
233 void balloon::set_burner_strength(const float bs)
234 {
235     if ((bs>=0.0) && (bs<=1.0))
236     current_burner_strength = bs;
237 }
238
239 void balloon::getVelocity(SGVec3f& v) const
240 {
241     v = velocity;
242 }
243
244 void balloon::setVelocity(const SGVec3f& v)
245 {
246     velocity = v;
247 }
248
249 void balloon::getPosition(SGVec3f& v) const
250 {
251     v = position;
252 }
253
254 void balloon::setPosition(const SGVec3f& v)
255 {
256     position = v;
257 }
258
259 void balloon::getHPR(SGVec3f& angles) const //the balloon isn't allways exactly vertical
260 {
261     angles = hpr;
262 }
263
264 void balloon::setHPR(const SGVec3f& angles)  //the balloon isn't allways exactly vertical
265 {
266     hpr = angles;
267 }
268
269 void balloon::setGroundLevel(const float altitude)
270 {
271     ground_level = altitude;
272 }
273
274 float balloon::getTemperature(void) const
275 {
276     return T;
277 }
278
279 float balloon::getFuelLeft(void) const
280 {
281     return fuel_left;
282 }
283
284 /*
285 void main(void)
286 {
287     bool burner = true;
288     balloon bal;
289     bool exit = false;
290     sgVec3 pos={0.0, 0.0, 0.0};
291     char c;
292     float acc_dt = 0.0;
293     float alt;
294
295 bool hysteresis = false; // moving up
296     for (;!exit;)
297     {
298         for (int i=0; i<100; i++)
299         {
300             bal.update(0.1); acc_dt += 0.1;
301             bal.getPosition(pos);
302             alt = pos[2];
303
304             if (alt > 3010) 
305             {
306                 hysteresis = true;
307                 burner = false;
308             }
309             if ((alt < 2990) && (hysteresis == true))
310             {
311                 hysteresis = false;
312                 burner = true;
313             }
314             if ((bal.getTemperature()-273.16)>250.0)
315                 burner = false; //emergency
316         }
317
318         // toogle burner
319         c = getch();
320         if (c==' ')
321             burner=!burner;
322         //if (c=='s')
323         //    show=!show;
324
325         //printf("Position: (%f/%f/%f), dP: (%f/%f/%f), burner: ", pos[0], pos[1], pos[2], dp[0], dp[1], dp[2]);
326         printf("%f         \t%f         \t%f         \t%f\n", acc_dt/60.0, bal.getTemperature()-273.16, pos[2], bal.getFuelLeft());
327         if (burner==true)
328         {
329             //printf("on\n");
330             bal.set_burner_strength(1.0);
331         }
332         else
333         {
334             //printf("off\n");
335             bal.set_burner_strength(0.0);
336         }
337
338     }
339 }
340 */