source: src/mlx/acft.py@ 204:6616046534cf

Last change on this file since 204:6616046534cf was 198:b75c849e59d8, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for smoothed IAS and VS values

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