Changeset 197:93f89e9049be


Ignore:
Timestamp:
05/27/12 11:15:19 (13 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Added support for smoothed IAS and VS values

Location:
src/mlx
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • src/mlx/acft.py

    r191 r197  
    1212import traceback
    1313
     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       
    1439#---------------------------------------------------------------------------------------
    1540
     
    3661        self._checkers = []
    3762
     63        config = flight.config
    3864        # Loggers
    3965
     
    5884        self._checkers.append(checks.SpoilerLogger())
    5985
    60         if flight.config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
     86        if config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
    6187            self._checkers.append(checks.VisibilityChecker())
    6288
     
    6692        # queried from it, so the model should have a reference to the GUI as
    6793        # well and access such data via the GUI!
    68         if flight.config.onlineACARS and not flight.entranceExam:
     94        if config.onlineACARS and not flight.entranceExam:
    6995            self._checkers.append(checks.ACARSSender(flight._gui))
    7096
     
    93119        self._checkers.append(checks.SpeedChecker())
    94120        self._checkers.append(checks.VSChecker())
    95         self._checkers.append(checks.OverspeedChecker())
     121
     122        timeout = 5.0 + config.realIASSmoothingLength - 1
     123        self._checkers.append(checks.OverspeedChecker(timeout = timeout))
     124                             
    96125        self._checkers.append(checks.StallChecker())
    97126
     
    99128       
    100129        self._checkers.append(checks.ReverserChecker())
     130
     131        self._smoothedIAS = SmoothedValue()
     132        self._smoothedVS = SmoothedValue()
    101133
    102134    @property
     
    132164
    133165    def handleState(self, aircraftState):
    134         """Called when the state of the aircraft changes."""
     166        """Called when the state of the aircraft changes.
     167
     168        This is the function that the simulator calls directly with the new
     169        state."""
     170        config = self._flight.config
     171
     172        self._smoothedIAS.add(config.realIASSmoothingLength, aircraftState.ias)
     173        aircraftState.smoothedIAS = self._smoothedIAS.get()
     174
     175        print "handleState, realVSSmoothingLength:", config.realVSSmoothingLength
     176        self._smoothedVS.add(config.realVSSmoothingLength, aircraftState.vs)
     177        aircraftState.smoothedVS = self._smoothedVS.get()
     178       
    135179        for checker in self._checkers:
    136180            try:
     
    753797
    754798#---------------------------------------------------------------------------------------
     799
     800if __name__ == "__main__":
     801    value = SmoothedValue()
     802
     803    print "Adding 1, 12.0"
     804    value.add(1, 12.0)
     805    print value.get()
     806
     807    print "Adding 1, 15.0"
     808    value.add(1, 15.0)
     809    print value.get()
     810
     811    print "Adding 2, 18.0"
     812    value.add(2, 18.0)
     813    print value.get()
     814
     815    print "Adding 2, 20.0"
     816    value.add(2, 20.0)
     817    print value.get()
     818
     819    print "Adding 5, 22.0"
     820    value.add(5, 22.0)
     821    print value.get()
     822
     823    print "Adding 5, 25.0"
     824    value.add(5, 25.0)
     825    print value.get()
     826
     827    print "Adding 5, 29.0"
     828    value.add(5, 29.0)
     829    print value.get()
     830
     831    print "Adding 5, 21.0"
     832    value.add(5, 21.0)
     833    print value.get()
     834
     835    print "Adding 5, 26.0"
     836    value.add(5, 26.0)
     837    print value.get()
     838
     839    print "Adding 2, 30.0"
     840    value.add(2, 30.0)
     841    print value.get()
     842
     843    print "Adding 2, 55.0"
     844    value.add(2, 55.0)
     845    print value.get()
     846
     847#---------------------------------------------------------------------------------------
  • src/mlx/checks.py

    r192 r197  
    619619        """Check if the fault condition holds."""
    620620        speedLimit = aircraft.getFlapsSpeedLimit(state.flapsSet)
    621         return speedLimit is not None and state.ias>speedLimit
     621        return speedLimit is not None and state.smoothedIAS>speedLimit
    622622
    623623    def logFault(self, flight, aircraft, logger, oldState, state):
     
    649649    def isCondition(self, flight, aircraft, oldState, state):
    650650        """Check if the fault condition holds."""
    651         return state.gearsDown and state.ias>aircraft.gearSpeedLimit
     651        return state.gearsDown and state.smoothedIAS>aircraft.gearSpeedLimit
    652652
    653653    def logFault(self, flight, aircraft, logger, oldState, state):
     
    803803class OverspeedChecker(PatientFaultChecker):
    804804    """Check if Vne has been exceeded."""
    805     def __init__(self):
     805    def __init__(self, timeout = 5.0):
    806806        """Construct the checker."""
    807         super(OverspeedChecker, self).__init__(timeout = 5.0)
     807        super(OverspeedChecker, self).__init__(timeout = timeout)
    808808
    809809    def isCondition(self, flight, aircraft, oldState, state):
     
    974974    def isCondition(self, flight, aircraft, oldState, state):
    975975        """Check if the fault condition holds."""
    976         vs = state.vs
     976        vs = state.smoothedVS
    977977        altitude = state.altitude
    978978        return vs < -8000 or vs > 8000 or \
     
    988988    def logFault(self, flight, aircraft, logger, oldState, state):
    989989        """Log the fault."""
    990         vs = state.vs
     990        vs = state.smoothedVS
    991991
    992992        message = "Vertical speed was %.0f feet/min" % (vs,)
  • src/mlx/config.py

    r183 r197  
    126126        self._syncFSTime = False
    127127        self._usingFS2Crew = False
     128        self._iasSmoothingLength = -2
     129        self._vsSmoothingLength = -2
    128130
    129131        self._pirepDirectory = None
     
    273275        if usingFS2Crew!=self._usingFS2Crew:
    274276            self._usingFS2Crew = usingFS2Crew
     277            self._modified = True
     278
     279    @property
     280    def iasSmoothingLength(self):
     281        """Get the number of samples over which the IAS is averaged for the
     282        smoothed IAS calculation. It may be negative, in which case smoothing
     283        is disabled, but we nevertheless store the number of seconds in case it
     284        may become useful later."""
     285        return self._iasSmoothingLength
     286
     287    @property
     288    def realIASSmoothingLength(self):
     289        """Get the real smoothing length of IAS."""
     290        return max(self._iasSmoothingLength, 1)
     291
     292    @iasSmoothingLength.setter
     293    def iasSmoothingLength(self, iasSmoothingLength):
     294        """Set the number of samples over which the IAS is averaged for the
     295        smoothed IAS calculation."""
     296        if iasSmoothingLength!=self._iasSmoothingLength:
     297            self._iasSmoothingLength = iasSmoothingLength
     298            self._modified = True
     299
     300    @property
     301    def vsSmoothingLength(self):
     302        """Get the number of samples over which the VS is averaged for the
     303        smoothed VS calculation. It may be negative, in which case smoothing
     304        is disabled, but we nevertheless store the number of seconds in case it
     305        may become useful later."""
     306        return self._vsSmoothingLength
     307
     308    @property
     309    def realVSSmoothingLength(self):
     310        """Get the real smoothing length of VS."""
     311        return max(self._vsSmoothingLength, 1)
     312
     313    @vsSmoothingLength.setter
     314    def vsSmoothingLength(self, vsSmoothingLength):
     315        """Set the number of samples over which the VS is averaged for the
     316        smoothed VS calculation."""
     317        if vsSmoothingLength!=self._vsSmoothingLength:
     318            self._vsSmoothingLength = vsSmoothingLength
    275319            self._modified = True
    276320
     
    455499                                              "usingFS2Crew",
    456500                                              False)
     501        self._iasSmoothingLength = int(self._get(config, "general",
     502                                                 "iasSmoothingLength",
     503                                                 -2))
     504        self._vsSmoothingLength = int(self._get(config, "general",
     505                                                "vsSmoothingLength",
     506                                                -2))
    457507        self._pirepDirectory = self._get(config, "general",
    458508                                         "pirepDirectory", None)
     
    517567        config.set("general", "usingFS2Crew",
    518568                   "yes" if self._usingFS2Crew else "no")
     569        config.set("general", "iasSmoothingLength",
     570                   str(self._iasSmoothingLength))
     571        config.set("general", "vsSmoothingLength",
     572                   str(self._vsSmoothingLength))
    519573
    520574        if self._pirepDirectory is not None:
  • src/mlx/const.py

    r191 r197  
    44
    55# The version of the program
    6 VERSION="0.1"
     6VERSION="0.2"
    77
    88#-------------------------------------------------------------------------------
  • src/mlx/fs.py

    r170 r197  
    173173    - bank: the bank of the aircraft in degrees. Positive means bank left,
    174174    negative means bank right (float)
    175     - ias: the indicated airspeed in knots (float)   
     175    - ias: the indicated airspeed in knots (float)
     176    - smoothedIAS: the smoothed IAS in knots (float)
    176177    - mach: the airspeed in mach (float)   
    177178    - groundSpeed: the ground speed (float)
    178179    - vs: the vertical speed in feet/minutes (float)
     180    - smoothedVS: the smoothed VS in feet/minutes (float)
    179181    - radioAltitude: the radio altitude of the aircraft in feet (float)
    180182    - altitude: the altitude of the aircraft in feet (float)
  • src/mlx/gui/monitor.py

    r89 r197  
    7272        table.attach(self._bank, 9, 10, 1, 2)
    7373
    74         (label, self._vs) = self._createLabeledEntry("VS:", 5)
     74        (label, self._vs) = self._createLabeledEntry("VS:", 13)
    7575        table.attach(label, 10, 11, 1, 2)
    7676        table.attach(self._vs, 11, 12, 1, 2)
    7777
    78         (label, self._ias) = self._createLabeledEntry("IAS:", 4)
     78        (label, self._ias) = self._createLabeledEntry("IAS:", 11)
    7979        table.attach(label, 0, 1, 2, 3)
    8080        table.attach(self._ias, 1, 2, 2, 3)
     
    259259            self._pitch.set_text("%.0f" % (aircraftState.pitch,))
    260260            self._bank.set_text("%.0f" % (aircraftState.bank,))
    261             self._vs.set_text("%.0f" % (aircraftState.vs,))
    262             self._ias.set_text("%.0f" % (aircraftState.ias,))
     261            self._vs.set_text("%.0f (%.0f)" % (aircraftState.vs,
     262                                               aircraftState.smoothedVS))
     263            self._ias.set_text("%.0f (%.0f)" % (aircraftState.ias,
     264                                                aircraftState.smoothedIAS))
    263265            self._mach.set_text("%.2f" % (aircraftState.mach,))
    264266            self._groundSpeed.set_text("%.0f" % (aircraftState.groundSpeed,))
  • src/mlx/gui/prefs.py

    r186 r197  
    229229        self._syncFSTime.set_active(config.syncFSTime)
    230230        self._usingFS2Crew.set_active(config.usingFS2Crew)
     231       
     232        self._setSmoothing(self._iasSmoothingEnabled, self._iasSmoothingLength,
     233                           config.iasSmoothingLength)
     234        self._setSmoothing(self._vsSmoothingEnabled, self._vsSmoothingLength,
     235                           config.vsSmoothingLength)
    231236
    232237        pirepDirectory = config.pirepDirectory
     
    269274        config.syncFSTime = self._syncFSTime.get_active()
    270275        config.usingFS2Crew = self._usingFS2Crew.get_active()
     276        config.iasSmoothingLength = self._getSmoothing(self._iasSmoothingEnabled,
     277                                                       self._iasSmoothingLength)
     278        config.vsSmoothingLength = self._getSmoothing(self._vsSmoothingEnabled,
     279                                                       self._vsSmoothingLength)
    271280        config.pirepDirectory = text2unicode(self._pirepDirectory.get_text())
    272281
     
    366375        self._usingFS2Crew.set_tooltip_text(xstr("prefs_usingFS2Crew_tooltip"))
    367376        simulatorBox.pack_start(self._usingFS2Crew, False, False, 4)
     377       
     378        (iasSmoothingBox, self._iasSmoothingEnabled,
     379         self._iasSmoothingLength) = \
     380           self._createSmoothingBox(xstr("prefs_iasSmoothingEnabled"),
     381                                    xstr("prefs_iasSmoothingEnabledTooltip"))
     382        simulatorBox.pack_start(iasSmoothingBox, False, False, 4)
     383
     384        (vsSmoothingBox, self._vsSmoothingEnabled,
     385         self._vsSmoothingLength) = \
     386           self._createSmoothingBox(xstr("prefs_vsSmoothingEnabled"),
     387                                    xstr("prefs_vsSmoothingEnabledTooltip"))
     388        simulatorBox.pack_start(vsSmoothingBox, False, False, 4)
    368389
    369390        pirepBox = gtk.HBox()
     
    401422
    402423        return vbox
     424
     425    def _createSmoothingBox(self, checkBoxLabel, checkBoxTooltip,
     426                            maxSeconds = 10):
     427        """Create a HBox that contains entry fields for smoothing some value."""
     428        smoothingBox = gtk.HBox()
     429
     430        smoothingEnabled = gtk.CheckButton(checkBoxLabel)
     431        smoothingEnabled.set_use_underline(True)
     432        smoothingEnabled.set_tooltip_text(checkBoxTooltip)
     433
     434        smoothingBox.pack_start(smoothingEnabled, False, False, 0)
     435
     436        smoothingLength = gtk.SpinButton()
     437        smoothingLength.set_numeric(True)
     438        smoothingLength.set_range(2, maxSeconds)
     439        smoothingLength.set_increments(1, 1)
     440        smoothingLength.set_alignment(1.0)
     441        smoothingLength.set_width_chars(2)
     442
     443        smoothingBox.pack_start(smoothingLength, False, False, 0)
     444
     445        smoothingBox.pack_start(gtk.Label(xstr("prefs_smoothing_seconds")),
     446                                False, False, 4)
     447
     448        smoothingEnabled.connect("toggled", self._smoothingToggled,
     449                                 smoothingLength)
     450        smoothingLength.set_sensitive(False)
     451
     452        return (smoothingBox, smoothingEnabled, smoothingLength)
    403453
    404454    def _setLanguage(self, language):
     
    434484            dialog.hide()
    435485            self._warnedRestartNeeded = True
    436        
     486
     487    def _smoothingToggled(self, smoothingEnabled, smoothingLength):
     488        """Called when a smoothing enabled check box is toggled."""
     489        sensitive = smoothingEnabled.get_active()
     490        smoothingLength.set_sensitive(sensitive)
     491        if sensitive:
     492            smoothingLength.grab_focus()
     493
     494    def _setSmoothing(self, smoothingEnabled, smoothingLength, smoothing):
     495        """Set the smoothing controls from the given value.
     496
     497        If the value is less than 2, smoothing is disabled. The smoothing
     498        length is the absolute value of the value."""
     499        smoothingEnabled.set_active(smoothing>=2)
     500        smoothingLength.set_value(abs(smoothing))
     501       
     502    def _getSmoothing(self, smoothingEnabled, smoothingLength):
     503        """Get the smoothing value from the given controls.
     504
     505        The returned value is the value of smoothingLength multiplied by -1, if
     506        smoothing is disabled."""
     507        value = smoothingLength.get_value_as_int()
     508        if not smoothingEnabled.get_active():
     509            value *= -1
     510        return value
     511       
    437512    def _pirepDirectoryButtonClicked(self, button):
    438513        """Called when the PIREP directory button is clicked."""
  • src/mlx/i18n.py

    r195 r197  
    662662                 "If this is checked, the logger will take into account, "
    663663                 "that you are using the FS2Crew addon.")
     664        self.add("prefs_iasSmoothingEnabled",
     665                 "Enable the smoothing of _IAS over ")
     666        self.add("prefs_iasSmoothingEnabledTooltip",
     667                 "If enabled, the IAS value will be averaged over the "
     668                 "given number of seconds, and in some checks "
     669                 "this averaged value will be considered.")
     670        self.add("prefs_vsSmoothingEnabled",
     671                 "Enable the smoothing of _VS over ")
     672        self.add("prefs_vsSmoothingEnabledTooltip",
     673                 "If enabled, the VS value will be averaged over the "
     674                 "given number of seconds, and in some checks "
     675                 "this averaged value will be considered.")
     676        self.add("prefs_smoothing_seconds", "sec.")
    664677        self.add("prefs_pirepDirectory",
    665678                 "_PIREP directory:")
Note: See TracChangeset for help on using the changeset viewer.