source: src/mlx/acft.py@ 214:19fb20505b1a

Last change on this file since 214:19fb20505b1a was 211:fbd8dad0b6be, checked in by István Váradi <ivaradi@…>, 12 years ago

Reorganized the lights loggin and checks a bit

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