source: src/mlx/acft.py@ 322:1189006d3996

Last change on this file since 322:1189006d3996 was 321:8f6b55fb98ed, checked in by István Váradi <ivaradi@…>, 12 years ago

Added the forced logging of radio frequencies when entering certain stages of the flight

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