source: src/mlx/acft.py@ 211:fbd8dad0b6be

Last change on this file since 211:fbd8dad0b6be 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
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 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 self._smoothedIAS = SmoothedValue()
126 self._smoothedVS = SmoothedValue()
127
128 @property
129 def type(self):
130 """Get the type of the aircraft."""
131 return self._flight.aircraftType
132
133 @property
134 def flight(self):
135 """Get the flight the aircraft belongs to."""
136 return self._flight
137
138 @property
139 def logger(self):
140 """Get the logger to use for the aircraft."""
141 return self._flight.logger
142
143 @property
144 def state(self):
145 """Get the current aircraft state."""
146 return self._aircraftState
147
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
153 def modelChanged(self, timestamp, aircraftName, modelName):
154 """Called when the simulator's aircraft changes."""
155 self._flight.logger.message(timestamp,
156 "Aircraft: name='%s', model='%s'" % \
157 (aircraftName, modelName))
158
159 def handleState(self, aircraftState):
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
172 for checker in self._checkers:
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()
179
180 self._flight.handleState(self._aircraftState, aircraftState)
181
182 self._maxVS = max(self._maxVS, aircraftState.vs)
183 self._minVS = min(self._minVS, aircraftState.vs)
184
185 self._aircraftState = aircraftState
186
187 def setStage(self, aircraftState, newStage):
188 """Set the given stage as the new one and do whatever should be
189 done."""
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))
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)
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))
210 self._logV1R2()
211 elif newStage==const.STAGE_TAXIAFTERLAND:
212 flight = self._flight
213 bookedFlight = flight.bookedFlight
214 config = flight.config
215 if config.onlineGateSystem and \
216 not flight.entranceExam and \
217 bookedFlight.arrivalICAO=="LHBP" and \
218 config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
219 self._flight.getFleet(callback = self._fleetRetrieved,
220 force = True)
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" % \
228 (self._minVS, self._maxVS))
229 elif newStage==const.STAGE_PARKING:
230 self.logger.message(aircraftState.timestamp, "Block time end")
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))
243
244 def prepareFlare(self):
245 """Called when it is detected that we will soon flare.
246
247 On the first call, it should start monitoring some parameters more
248 closely to determine flare time."""
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,))
263 self._logVRef()
264 self.flight.flareStarted(flareStart, flareStartFS)
265 fs.sendMessage(const.MESSAGETYPE_INFORMATION, "Flare-time", 3)
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,
271 flareEndFS,
272 tdRate)
273 self.logger.message(self._aircraftState.timestamp,
274 "Flaretime: %.3f (from %s)" % \
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,))
290
291 def cancelFlare(self):
292 """Cancel flare, if it has started."""
293 self.flight.simulator.cancelFlare()
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
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
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
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
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
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
377#---------------------------------------------------------------------------------------
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:
384 - fuel: left, centre, right
385 - n1: left, right
386 - reverser: left, right"""
387 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
388
389 def __init__(self, flight):
390 super(Boeing737, self).__init__(flight)
391 self._checkers.append(checks.ThrustChecker())
392
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 }
402
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" % \
407 (aircraftState.fuel[0], aircraftState.fuel[1],
408 aircraftState.fuel[2]))
409 self.logger.message(aircraftState.timestamp,
410 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
411
412#---------------------------------------------------------------------------------------
413
414class B736(Boeing737):
415 """Boeing 737-600 aircraft."""
416 def __init__(self, flight):
417 super(B736, self).__init__(flight)
418 self.dow = 38307
419 self.mtow = 58328
420 self.mlw = 54657
421 self.mzfw = 51482
422
423#---------------------------------------------------------------------------------------
424
425class B737(Boeing737):
426 """Boeing 737-700 aircraft."""
427 def __init__(self, flight):
428 super(B737, self).__init__(flight)
429 self.dow = 39250
430 self.mtow = 61410
431 self.mlw = 58059
432 self.mzfw = 54657
433
434#---------------------------------------------------------------------------------------
435
436class B738(Boeing737):
437 """Boeing 737-800 aircraft."""
438 def __init__(self, flight):
439 super(B738, self).__init__(flight)
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
452
453#---------------------------------------------------------------------------------------
454
455class B733(Boeing737):
456 """Boeing 737-300 aircraft."""
457 def __init__(self, flight):
458 super(B733, self).__init__(flight)
459 self.dow = 32700
460 self.mtow = 62820
461 self.mlw = 51700
462 self.mzfw = 48410
463
464#---------------------------------------------------------------------------------------
465
466class B734(Boeing737):
467 """Boeing 737-400 aircraft."""
468 def __init__(self, flight):
469 super(B734, self).__init__(flight)
470 self.dow = 33200
471 self.mtow = 68050
472 self.mlw = 56200
473 self.mzfw = 53100
474
475#---------------------------------------------------------------------------------------
476
477class B735(Boeing737):
478 """Boeing 737-500 aircraft."""
479 def __init__(self, flight):
480 super(B735, self).__init__(flight)
481 self.dow = 31300
482 self.mtow = 60550
483 self.mlw = 50000
484 self.mzfw = 46700
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:
493 - fuel: left, right
494 - n1: left, right
495 - reverser: left, right."""
496 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
497
498 def __init__(self, flight):
499 super(DH8D, self).__init__(flight)
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,
513 "Fuel: left=%.0f kg - right=%.0f kg" % \
514 (aircraftState.fuel[0], aircraftState.fuel[1]))
515 self.logger.message(aircraftState.timestamp,
516 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
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:
525 - fuel: left, centre, right
526 - n1: left, right
527 - reverser: left, right"""
528 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
529
530 def __init__(self, flight):
531 super(Boeing767, self).__init__(flight)
532 self._checkers.append(checks.ThrustChecker())
533 self.gearSpeedLimit = 270
534 self.flapSpeedLimits = { 1 : 255,
535 5 : 235,
536 10 : 215,
537 20 : 215,
538 25 : 185,
539 30 : 175 }
540
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" % \
545 (aircraftState.fuel[0], aircraftState.fuel[1],
546 aircraftState.fuel[2]))
547 self.logger.message(aircraftState.timestamp,
548 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
549
550#---------------------------------------------------------------------------------------
551
552class B762(Boeing767):
553 """Boeing 767-200 aircraft."""
554 def __init__(self, flight):
555 super(B762, self).__init__(flight)
556 self.dow = 84507
557 self.mtow = 175540
558 self.mlw = 126098
559 self.mzfw = 114758
560
561#---------------------------------------------------------------------------------------
562
563class B763(Boeing767):
564 """Boeing 767-300 aircraft."""
565 def __init__(self, flight):
566 super(B763, self).__init__(cflight)
567 self.dow = 91311
568 self.mtow = 181436
569 self.mlw = 137892
570 self.mzfw = 130635
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:
579 - fuel: left, centre, right
580 - n1: left, right
581 - reverser: left, right."""
582 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
583
584 def __init__(self, flight):
585 super(CRJ2, self).__init__(flight)
586 self._checkers.append(checks.ThrustChecker())
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 }
596
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" % \
601 (aircraftState.fuel[0], aircraftState.fuel[1],
602 aircraftState.fuel[2]))
603 self.logger.message(aircraftState.timestamp,
604 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
605
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:
613 - fuel: left, centre, right
614 - n1: left, right
615 - reverser: left, right."""
616 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
617
618 def __init__(self, flight):
619 super(F70, self).__init__(flight)
620 self._checkers.append(checks.ThrustChecker())
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 }
631
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" % \
636 (aircraftState.fuel[0], aircraftState.fuel[1],
637 aircraftState.fuel[2]))
638 self.logger.message(aircraftState.timestamp,
639 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
640
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:
648 - fuel: left aux, left, right, right aux
649 - rpm: left, right
650 - reverser: left, right."""
651 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
652 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
653
654 def __init__(self, flight):
655 super(DC3, self).__init__(flight)
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 }
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:
670 if rpm>0: return False
671 return True
672
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" % \
677 (aircraftState.fuel[0], aircraftState.fuel[1],
678 aircraftState.fuel[2], aircraftState.fuel[3]))
679 self.logger.message(aircraftState.timestamp,
680 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
681
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:
689 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
690 external 2
691 - n1: left, right
692 - reverser: left, right."""
693 fuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
694 const.FUELTANK_LEFT_AUX,
695 const.FUELTANK_CENTRE,
696 const.FUELTANK_RIGHT_AUX,
697 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
698
699 def __init__(self, flight):
700 super(T134, self).__init__(flight)
701 self._checkers.append(checks.ThrustChecker())
702 self.dow = 29500
703 self.mtow = 49000
704 self.mlw = 43000
705 self.mzfw = 38500
706 self.gearSpeedLimit = 216
707 self.flapSpeedLimits = { 10 : 450,
708 20 : 400,
709 30 : 300 }
710
711 def logFuel(self, aircraftState):
712 """Log the amount of fuel"""
713 self.logger.message(aircraftState.timestamp,
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],
716 aircraftState.fuel[2],
717 aircraftState.fuel[3], aircraftState.fuel[4],
718 aircraftState.fuel[5], aircraftState.fuel[6]))
719 self.logger.message(aircraftState.timestamp,
720 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
721
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
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:
741 - fuel: left aux, left, centre, centre 2, right, right aux
742 - n1: left, centre, right
743 - reverser: left, right"""
744 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
745 const.FUELTANK_CENTRE, const.FUELTANK_CENTRE2,
746 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
747 def __init__(self, flight):
748 super(T154, self).__init__(flight)
749 self._checkers.append(checks.ThrustChecker())
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" % \
763 (aircraftState.fuel[0], aircraftState.fuel[1],
764 aircraftState.fuel[2], aircraftState.fuel[3],
765 aircraftState.fuel[4], aircraftState.fuel[5]))
766 self.logger.message(aircraftState.timestamp,
767 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
768
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
781#---------------------------------------------------------------------------------------
782
783
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"""
792 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
793
794 def __init__(self, flight):
795 super(YK40, self).__init__(flight)
796 self._checkers.append(checks.ThrustChecker())
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),))
812
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
825#---------------------------------------------------------------------------------------
826
827MostFuelTankAircraft = T134
828
829#---------------------------------------------------------------------------------------
830
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 }
847
848#---------------------------------------------------------------------------------------
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.