source: src/mlx/acft.py@ 197:93f89e9049be

Last change on this file since 197:93f89e9049be was 197:93f89e9049be, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for smoothed IAS and VS values

File size: 32.4 KB
Line 
1# Module for the simulator-independent aircraft classes
2
3#---------------------------------------------------------------------------------------
4
5import const
6import checks
7import fs
8import util
9
10import sys
11import time
12import traceback
13
14from collections import deque
15
16#---------------------------------------------------------------------------------------
17
18class SmoothedValue(object):
19 """A smoothed value."""
20 def __init__(self):
21 """Construct the value."""
22 self._deque = deque()
23 self._sum = 0
24
25 def add(self, length, value):
26 """Add the given value and smooth with the given length."""
27 dequeLength = len(self._deque)
28 while dequeLength>=length:
29 self._sum -= self._deque.popleft()
30 dequeLength -= 1
31
32 self._sum += value
33 self._deque.append(value)
34
35 def get(self):
36 """Get the average."""
37 return self._sum / len(self._deque)
38
39#---------------------------------------------------------------------------------------
40
41class Aircraft(object):
42 """Base class for aircraft."""
43 @staticmethod
44 def create(flight):
45 """Create an aircraft instance for the type in the given flight."""
46 return _classes[flight.aircraftType](flight)
47
48 def __init__(self, flight):
49 """Construct the aircraft for the given type."""
50 self._flight = flight
51 self._aircraftState = None
52
53 self._maxVS = -10000.0
54 self._minVS = 10000.0
55
56 self._v1r2LineIndex = None
57 self._vrefLineIndex = None
58
59 self.humanWeight = 82.0
60
61 self._checkers = []
62
63 config = flight.config
64 # Loggers
65
66 self._checkers.append(checks.StageChecker())
67 self._checkers.append(checks.TakeOffLogger())
68
69 self._checkers.append(checks.AltimeterLogger())
70
71 self._checkers.append(checks.NAV1Logger())
72 self._checkers.append(checks.NAV2Logger())
73 self._checkers.append(checks.SquawkLogger())
74
75 self._checkers.append(checks.AnticollisionLightsLogger())
76 self._checkers.append(checks.LandingLightsLogger())
77 self._checkers.append(checks.StrobeLightsLogger())
78 self._checkers.append(checks.NavLightsLogger())
79
80 self._checkers.append(checks.FlapsLogger())
81
82 self._checkers.append(checks.GearsLogger())
83 self._checkers.append(checks.CruiseSpeedLogger())
84 self._checkers.append(checks.SpoilerLogger())
85
86 if config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
87 self._checkers.append(checks.VisibilityChecker())
88
89 # FIXME: we should have a central data model object, and not collect
90 # the data from the GUI. However, some pieces of data (e.g. V-speeds,
91 # etc. that is entered into the GUI) *should* be a part of the GUI and
92 # queried from it, so the model should have a reference to the GUI as
93 # well and access such data via the GUI!
94 if config.onlineACARS and not flight.entranceExam:
95 self._checkers.append(checks.ACARSSender(flight._gui))
96
97 # Fault checkers
98
99 self._checkers.append(checks.AntiCollisionLightsChecker())
100 self._checkers.append(checks.LandingLightsChecker())
101 self._checkers.append(checks.NavLightsChecker())
102 self._checkers.append(checks.StrobeLightsChecker())
103
104 self._checkers.append(checks.BankChecker())
105
106 self._checkers.append(checks.FlapsRetractChecker())
107 self._checkers.append(checks.FlapsSpeedLimitChecker())
108
109 self._checkers.append(checks.GearsDownChecker())
110 self._checkers.append(checks.GearSpeedLimitChecker())
111
112 self._checkers.append(checks.GLoadChecker())
113
114 self._checkers.append(checks.MLWChecker())
115 self._checkers.append(checks.MTOWChecker())
116 self._checkers.append(checks.MZFWChecker())
117 self._checkers.append(checks.PayloadChecker())
118
119 self._checkers.append(checks.SpeedChecker())
120 self._checkers.append(checks.VSChecker())
121
122 timeout = 5.0 + config.realIASSmoothingLength - 1
123 self._checkers.append(checks.OverspeedChecker(timeout = timeout))
124
125 self._checkers.append(checks.StallChecker())
126
127 self._checkers.append(checks.PitotChecker())
128
129 self._checkers.append(checks.ReverserChecker())
130
131 self._smoothedIAS = SmoothedValue()
132 self._smoothedVS = SmoothedValue()
133
134 @property
135 def type(self):
136 """Get the type of the aircraft."""
137 return self._flight.aircraftType
138
139 @property
140 def flight(self):
141 """Get the flight the aircraft belongs to."""
142 return self._flight
143
144 @property
145 def logger(self):
146 """Get the logger to use for the aircraft."""
147 return self._flight.logger
148
149 @property
150 def state(self):
151 """Get the current aircraft state."""
152 return self._aircraftState
153
154 def getFlapsSpeedLimit(self, flaps):
155 """Get the speed limit for the given flaps setting."""
156 return self.flapSpeedLimits[flaps] if flaps in self.flapSpeedLimits \
157 else None
158
159 def modelChanged(self, timestamp, aircraftName, modelName):
160 """Called when the simulator's aircraft changes."""
161 self._flight.logger.message(timestamp,
162 "Aircraft: name='%s', model='%s'" % \
163 (aircraftName, modelName))
164
165 def handleState(self, aircraftState):
166 """Called when the state of the aircraft changes.
167
168 This is the function that the simulator calls directly with the new
169 state."""
170 config = self._flight.config
171
172 self._smoothedIAS.add(config.realIASSmoothingLength, aircraftState.ias)
173 aircraftState.smoothedIAS = self._smoothedIAS.get()
174
175 print "handleState, realVSSmoothingLength:", config.realVSSmoothingLength
176 self._smoothedVS.add(config.realVSSmoothingLength, aircraftState.vs)
177 aircraftState.smoothedVS = self._smoothedVS.get()
178
179 for checker in self._checkers:
180 try:
181 checker.check(self._flight, self, self._flight.logger,
182 self._aircraftState, aircraftState)
183 except:
184 print >> sys.stderr, "Checker", checker, "failed"
185 traceback.print_exc()
186
187 self._flight.handleState(self._aircraftState, aircraftState)
188
189 self._maxVS = max(self._maxVS, aircraftState.vs)
190 self._minVS = min(self._minVS, aircraftState.vs)
191
192 self._aircraftState = aircraftState
193
194 def setStage(self, aircraftState, newStage):
195 """Set the given stage as the new one and do whatever should be
196 done."""
197 if self._flight.setStage(aircraftState.timestamp, newStage):
198 if newStage==const.STAGE_PUSHANDTAXI:
199 self.logger.message(aircraftState.timestamp, "Block time start")
200 self.logFuel(aircraftState)
201 self.logger.message(aircraftState.timestamp,
202 "Zero-fuel weight: %.0f kg" % (aircraftState.zfw))
203 flight = self._flight
204 if flight.v1 is None or flight.vr is None or flight.v2 is None:
205 fs.sendMessage(const.MESSAGETYPE_HELP,
206 "Don't forget to set the takeoff V-speeds!",
207 5)
208 elif newStage==const.STAGE_TAKEOFF:
209 self.logger.message(aircraftState.timestamp, "Flight time start")
210 self.logger.message(aircraftState.timestamp,
211 "Takeoff weight: %.0f kg, MTOW: %.0f kg" % \
212 (aircraftState.grossWeight, self.mtow))
213 self.logger.message(aircraftState.timestamp,
214 "Wind %03.0f degrees at %.0f knots" % \
215 (aircraftState.windDirection,
216 aircraftState.windSpeed))
217 self._logV1R2()
218 elif newStage==const.STAGE_TAXIAFTERLAND:
219 flight = self._flight
220 bookedFlight = flight.bookedFlight
221 config = flight.config
222 if config.onlineGateSystem and \
223 not flight.entranceExam and \
224 bookedFlight.arrivalICAO=="LHBP" and \
225 config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
226 self._flight.getFleet(callback = self._fleetRetrieved,
227 force = True)
228 self.logger.message(aircraftState.timestamp, "Flight time end")
229 self.logFuel(aircraftState)
230 self.logger.message(aircraftState.timestamp,
231 "Landing weight: %.0f kg, MLW: %.0f" % \
232 (aircraftState.grossWeight, self.mlw))
233 self.logger.message(aircraftState.timestamp,
234 "Vertical speed range: %.0f..%.0f feet/min" % \
235 (self._minVS, self._maxVS))
236 elif newStage==const.STAGE_PARKING:
237 self.logger.message(aircraftState.timestamp, "Block time end")
238 elif newStage==const.STAGE_END:
239 flightLength = self._flight.flightTimeEnd - self._flight.flightTimeStart
240 self.logger.message(aircraftState.timestamp,
241 "Flight time: " +
242 util.getTimeIntervalString(flightLength))
243 self.logger.message(aircraftState.timestamp,
244 "Flown distance: %.2f NM" % \
245 (self._flight.flownDistance,))
246 blockLength = self._flight.blockTimeEnd - self._flight.blockTimeStart
247 self.logger.message(aircraftState.timestamp,
248 "Block time: " +
249 util.getTimeIntervalString(blockLength))
250
251 def prepareFlare(self):
252 """Called when it is detected that we will soon flare.
253
254 On the first call, it should start monitoring some parameters more
255 closely to determine flare time."""
256 self.flight.simulator.startFlare()
257
258 def flareStarted(self, windSpeed, windDirection, visibility,
259 flareStart, flareStartFS):
260 """Called when the flare has started."""
261 self.logger.message(self._aircraftState.timestamp, "The flare has begun")
262 self.logger.message(self._aircraftState.timestamp,
263 "Wind %03.0f degrees at %.0f knots" % \
264 (windDirection, windSpeed))
265 self.logger.message(self._aircraftState.timestamp,
266 "Visibility: %.0f metres" % (visibility,))
267 self.logger.message(self._aircraftState.timestamp,
268 "Altimeter setting: %.0f hPa" % \
269 (self._aircraftState.altimeter,))
270 self._logVRef()
271 self.flight.flareStarted(flareStart, flareStartFS)
272 fs.sendMessage(const.MESSAGETYPE_INFORMATION, "Flare-time", 3)
273
274 def flareFinished(self, flareEnd, flareEndFS, tdRate, tdRateCalculatedByFS,
275 ias, pitch, bank, heading):
276 """Called when the flare has finished."""
277 (flareTimeFromFS, flareTime) = self.flight.flareFinished(flareEnd,
278 flareEndFS,
279 tdRate)
280 self.logger.message(self._aircraftState.timestamp,
281 "Flaretime: %.3f (from %s)" % \
282 (flareTime,
283 "the simulator" if flareTimeFromFS else "real time",))
284 self.logger.message(self._aircraftState.timestamp,
285 "Touchdown rate: %.0f feet/min" % (tdRate,))
286 self.logger.message(self._aircraftState.timestamp,
287 "Touchdown rate was calculated by the %s" % \
288 ("simulator" if tdRateCalculatedByFS else "logger",))
289 self.logger.message(self._aircraftState.timestamp,
290 "Touchdown speed: %.0f knots" % (ias,))
291 self.logger.message(self._aircraftState.timestamp,
292 "Touchdown pitch: %.1f degrees" % (pitch,))
293 self.logger.message(self._aircraftState.timestamp,
294 "Touchdown bank: %.1f degrees" % (bank,))
295 self.logger.message(self._aircraftState.timestamp,
296 "Touchdown heading: %03.0f degrees" % (heading,))
297
298 def cancelFlare(self):
299 """Cancel flare, if it has started."""
300 self.flight.simulator.cancelFlare()
301
302 def checkFlightEnd(self, aircraftState):
303 """Check if the end of the flight has arrived.
304
305 This default implementation checks the N1 values, but for
306 piston-powered aircraft you need to check the RPMs."""
307 for n1 in aircraftState.n1:
308 if n1>=0.5: return False
309 return True
310
311 def updateV1R2(self):
312 """Update the V1, Vr and V2 values from the flight, if the these values
313 have already been logged."""
314 if self._v1r2LineIndex is not None:
315 self._logV1R2()
316
317 def _logV1R2(self):
318 """Log the V1, Vr and V2 value either newly, or by updating the
319 corresponding line."""
320 message = "Speeds calculated by the pilot: V1: %s, VR: %s, V2: %s" % \
321 ("-" if self._flight.v1 is None
322 else str(self._flight.v1),
323 "-" if self._flight.vr is None
324 else str(self._flight.vr),
325 "-" if self._flight.v2 is None
326 else str(self._flight.v2))
327
328 if self._v1r2LineIndex is None:
329 self._v1r2LineIndex = \
330 self.logger.message(self._aircraftState.timestamp, message)
331 else:
332 self.logger.updateLine(self._v1r2LineIndex, message)
333
334 def updateVRef(self):
335 """Update the Vref value from the flight, if the Vref value has already
336 been logged."""
337 if self._vrefLineIndex is not None:
338 self._logVRef()
339
340 def _logVRef(self):
341 """Log the Vref value either newly, or by updating the corresponding
342 line."""
343 message = "VRef speed calculated by the pilot: %s" % \
344 ("-" if self._flight.vref is None else str(self._flight.vref))
345 if self._vrefLineIndex is None:
346 self._vrefLineIndex = \
347 self.logger.message(self._aircraftState.timestamp, message)
348 else:
349 self.logger.updateLine(self._vrefLineIndex, message)
350
351 def _fleetRetrieved(self, fleet):
352 """Callback for the fleet retrieval result."""
353 if fleet is not None:
354 gateList = ""
355 occupiedGateNumbers = fleet.getOccupiedGateNumbers()
356 for gateNumber in const.lhbpGateNumbers:
357 if gateNumber not in occupiedGateNumbers:
358 if gateList: gateList += ", "
359 gateList += gateNumber
360 fs.sendMessage(const.MESSAGETYPE_GATE_SYSTEM,
361 "Free gates: " + gateList, 20)
362
363
364#---------------------------------------------------------------------------------------
365
366class Boeing737(Aircraft):
367 """Base class for the various aircraft in the Boeing 737 family.
368
369 The aircraft type-specific values in the aircraft state have the following
370 structure:
371 - fuel: left, centre, right
372 - n1: left, right
373 - reverser: left, right"""
374 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
375
376 def __init__(self, flight):
377 super(Boeing737, self).__init__(flight)
378 self._checkers.append(checks.ThrustChecker())
379
380 self.gearSpeedLimit = 270
381 self.flapSpeedLimits = { 1 : 260,
382 2 : 260,
383 5 : 250,
384 10 : 210,
385 15 : 200,
386 25 : 190,
387 30 : 175,
388 40 : 162 }
389
390 def logFuel(self, aircraftState):
391 """Log the amount of fuel"""
392 self.logger.message(aircraftState.timestamp,
393 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
394 (aircraftState.fuel[0], aircraftState.fuel[1],
395 aircraftState.fuel[2]))
396 self.logger.message(aircraftState.timestamp,
397 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
398
399#---------------------------------------------------------------------------------------
400
401class B736(Boeing737):
402 """Boeing 737-600 aircraft."""
403 def __init__(self, flight):
404 super(B736, self).__init__(flight)
405 self.dow = 38307
406 self.mtow = 58328
407 self.mlw = 54657
408 self.mzfw = 51482
409
410#---------------------------------------------------------------------------------------
411
412class B737(Boeing737):
413 """Boeing 737-700 aircraft."""
414 def __init__(self, flight):
415 super(B737, self).__init__(flight)
416 self.dow = 39250
417 self.mtow = 61410
418 self.mlw = 58059
419 self.mzfw = 54657
420
421#---------------------------------------------------------------------------------------
422
423class B738(Boeing737):
424 """Boeing 737-800 aircraft."""
425 def __init__(self, flight):
426 super(B738, self).__init__(flight)
427 self.dow = 42690
428 self.mtow = 71709
429 self.mlw = 65317
430 self.mzfw = 61688
431
432#---------------------------------------------------------------------------------------
433
434class B738Charter(B738):
435 """Boeing 737-800 aircraft used for charters."""
436 def __init__(self, flight):
437 super(B738Charter, self).__init__(flight)
438 self.mtow = 77791
439
440#---------------------------------------------------------------------------------------
441
442class B733(Boeing737):
443 """Boeing 737-300 aircraft."""
444 def __init__(self, flight):
445 super(B733, self).__init__(flight)
446 self.dow = 32700
447 self.mtow = 62820
448 self.mlw = 51700
449 self.mzfw = 48410
450
451#---------------------------------------------------------------------------------------
452
453class B734(Boeing737):
454 """Boeing 737-400 aircraft."""
455 def __init__(self, flight):
456 super(B734, self).__init__(flight)
457 self.dow = 33200
458 self.mtow = 68050
459 self.mlw = 56200
460 self.mzfw = 53100
461
462#---------------------------------------------------------------------------------------
463
464class B735(Boeing737):
465 """Boeing 737-500 aircraft."""
466 def __init__(self, flight):
467 super(B735, self).__init__(flight)
468 self.dow = 31300
469 self.mtow = 60550
470 self.mlw = 50000
471 self.mzfw = 46700
472
473#---------------------------------------------------------------------------------------
474
475class DH8D(Aircraft):
476 """Bombardier Dash-8 Q400 aircraft.
477
478 The aircraft type-specific values in the aircraft state have the following
479 structure:
480 - fuel: left, right
481 - n1: left, right
482 - reverser: left, right."""
483 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
484
485 def __init__(self, flight):
486 super(DH8D, self).__init__(flight)
487 self.dow = 17185
488 self.mtow = 29257
489 self.mlw = 28009
490 self.mzfw = 25855
491 self.gearSpeedLimit = 215
492 self.flapSpeedLimits = { 5 : 200,
493 10 : 181,
494 15 : 172,
495 35 : 158 }
496
497 def logFuel(self, aircraftState):
498 """Log the amount of fuel"""
499 self.logger.message(aircraftState.timestamp,
500 "Fuel: left=%.0f kg - right=%.0f kg" % \
501 (aircraftState.fuel[0], aircraftState.fuel[1]))
502 self.logger.message(aircraftState.timestamp,
503 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
504
505#---------------------------------------------------------------------------------------
506
507class Boeing767(Aircraft):
508 """Base class for the various aircraft in the Boeing 767 family.
509
510 The aircraft type-specific values in the aircraft state have the following
511 structure:
512 - fuel: left, centre, right
513 - n1: left, right
514 - reverser: left, right"""
515 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
516
517 def __init__(self, flight):
518 super(Boeing767, self).__init__(flight)
519 self._checkers.append(checks.ThrustChecker())
520 self.gearSpeedLimit = 270
521 self.flapSpeedLimits = { 1 : 255,
522 5 : 235,
523 10 : 215,
524 20 : 215,
525 25 : 185,
526 30 : 175 }
527
528 def logFuel(self, aircraftState):
529 """Log the amount of fuel"""
530 self.logger.message(aircraftState.timestamp,
531 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
532 (aircraftState.fuel[0], aircraftState.fuel[1],
533 aircraftState.fuel[2]))
534 self.logger.message(aircraftState.timestamp,
535 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
536
537#---------------------------------------------------------------------------------------
538
539class B762(Boeing767):
540 """Boeing 767-200 aircraft."""
541 def __init__(self, flight):
542 super(B762, self).__init__(flight)
543 self.dow = 84507
544 self.mtow = 175540
545 self.mlw = 126098
546 self.mzfw = 114758
547
548#---------------------------------------------------------------------------------------
549
550class B763(Boeing767):
551 """Boeing 767-300 aircraft."""
552 def __init__(self, flight):
553 super(B763, self).__init__(cflight)
554 self.dow = 91311
555 self.mtow = 181436
556 self.mlw = 137892
557 self.mzfw = 130635
558
559#---------------------------------------------------------------------------------------
560
561class CRJ2(Aircraft):
562 """Bombardier CRJ-200 aircraft.
563
564 The aircraft type-specific values in the aircraft state have the following
565 structure:
566 - fuel: left, centre, right
567 - n1: left, right
568 - reverser: left, right."""
569 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
570
571 def __init__(self, flight):
572 super(CRJ2, self).__init__(flight)
573 self._checkers.append(checks.ThrustChecker())
574 self.dow = 14549
575 self.mtow = 22995
576 self.mlw = 21319
577 self.mzfw = 19958
578 self.gearSpeedLimit = 240
579 self.flapSpeedLimits = { 8 : 260,
580 20 : 220,
581 30 : 190,
582 45 : 175 }
583
584 def logFuel(self, aircraftState):
585 """Log the amount of fuel"""
586 self.logger.message(aircraftState.timestamp,
587 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
588 (aircraftState.fuel[0], aircraftState.fuel[1],
589 aircraftState.fuel[2]))
590 self.logger.message(aircraftState.timestamp,
591 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
592
593#---------------------------------------------------------------------------------------
594
595class F70(Aircraft):
596 """Fokker 70 aircraft.
597
598 The aircraft type-specific values in the aircraft state have the following
599 structure:
600 - fuel: left, centre, right
601 - n1: left, right
602 - reverser: left, right."""
603 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
604
605 def __init__(self, flight):
606 super(F70, self).__init__(flight)
607 self._checkers.append(checks.ThrustChecker())
608 self.dow = 24283
609 self.mtow = 38100 # FIXME: differentiate by registration number,
610 # MTOW of HA-LMF: 41955
611 self.mlw = 36740
612 self.mzfw = 32655
613 self.gearSpeedLimit = 200
614 self.flapSpeedLimits = { 8 : 250,
615 15 : 220,
616 25 : 220,
617 42 : 180 }
618
619 def logFuel(self, aircraftState):
620 """Log the amount of fuel"""
621 self.logger.message(aircraftState.timestamp,
622 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
623 (aircraftState.fuel[0], aircraftState.fuel[1],
624 aircraftState.fuel[2]))
625 self.logger.message(aircraftState.timestamp,
626 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
627
628#---------------------------------------------------------------------------------------
629
630class DC3(Aircraft):
631 """Lisunov Li-2 (DC-3) aircraft.
632
633 The aircraft type-specific values in the aircraft state have the following
634 structure:
635 - fuel: left aux, left, right, right aux
636 - rpm: left, right
637 - reverser: left, right."""
638 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
639 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
640
641 def __init__(self, flight):
642 super(DC3, self).__init__(flight)
643 self.dow = 8627
644 self.mtow = 11884
645 self.mlw = 11793
646 self.mzfw = 11780
647 self.gearSpeedLimit = 148
648 self.flapSpeedLimits = { 15 : 135,
649 30 : 99,
650 45 : 97 }
651
652 def _checkFlightEnd(self, aircraftState):
653 """Check if the end of the flight has arrived.
654
655 This implementation checks the RPM values to be 0."""
656 for rpm in aircraftState.rpm:
657 if rpm>0: return False
658 return True
659
660 def logFuel(self, aircraftState):
661 """Log the amount of fuel"""
662 self.logger.message(aircraftState.timestamp,
663 "Fuel: left aux=%.0f kg - left=%.0f kg - right=%.0f kg - right aux=%.0f kg" % \
664 (aircraftState.fuel[0], aircraftState.fuel[1],
665 aircraftState.fuel[2], aircraftState.fuel[3]))
666 self.logger.message(aircraftState.timestamp,
667 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
668
669#---------------------------------------------------------------------------------------
670
671class T134(Aircraft):
672 """Tupolev Tu-134 aircraft.
673
674 The aircraft type-specific values in the aircraft state have the following
675 structure:
676 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
677 external 2
678 - n1: left, right
679 - reverser: left, right."""
680 fuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_LEFT_AUX,
681 const.FUELTANK_CENTRE,
682 const.FUELTANK_RIGHT_AUX, const.FUELTANK_RIGHT_TIP,
683 const.FUELTANK_EXTERNAL1, const.FUELTANK_EXTERNAL2]
684
685 def __init__(self, flight):
686 super(T134, self).__init__(flight)
687 self._checkers.append(checks.ThrustChecker())
688 self.dow = 29927
689 self.mtow = 47600
690 self.mlw = 43000
691 self.mzfw = 38500
692 self.gearSpeedLimit = 216
693 self.flapSpeedLimits = { 10 : 240,
694 20 : 216,
695 30 : 161 }
696
697 def logFuel(self, aircraftState):
698 """Log the amount of fuel"""
699 self.logger.message(aircraftState.timestamp,
700 "Fuel: left aux=%.0f kg - left tip=%.0f kg - centre= %.0f kg - right tip=%.0f kg - right aux=%.0f kg - external 1=%.0f kg - external 2=%.0f kg" % \
701 (aircraftState.fuel[1], aircraftState.fuel[0],
702 aircraftState.fuel[2],
703 aircraftState.fuel[4], aircraftState.fuel[3],
704 aircraftState.fuel[5], aircraftState.fuel[6]))
705 self.logger.message(aircraftState.timestamp,
706 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
707
708#---------------------------------------------------------------------------------------
709
710class T154(Aircraft):
711 """Tupolev Tu-154 aircraft.
712
713 The aircraft type-specific values in the aircraft state have the following
714 structure:
715 - fuel: left aux, left, centre, centre 2, right, right aux
716 - n1: left, centre, right
717 - reverser: left, right"""
718 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
719 const.FUELTANK_CENTRE, const.FUELTANK_CENTRE2,
720 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
721 def __init__(self, flight):
722 super(T154, self).__init__(flight)
723 self._checkers.append(checks.ThrustChecker())
724 self.dow = 53259
725 self.mtow = 98000
726 self.mlw = 78000
727 self.mzfw = 72000
728 self.gearSpeedLimit = 216
729 self.flapSpeedLimits = { 15 : 227,
730 28 : 194,
731 45 : 162 }
732
733 def logFuel(self, aircraftState):
734 """Log the amount of fuel"""
735 self.logger.message(aircraftState.timestamp,
736 "Fuel: left aux=%.0f kg - left=%.0f kg - centre=%.0f kg - centre 2=%.0f kg - right=%.0f kg - right aux=%.0f kg" % \
737 (aircraftState.fuel[0], aircraftState.fuel[1],
738 aircraftState.fuel[2], aircraftState.fuel[3],
739 aircraftState.fuel[4], aircraftState.fuel[5]))
740 self.logger.message(aircraftState.timestamp,
741 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
742
743#---------------------------------------------------------------------------------------
744
745
746class YK40(Aircraft):
747 """Yakovlev Yak-40 aircraft.
748
749 The aircraft type-specific values in the aircraft state have the following
750 structure:
751 - fuel: left, right
752 - n1: left, right
753 - reverser: left, right"""
754 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
755
756 def __init__(self, flight):
757 super(YK40, self).__init__(flight)
758 self._checkers.append(checks.ThrustChecker())
759 self.dow = 9400
760 self.mtow = 17200
761 self.mlw = 16800
762 self.mzfw = 12100
763 self.gearSpeedLimit = 165
764 self.flapSpeedLimits = { 20 : 165,
765 35 : 135 }
766
767 def logFuel(self, aircraftState):
768 """Log the amount of fuel"""
769 self.logger.message(aircraftState.timestamp,
770 "Fuel: left=%.0f kg - right=%.0f kg" % \
771 (aircraftState.fuel[0], aircraftState.fuel[1]))
772 self.logger.message(aircraftState.timestamp,
773 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
774
775#---------------------------------------------------------------------------------------
776
777MostFuelTankAircraft = T134
778
779#---------------------------------------------------------------------------------------
780
781_classes = { const.AIRCRAFT_B736 : B736,
782 const.AIRCRAFT_B737 : B737,
783 const.AIRCRAFT_B738 : B738,
784 const.AIRCRAFT_B738C : B738Charter,
785 const.AIRCRAFT_B733 : B733,
786 const.AIRCRAFT_B734 : B734,
787 const.AIRCRAFT_B735 : B735,
788 const.AIRCRAFT_DH8D : DH8D,
789 const.AIRCRAFT_B762 : B762,
790 const.AIRCRAFT_B763 : B763,
791 const.AIRCRAFT_CRJ2 : CRJ2,
792 const.AIRCRAFT_F70 : F70,
793 const.AIRCRAFT_DC3 : DC3,
794 const.AIRCRAFT_T134 : T134,
795 const.AIRCRAFT_T154 : T154,
796 const.AIRCRAFT_YK40 : YK40 }
797
798#---------------------------------------------------------------------------------------
799
800if __name__ == "__main__":
801 value = SmoothedValue()
802
803 print "Adding 1, 12.0"
804 value.add(1, 12.0)
805 print value.get()
806
807 print "Adding 1, 15.0"
808 value.add(1, 15.0)
809 print value.get()
810
811 print "Adding 2, 18.0"
812 value.add(2, 18.0)
813 print value.get()
814
815 print "Adding 2, 20.0"
816 value.add(2, 20.0)
817 print value.get()
818
819 print "Adding 5, 22.0"
820 value.add(5, 22.0)
821 print value.get()
822
823 print "Adding 5, 25.0"
824 value.add(5, 25.0)
825 print value.get()
826
827 print "Adding 5, 29.0"
828 value.add(5, 29.0)
829 print value.get()
830
831 print "Adding 5, 21.0"
832 value.add(5, 21.0)
833 print value.get()
834
835 print "Adding 5, 26.0"
836 value.add(5, 26.0)
837 print value.get()
838
839 print "Adding 2, 30.0"
840 value.add(2, 30.0)
841 print value.get()
842
843 print "Adding 2, 55.0"
844 value.add(2, 55.0)
845 print value.get()
846
847#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.