source: src/mlx/acft.py@ 273:066f7271e849

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

Added the playback of approach callouts

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