source: src/mlx/acft.py@ 243:1a42c5aa468b

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

Added the logging of the CoG value

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