FlightGear next
BalloonSim.cpp
Go to the documentation of this file.
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
27FUNCTIONAL DESCRIPTION
28------------------------------------------------------------------------------
29A hot air balloon simulator
30
31HISTORY
32------------------------------------------------------------------------------
3301.09.1999 Christian Mayer Created
3403.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 <cmath>
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/****************************************************************************/
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
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
234{
235 if ((bs>=0.0) && (bs<=1.0))
236 current_burner_strength = bs;
237}
238
239void balloon::getVelocity(SGVec3f& v) const
240{
241 v = velocity;
242}
243
244void balloon::setVelocity(const SGVec3f& v)
245{
246 velocity = v;
247}
248
249void balloon::getPosition(SGVec3f& v) const
250{
251 v = position;
252}
253
254void balloon::setPosition(const SGVec3f& v)
255{
256 position = v;
257}
258
259void balloon::getHPR(SGVec3f& angles) const //the balloon isn't allways exactly vertical
260{
261 angles = hpr;
262}
263
264void balloon::setHPR(const SGVec3f& angles) //the balloon isn't allways exactly vertical
265{
266 hpr = angles;
267}
268
270{
271 ground_level = altitude;
272}
273
274float balloon::getTemperature(void) const
275{
276 return T;
277}
278
279float balloon::getFuelLeft(void) const
280{
281 return fuel_left;
282}
283
284/*
285void 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
295bool 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*/
double altitude
Definition ADA.cxx:46
void getPosition(SGVec3f &v) const
void getVelocity(SGVec3f &v) const
void update()
void set_burner_strength(const float bs)
float getFuelLeft(void) const
void getHPR(SGVec3f &angles) const
void setVelocity(const SGVec3f &v)
void setGroundLevel(const float altitude)
void setHPR(const SGVec3f &angles)
float getTemperature(void) const
void setPosition(const SGVec3f &v)