source: src/mlx/acft.py@ 239:d105a58c4273

Last change on this file since 239:d105a58c4273 was 215:bff7327b2da0, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for flying without logging in

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