source: src/mlx/acft.py@ 241:dea155dd3ac0

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

Added support for calculating speeds in km/h for Soviet aircraft

File size: 35.4 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
303 def cancelFlare(self):
304 """Cancel flare, if it has started."""
305 self.flight.simulator.cancelFlare()
306
307 def checkFlightEnd(self, aircraftState):
308 """Check if the end of the flight has arrived.
309
310 This default implementation checks the N1 values, but for
311 piston-powered aircraft you need to check the RPMs."""
312 for n1 in aircraftState.n1:
313 if n1>=0.5: return False
314 return True
315
316 def updateV1R2(self):
317 """Update the V1, Vr and V2 values from the flight, if the these values
318 have already been logged."""
319 if self._v1r2LineIndex is not None:
320 self._logV1R2()
321
322 def _appendLightsLoggers(self):
323 """Append the loggers needed for the lights.
324
325 This default implementation adds the loggers for the anti-collision
326 lights, the landing lights, the strobe lights and the NAV lights."""
327 self._checkers.append(checks.AnticollisionLightsLogger())
328 self._checkers.append(checks.LandingLightsLogger())
329 self._checkers.append(checks.StrobeLightsLogger())
330 self._checkers.append(checks.NavLightsLogger())
331
332 def _appendLightsCheckers(self):
333 """Append the checkers needed for the lights.
334
335 This default implementation adds the checkers for the anti-collision
336 lights, the landing lights, the strobe lights and the NAV lights."""
337 self._checkers.append(checks.AntiCollisionLightsChecker())
338 self._checkers.append(checks.LandingLightsChecker())
339 self._checkers.append(checks.NavLightsChecker())
340 self._checkers.append(checks.StrobeLightsChecker())
341
342 def _speedToLog(self, speed):
343 """Convert the given speed (being either None or expressed in the
344 flight's speed unit into a string."""
345 if speed is None:
346 return "-"
347 else:
348 return str(speed) + " " + self._flight.getEnglishSpeedUnit()
349
350 def _logV1R2(self):
351 """Log the V1, Vr and V2 value either newly, or by updating the
352 corresponding line."""
353 message = "Speeds calculated by the pilot: V1: %s, VR: %s, V2: %s" % \
354 (self._speedToLog(self._flight.v1),
355 self._speedToLog(self._flight.vr),
356 self._speedToLog(self._flight.v2))
357
358 if self._v1r2LineIndex is None:
359 self._v1r2LineIndex = \
360 self.logger.message(self._aircraftState.timestamp, message)
361 else:
362 self.logger.updateLine(self._v1r2LineIndex, message)
363
364 def updateVRef(self):
365 """Update the Vref value from the flight, if the Vref value has already
366 been logged."""
367 if self._vrefLineIndex is not None:
368 self._logVRef()
369
370 def _logVRef(self):
371 """Log the Vref value either newly, or by updating the corresponding
372 line."""
373 message = "VRef speed calculated by the pilot: %s" % \
374 (self._speedToLog(self._flight.vref),)
375 if self._vrefLineIndex is None:
376 self._vrefLineIndex = \
377 self.logger.message(self._aircraftState.timestamp, message)
378 else:
379 self.logger.updateLine(self._vrefLineIndex, message)
380
381 def _fleetRetrieved(self, fleet):
382 """Callback for the fleet retrieval result."""
383 if fleet is not None:
384 gateList = ""
385 occupiedGateNumbers = fleet.getOccupiedGateNumbers()
386 for gateNumber in const.lhbpGateNumbers:
387 if gateNumber not in occupiedGateNumbers:
388 if gateList: gateList += ", "
389 gateList += gateNumber
390 fs.sendMessage(const.MESSAGETYPE_GATE_SYSTEM,
391 "Free gates: " + gateList, 20)
392
393
394#---------------------------------------------------------------------------------------
395
396class Boeing737(Aircraft):
397 """Base class for the various aircraft in the Boeing 737 family.
398
399 The aircraft type-specific values in the aircraft state have the following
400 structure:
401 - fuel: left, centre, right
402 - n1: left, right
403 - reverser: left, right"""
404 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
405
406 def __init__(self, flight):
407 super(Boeing737, self).__init__(flight)
408 self._checkers.append(checks.ThrustChecker())
409
410 self.gearSpeedLimit = 270
411 self.flapSpeedLimits = { 1 : 260,
412 2 : 260,
413 5 : 250,
414 10 : 210,
415 15 : 200,
416 25 : 190,
417 30 : 175,
418 40 : 162 }
419
420 def logFuel(self, aircraftState):
421 """Log the amount of fuel"""
422 self.logger.message(aircraftState.timestamp,
423 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
424 (aircraftState.fuel[0], aircraftState.fuel[1],
425 aircraftState.fuel[2]))
426 self.logger.message(aircraftState.timestamp,
427 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
428
429#---------------------------------------------------------------------------------------
430
431class B736(Boeing737):
432 """Boeing 737-600 aircraft."""
433 def __init__(self, flight):
434 super(B736, self).__init__(flight)
435 self.dow = 38307
436 self.mtow = 58328
437 self.mlw = 54657
438 self.mzfw = 51482
439
440#---------------------------------------------------------------------------------------
441
442class B737(Boeing737):
443 """Boeing 737-700 aircraft."""
444 def __init__(self, flight):
445 super(B737, self).__init__(flight)
446 self.dow = 39250
447 self.mtow = 61410
448 self.mlw = 58059
449 self.mzfw = 54657
450
451#---------------------------------------------------------------------------------------
452
453class B738(Boeing737):
454 """Boeing 737-800 aircraft."""
455 def __init__(self, flight):
456 super(B738, self).__init__(flight)
457 self.dow = 42690
458 self.mtow = 71709
459 self.mlw = 65317
460 self.mzfw = 61688
461
462#---------------------------------------------------------------------------------------
463
464class B738Charter(B738):
465 """Boeing 737-800 aircraft used for charters."""
466 def __init__(self, flight):
467 super(B738Charter, self).__init__(flight)
468 self.mtow = 77791
469
470#---------------------------------------------------------------------------------------
471
472class B733(Boeing737):
473 """Boeing 737-300 aircraft."""
474 def __init__(self, flight):
475 super(B733, self).__init__(flight)
476 self.dow = 32700
477 self.mtow = 62820
478 self.mlw = 51700
479 self.mzfw = 48410
480
481#---------------------------------------------------------------------------------------
482
483class B734(Boeing737):
484 """Boeing 737-400 aircraft."""
485 def __init__(self, flight):
486 super(B734, self).__init__(flight)
487 self.dow = 33200
488 self.mtow = 68050
489 self.mlw = 56200
490 self.mzfw = 53100
491
492#---------------------------------------------------------------------------------------
493
494class B735(Boeing737):
495 """Boeing 737-500 aircraft."""
496 def __init__(self, flight):
497 super(B735, self).__init__(flight)
498 self.dow = 31300
499 self.mtow = 60550
500 self.mlw = 50000
501 self.mzfw = 46700
502
503#---------------------------------------------------------------------------------------
504
505class DH8D(Aircraft):
506 """Bombardier Dash-8 Q400 aircraft.
507
508 The aircraft type-specific values in the aircraft state have the following
509 structure:
510 - fuel: left, right
511 - n1: left, right
512 - reverser: left, right."""
513 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
514
515 def __init__(self, flight):
516 super(DH8D, self).__init__(flight)
517 self.dow = 17185
518 self.mtow = 29257
519 self.mlw = 28009
520 self.mzfw = 25855
521 self.gearSpeedLimit = 215
522 self.flapSpeedLimits = { 5 : 200,
523 10 : 181,
524 15 : 172,
525 35 : 158 }
526
527 def logFuel(self, aircraftState):
528 """Log the amount of fuel"""
529 self.logger.message(aircraftState.timestamp,
530 "Fuel: left=%.0f kg - right=%.0f kg" % \
531 (aircraftState.fuel[0], aircraftState.fuel[1]))
532 self.logger.message(aircraftState.timestamp,
533 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
534
535#---------------------------------------------------------------------------------------
536
537class Boeing767(Aircraft):
538 """Base class for the various aircraft in the Boeing 767 family.
539
540 The aircraft type-specific values in the aircraft state have the following
541 structure:
542 - fuel: left, centre, right
543 - n1: left, right
544 - reverser: left, right"""
545 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
546
547 def __init__(self, flight):
548 super(Boeing767, self).__init__(flight)
549 self._checkers.append(checks.ThrustChecker())
550 self.gearSpeedLimit = 270
551 self.flapSpeedLimits = { 1 : 255,
552 5 : 235,
553 10 : 215,
554 20 : 215,
555 25 : 185,
556 30 : 175 }
557
558 def logFuel(self, aircraftState):
559 """Log the amount of fuel"""
560 self.logger.message(aircraftState.timestamp,
561 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
562 (aircraftState.fuel[0], aircraftState.fuel[1],
563 aircraftState.fuel[2]))
564 self.logger.message(aircraftState.timestamp,
565 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
566
567#---------------------------------------------------------------------------------------
568
569class B762(Boeing767):
570 """Boeing 767-200 aircraft."""
571 def __init__(self, flight):
572 super(B762, self).__init__(flight)
573 self.dow = 84507
574 self.mtow = 175540
575 self.mlw = 126098
576 self.mzfw = 114758
577
578#---------------------------------------------------------------------------------------
579
580class B763(Boeing767):
581 """Boeing 767-300 aircraft."""
582 def __init__(self, flight):
583 super(B763, self).__init__(cflight)
584 self.dow = 91311
585 self.mtow = 181436
586 self.mlw = 137892
587 self.mzfw = 130635
588
589#---------------------------------------------------------------------------------------
590
591class CRJ2(Aircraft):
592 """Bombardier CRJ-200 aircraft.
593
594 The aircraft type-specific values in the aircraft state have the following
595 structure:
596 - fuel: left, centre, right
597 - n1: left, right
598 - reverser: left, right."""
599 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
600
601 def __init__(self, flight):
602 super(CRJ2, self).__init__(flight)
603 self._checkers.append(checks.ThrustChecker())
604 self.dow = 14549
605 self.mtow = 22995
606 self.mlw = 21319
607 self.mzfw = 19958
608 self.gearSpeedLimit = 240
609 self.flapSpeedLimits = { 8 : 260,
610 20 : 220,
611 30 : 190,
612 45 : 175 }
613
614 def logFuel(self, aircraftState):
615 """Log the amount of fuel"""
616 self.logger.message(aircraftState.timestamp,
617 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
618 (aircraftState.fuel[0], aircraftState.fuel[1],
619 aircraftState.fuel[2]))
620 self.logger.message(aircraftState.timestamp,
621 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
622
623#---------------------------------------------------------------------------------------
624
625class F70(Aircraft):
626 """Fokker 70 aircraft.
627
628 The aircraft type-specific values in the aircraft state have the following
629 structure:
630 - fuel: left, centre, right
631 - n1: left, right
632 - reverser: left, right."""
633 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_CENTRE, const.FUELTANK_RIGHT]
634
635 def __init__(self, flight):
636 super(F70, self).__init__(flight)
637 self._checkers.append(checks.ThrustChecker())
638 self.dow = 24283
639 self.mtow = 38100 # FIXME: differentiate by registration number,
640 # MTOW of HA-LMF: 41955
641 self.mlw = 36740
642 self.mzfw = 32655
643 self.gearSpeedLimit = 200
644 self.flapSpeedLimits = { 8 : 250,
645 15 : 220,
646 25 : 220,
647 42 : 180 }
648
649 def logFuel(self, aircraftState):
650 """Log the amount of fuel"""
651 self.logger.message(aircraftState.timestamp,
652 "Fuel: left=%.0f kg - centre=%.0f kg - right=%.0f kg" % \
653 (aircraftState.fuel[0], aircraftState.fuel[1],
654 aircraftState.fuel[2]))
655 self.logger.message(aircraftState.timestamp,
656 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
657
658#---------------------------------------------------------------------------------------
659
660class DC3(Aircraft):
661 """Lisunov Li-2 (DC-3) aircraft.
662
663 The aircraft type-specific values in the aircraft state have the following
664 structure:
665 - fuel: left aux, left, right, right aux
666 - rpm: left, right
667 - reverser: left, right."""
668 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
669 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
670
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 def logFuel(self, aircraftState):
691 """Log the amount of fuel"""
692 self.logger.message(aircraftState.timestamp,
693 "Fuel: left aux=%.0f kg - left=%.0f kg - right=%.0f kg - right aux=%.0f kg" % \
694 (aircraftState.fuel[0], aircraftState.fuel[1],
695 aircraftState.fuel[2], aircraftState.fuel[3]))
696 self.logger.message(aircraftState.timestamp,
697 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
698
699#---------------------------------------------------------------------------------------
700
701class T134(Aircraft):
702 """Tupolev Tu-134 aircraft.
703
704 The aircraft type-specific values in the aircraft state have the following
705 structure:
706 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
707 external 2
708 - n1: left, right
709 - reverser: left, right."""
710 fuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
711 const.FUELTANK_LEFT_AUX,
712 const.FUELTANK_CENTRE,
713 const.FUELTANK_RIGHT_AUX,
714 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
715
716 def __init__(self, flight):
717 super(T134, self).__init__(flight)
718 self._checkers.append(checks.ThrustChecker())
719 self.dow = 29500
720 self.mtow = 49000
721 self.mlw = 43000
722 self.mzfw = 38500
723 self.gearSpeedLimit = 216
724 self.flapSpeedLimits = { 10 : 450,
725 20 : 400,
726 30 : 300 }
727
728 @property
729 def speedInKnots(self):
730 """Indicate if the speed is in knots."""
731 return False
732
733 def logFuel(self, aircraftState):
734 """Log the amount of fuel"""
735 self.logger.message(aircraftState.timestamp,
736 "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" % \
737 (aircraftState.fuel[0], aircraftState.fuel[1],
738 aircraftState.fuel[2],
739 aircraftState.fuel[3], aircraftState.fuel[4],
740 aircraftState.fuel[5], aircraftState.fuel[6]))
741 self.logger.message(aircraftState.timestamp,
742 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
743
744 def _appendLightsLoggers(self):
745 """Append the loggers needed for the lights."""
746 self._checkers.append(checks.AnticollisionLightsLogger())
747 self._checkers.append(checks.LandingLightsLogger())
748 self._checkers.append(checks.NavLightsLogger())
749
750 def _appendLightsCheckers(self):
751 """Append the checkers needed for the lights."""
752 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
753 self._checkers.append(checks.LandingLightsChecker())
754 self._checkers.append(checks.NavLightsChecker())
755
756#---------------------------------------------------------------------------------------
757
758class T154(Aircraft):
759 """Tupolev Tu-154 aircraft.
760
761 The aircraft type-specific values in the aircraft state have the following
762 structure:
763 - fuel: left aux, left, centre, centre 2, right, right aux
764 - n1: left, centre, right
765 - reverser: left, right"""
766 fuelTanks = [const.FUELTANK_LEFT_AUX, const.FUELTANK_LEFT,
767 const.FUELTANK_CENTRE, const.FUELTANK_CENTRE2,
768 const.FUELTANK_RIGHT, const.FUELTANK_RIGHT_AUX]
769 def __init__(self, flight):
770 super(T154, self).__init__(flight)
771 self._checkers.append(checks.ThrustChecker())
772 self.dow = 53259
773 self.mtow = 98000
774 self.mlw = 78000
775 self.mzfw = 72000
776 self.gearSpeedLimit = 216
777 self.flapSpeedLimits = { 15 : 227,
778 28 : 194,
779 45 : 162 }
780
781 @property
782 def speedInKnots(self):
783 """Indicate if the speed is in knots."""
784 return False
785
786 def logFuel(self, aircraftState):
787 """Log the amount of fuel"""
788 self.logger.message(aircraftState.timestamp,
789 "Fuel: left aux=%.0f kg - left=%.0f kg - centre=%.0f kg - centre 2=%.0f kg - right=%.0f kg - right aux=%.0f kg" % \
790 (aircraftState.fuel[0], aircraftState.fuel[1],
791 aircraftState.fuel[2], aircraftState.fuel[3],
792 aircraftState.fuel[4], aircraftState.fuel[5]))
793 self.logger.message(aircraftState.timestamp,
794 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
795
796 def _appendLightsLoggers(self):
797 """Append the loggers needed for the lights."""
798 self._checkers.append(checks.AnticollisionLightsLogger())
799 self._checkers.append(checks.LandingLightsLogger())
800 self._checkers.append(checks.NavLightsLogger())
801
802 def _appendLightsCheckers(self):
803 """Append the checkers needed for the lights."""
804 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
805 self._checkers.append(checks.LandingLightsChecker())
806 self._checkers.append(checks.NavLightsChecker())
807
808#---------------------------------------------------------------------------------------
809
810
811class YK40(Aircraft):
812 """Yakovlev Yak-40 aircraft.
813
814 The aircraft type-specific values in the aircraft state have the following
815 structure:
816 - fuel: left, right
817 - n1: left, right
818 - reverser: left, right"""
819 fuelTanks = [const.FUELTANK_LEFT, const.FUELTANK_RIGHT]
820
821 def __init__(self, flight):
822 super(YK40, self).__init__(flight)
823 self._checkers.append(checks.ThrustChecker())
824 self.dow = 9400
825 self.mtow = 17200
826 self.mlw = 16800
827 self.mzfw = 12100
828 self.gearSpeedLimit = 165
829 self.flapSpeedLimits = { 20 : 165,
830 35 : 135 }
831
832 @property
833 def speedInKnots(self):
834 """Indicate if the speed is in knots."""
835 return False
836
837 def logFuel(self, aircraftState):
838 """Log the amount of fuel"""
839 self.logger.message(aircraftState.timestamp,
840 "Fuel: left=%.0f kg - right=%.0f kg" % \
841 (aircraftState.fuel[0], aircraftState.fuel[1]))
842 self.logger.message(aircraftState.timestamp,
843 "Total fuel: %.0f kg" % (sum(aircraftState.fuel),))
844
845 def _appendLightsLoggers(self):
846 """Append the loggers needed for the lights."""
847 self._checkers.append(checks.AnticollisionLightsLogger())
848 self._checkers.append(checks.LandingLightsLogger())
849 self._checkers.append(checks.NavLightsLogger())
850
851 def _appendLightsCheckers(self):
852 """Append the checkers needed for the lights."""
853 self._checkers.append(checks.AntiCollisionLightsChecker())
854 self._checkers.append(checks.LandingLightsChecker())
855 self._checkers.append(checks.NavLightsChecker())
856
857#---------------------------------------------------------------------------------------
858
859MostFuelTankAircraft = T134
860
861#---------------------------------------------------------------------------------------
862
863_classes = { const.AIRCRAFT_B736 : B736,
864 const.AIRCRAFT_B737 : B737,
865 const.AIRCRAFT_B738 : B738,
866 const.AIRCRAFT_B738C : B738Charter,
867 const.AIRCRAFT_B733 : B733,
868 const.AIRCRAFT_B734 : B734,
869 const.AIRCRAFT_B735 : B735,
870 const.AIRCRAFT_DH8D : DH8D,
871 const.AIRCRAFT_B762 : B762,
872 const.AIRCRAFT_B763 : B763,
873 const.AIRCRAFT_CRJ2 : CRJ2,
874 const.AIRCRAFT_F70 : F70,
875 const.AIRCRAFT_DC3 : DC3,
876 const.AIRCRAFT_T134 : T134,
877 const.AIRCRAFT_T154 : T154,
878 const.AIRCRAFT_YK40 : YK40 }
879
880#---------------------------------------------------------------------------------------
881
882if __name__ == "__main__":
883 value = SmoothedValue()
884
885 print "Adding 1, 12.0"
886 value.add(1, 12.0)
887 print value.get()
888
889 print "Adding 1, 15.0"
890 value.add(1, 15.0)
891 print value.get()
892
893 print "Adding 2, 18.0"
894 value.add(2, 18.0)
895 print value.get()
896
897 print "Adding 2, 20.0"
898 value.add(2, 20.0)
899 print value.get()
900
901 print "Adding 5, 22.0"
902 value.add(5, 22.0)
903 print value.get()
904
905 print "Adding 5, 25.0"
906 value.add(5, 25.0)
907 print value.get()
908
909 print "Adding 5, 29.0"
910 value.add(5, 29.0)
911 print value.get()
912
913 print "Adding 5, 21.0"
914 value.add(5, 21.0)
915 print value.get()
916
917 print "Adding 5, 26.0"
918 value.add(5, 26.0)
919 print value.get()
920
921 print "Adding 2, 30.0"
922 value.add(2, 30.0)
923 print value.get()
924
925 print "Adding 2, 55.0"
926 value.add(2, 55.0)
927 print value.get()
928
929#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.