Changeset 5:90eade9afbcb


Ignore:
Timestamp:
01/31/12 18:01:43 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Added some further data to those queried and reworked a bit the way the model changes are handled

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/acft.py

    r4 r5  
    4949
    5050        if self._aircraftState is None or \
     51           self._aircraftState.onTheGround != aircraftState.onTheGround:
     52            print "Aircraft.handleState: %s: onTheGround=%d" % \
     53                (timeStr, aircraftState.onTheGround)
     54
     55        if self._aircraftState is None or \
    5156           self._aircraftState.grossWeight != aircraftState.grossWeight:
    5257            print "Aircraft.handleState: %s: grossWeight=%f" % \
     
    7479
    7580        if self._aircraftState is None or \
     81           self._aircraftState.groundSpeed != aircraftState.groundSpeed:
     82            print "Aircraft.handleState: %s: groundSpeed=%f" % \
     83                (timeStr, aircraftState.groundSpeed)
     84
     85        if self._aircraftState is None or \
    7686           self._aircraftState.vs != aircraftState.vs:
    7787            print "Aircraft.handleState: %s: vs=%f" % \
     
    8292            print "Aircraft.handleState: %s: altitude=%f" % \
    8393                (timeStr, aircraftState.altitude)
     94
     95        if self._aircraftState is None or \
     96           self._aircraftState.gLoad != aircraftState.gLoad:
     97            print "Aircraft.handleState: %s: gLoad=%f" % \
     98                (timeStr, aircraftState.gLoad)
    8499
    85100        if self._aircraftState is None or \
     
    133148                (timeStr, aircraftState.spoilersExtension)
    134149
     150        if self._aircraftState is None or \
     151           self._aircraftState.altimeter != aircraftState.altimeter:
     152            print "Aircraft.handleState: %s: altimeter=%f" % \
     153                (timeStr, aircraftState.altimeter)
     154
     155        if self._aircraftState is None or \
     156           self._aircraftState.nav1 != aircraftState.nav1:
     157            print "Aircraft.handleState: %s: nav1=%s" % \
     158                (timeStr, aircraftState.nav1)
     159
     160        if self._aircraftState is None or \
     161           self._aircraftState.nav2 != aircraftState.nav2:
     162            print "Aircraft.handleState: %s: nav2=%s" % \
     163                (timeStr, aircraftState.nav2)
     164
    135165        self._aircraftState = aircraftState
    136166           
  • src/fs.py

    r4 r5  
    2525#-------------------------------------------------------------------------------
    2626
    27 def createSimulator(type, connectionListener):
     27def createSimulator(type, connectionListener, aircraft):
    2828    """Create a simulator instance for the given simulator type with the given
    2929    connection listener.
     
    3434    assert type==const.TYPE_MSFS9, "Only MS Flight Simulator 2004 is supported"
    3535    import fsuipc
    36     return fsuipc.Simulator(connectionListener)
     36    return fsuipc.Simulator(connectionListener, aircraft)
    3737
    3838#-------------------------------------------------------------------------------
     
    6060    negative means bank right (float)
    6161    - ias: the indicated airspeed in knots (float)   
     62    - groundSpeed: the ground speed (float)
    6263    - vs: the vertical speed in feet/minutes (float)
    6364    - altitude: the altitude of the aircraft in feet (float)
     65    - gLoad: G-load (float)
    6466    - flapsSet: the selected degrees of the flaps (float)
    6567    - flaps: the actual degrees of the flaps (float)
     68    - fuelWeight[]: the fuel weights in the different tanks in kgs (array of
     69    floats of as many items as the number fuel tanks)
    6670    - n1[]: the N1 values of the turbine engines (array of floats
    6771    of as many items as the number of engines, present only for aircraft with
     
    8387    - spoilersExtension: the percentage of how much the spoiler is extended
    8488    (float)
     89    - altimeter: the altimeter setting in hPa (float)
     90    - nav1: the frequency of the NAV1 radio in MHz (string)
     91    - nav2: the frequency of the NAV1 radio in MHz (string)
    8592
    8693    FIXME: needed when taxiing only:
    8794    - zfw: the Zero Fuel Weight in klograms (float)
     95    - payload weight
    8896
    8997    FIXME: needed for touchdown only:
     
    9199    - ambientWindSpeed: the ambient wind speed around the aircraft in knowns (float)
    92100    - tdRate: the touchdown rate calculated by FSUIPC (float)
     101
     102    FIXME: needed rarely:
     103    - latitude, longitude
     104    - transporter
     105    - visibility
    93106    """
    94107   
  • src/fsuipc.py

    r4 r5  
    340340    """The simulator class representing the interface to the flight simulator
    341341    via FSUIPC."""
    342     def __init__(self, connectionListener):
    343         """Construct the simulator."""
    344         self._handler = Handler(connectionListener)
    345         self._handler.start()
    346         self._aircraft = None
    347         self._aircraftName = None
    348         self._aircraftModel = None
    349         self._monitoringRequestID = None
    350 
    351     def connect(self):
    352         """Initiate a connection to the simulator."""
    353         self._handler.connect()
    354 
    355     def startMonitoring(self, aircraft):
    356         """Start the periodic monitoring of the aircraft and pass the resulting
    357         state to the given aircraft object periodically.
     342    # The basic data that should be queried all the time once we are connected
     343    normalData = [ (0x3d00, -256) ]
     344
     345    def __init__(self, connectionListener, aircraft):
     346        """Construct the simulator.
    358347       
    359348        The aircraft object passed must provide the following members:
     
    362351        the aircraft has changed.
    363352        - handleState(aircraftState): handle the given state."""
    364         assert self._aircraft is None
    365 
    366353        self._aircraft = aircraft
    367         self._startMonitoring()
     354
     355        self._handler = Handler(connectionListener)
     356        self._handler.start()
     357
     358        self._normalRequestID = None
     359
     360        self._monitoringRequested = False
     361        self._monitoring = False
     362
     363        self._aircraftName = None
     364        self._aircraftModel = None
     365
     366    def connect(self):
     367        """Initiate a connection to the simulator."""
     368        self._handler.connect()
     369        self._startDefaultNormal()
     370                                                           
     371    def startMonitoring(self):
     372        """Start the periodic monitoring of the aircraft and pass the resulting
     373        state to the aircraft object periodically."""
     374        assert not self._monitoringRequested         
     375        self._monitoringRequested = True
    368376
    369377    def stopMonitoring(self):
    370378        """Stop the periodic monitoring of the aircraft."""
    371         self._aircraft = None
     379        assert self._monitoringRequested
     380        self._monitoringRequested = False
    372381
    373382    def disconnect(self):
    374383        """Disconnect from the simulator."""
     384        assert not self._monitoringRequested
     385       
     386        self._stopNormal()
    375387        self._handler.disconnect()
    376388
    377     def _startMonitoring(self):
    378         """The internal call to start monitoring."""
    379         self._handler.requestRead([(0x3d00, -256)], self._monitoringStartCallback)
    380 
    381     def _monitoringStartCallback(self, data, extra):
    382         """Callback for the data read when the monitoring has started.
    383        
    384         The following data items are expected:
    385         - the name of the aircraft
     389    def _startDefaultNormal(self):
     390        """Start the default normal periodic request."""
     391        assert self._normalRequestID is None
     392        self._normalRequestID = self._handler.requestPeriodicRead(1.0,
     393                                                                  Simulator.normalData,
     394                                                                  self._handleNormal)
     395
     396    def _stopNormal(self):
     397        """Stop the normal period request."""
     398        assert self._normalRequestID is not None
     399        self._handler.clearPeriodic(self._normalRequestID)
     400        self._normalRequestID = None
     401
     402    def _handleNormal(self, data, extra):
     403        """Handle the reply to the normal request.
     404
     405        At the beginning the result consists the data for normalData. When
     406        monitoring is started, it contains the result also for the
     407        aircraft-specific values.
    386408        """
    387         if self._aircraft is None:
    388             return
    389         elif data is None:
     409        self._setAircraftName(data[0])
     410        if self._monitoringRequested and not self._monitoring:
     411            self._monitoring = True
     412            self._stopNormal()
    390413            self._startMonitoring()
    391         else:
    392             self._setAircraftName(data[0])           
     414        elif self._monitoring and not self._monitoringRequested:
     415            self._monitoring = False
     416            self._stopNormal()
     417            self._startDefaultNormal()
     418        elif self._monitoring and self._aircraftModel is not None:
     419            aircraftState = self._aircraftModel.getAircraftState(self._aircraft, data)
     420            self._aircraft.handleState(aircraftState)
    393421
    394422    def _setAircraftName(self, name):
     
    415443        self._aircraftModel = model
    416444       
    417         if self._monitoringRequestID is not None:
    418             self._handler.clearPeriodic(self._monitoringRequestID)
    419            
    420         self._monitoringRequestID = \
    421             self._handler.requestPeriodicRead(1.0,
    422                                               model.getMonitoringData(),
    423                                               self._handleMonitoringData)
    424 
    425     def _handleMonitoringData(self, data, extra):
    426         """Handle the monitoring data."""
    427         if self._aircraft is None:
    428             self._handler.clearPeriodic(self._monitoringRequestID)
    429             return
    430 
    431         self._setAircraftName(data[0])
    432         aircraftState = self._aircraftModel.getAircraftState(self._aircraft, data)
    433         self._aircraft.handleState(aircraftState)
     445        if self._monitoring:
     446            self._handler.clearPeriodic(self._normalRequestID)           
     447            self._startMonitoring()
     448           
     449    def _startMonitoring(self):
     450        """Start monitoring with the current aircraft model."""
     451        assert self._monitoring
     452
     453        data = Simulator.normalData[:]
     454        self._aircraftModel.addMonitoringData(data)
     455       
     456        self._normalRequestID = \
     457            self._handler.requestPeriodicRead(1.0, data,
     458                                              self._handleNormal)
    434459
    435460#------------------------------------------------------------------------------
     
    440465    Aircraft models handle the data arriving from FSUIPC and turn it into an
    441466    object describing the aircraft's state."""
    442     monitoringData = [("aircraftName", 0x3d00, -256),
    443                       ("year", 0x0240, "H"),
     467    monitoringData = [("year", 0x0240, "H"),
    444468                      ("dayOfYear", 0x023e, "H"),
    445469                      ("zuluHour", 0x023b, "b"),
     
    448472                      ("paused", 0x0264, "H"),
    449473                      ("frozen", 0x3364, "H"),
     474                      ("replay", 0x0628, "d"),
    450475                      ("slew", 0x05dc, "H"),
    451476                      ("overspeed", 0x036d, "b"),
     
    457482                      ("bank", 0x057c, "d"),
    458483                      ("ias", 0x02bc, "d"),
     484                      ("groundSpeed", 0x02b4, "d"),
    459485                      ("vs", 0x02c8, "d"),
    460486                      ("altitude", 0x0570, "l"),
     487                      ("gLoad", 0x11ba, "H"),
    461488                      ("flapsControl", 0x0bdc, "d"),
    462489                      ("flapsLeft", 0x0be0, "d"),
     
    466493                      ("noseGear", 0x0bec, "d"),
    467494                      ("spoilersArmed", 0x0bcc, "d"),
    468                       ("spoilers", 0x0bd0, "d")]
     495                      ("spoilers", 0x0bd0, "d"),
     496                      ("altimeter", 0x0330, "H"),
     497                      ("nav1", 0x0350, "H"),
     498                      ("nav2", 0x0352, "H")]
    469499
    470500    @staticmethod
     
    473503        aircraft about it."""       
    474504        return AircraftModel([0, 10, 20, 30])
     505
     506    @staticmethod
     507    def convertFrequency(data):
     508        """Convert the given frequency data to a string."""
     509        frequency = ""
     510        for i in range(0, 4):
     511            digit = chr(ord('0') + (data&0x0f))
     512            data >>= 4
     513            frequency = digit + frequency
     514            if i==1:
     515                frequency = "." + frequency
     516        return "1" + frequency           
    475517
    476518    def __init__(self, flapsNotches):
     
    508550            index += 1
    509551           
    510     def getMonitoringData(self):
     552    def addMonitoringData(self, data):
    511553        """Get the data specification for monitoring.
    512554       
    513         The first item should always be the aircraft name (0x3d00, -256)."""
    514         data = []
     555        Add the model-specific monitoring data to the given array."""
    515556        self.addDataWithIndexMembers(data, "_monidx_",
    516557                                     AircraftModel.monitoringData)
    517         return data
    518558   
    519559    def getAircraftState(self, aircraft, data):
     
    530570       
    531571        state.paused = data[self._monidx_paused]!=0 or \
    532             data[self._monidx_frozen]!=0
     572            data[self._monidx_frozen]!=0 or \
     573            data[self._monidx_replay]!=0
    533574        state.trickMode = data[self._monidx_slew]!=0
    534575
     
    546587
    547588        state.ias = data[self._monidx_ias]/128.0
     589        state.groundSpeed = data[self._monidx_groundSpeed]* 3600.0/65536.0/1852.0
    548590        state.vs = data[self._monidx_vs]*60.0*3.28984/256.0
    549591
    550592        state.altitude = data[self._monidx_altitude]*3.28084/65536.0/65536.0
     593
     594        state.gLoad = data[self._monidx_gLoad] / 625.0
    551595       
    552596        numNotchesM1 = len(self._flapsNotches) - 1
     
    572616        lights = data[self._monidx_lights]
    573617       
    574         state.navLightsOn = (lights%0x01) != 0
    575         state.antiCollisionLightsOn = (lights%0x02) != 0
    576         state.landingLightsOn = (lights%0x04) != 0
    577         state.strobeLightsOn = (lights%0x10) != 0
     618        state.navLightsOn = (lights&0x01) != 0
     619        state.antiCollisionLightsOn = (lights&0x02) != 0
     620        state.landingLightsOn = (lights&0x04) != 0
     621        state.strobeLightsOn = (lights&0x10) != 0
    578622       
    579623        state.pitotHeatOn = data[self._monidx_pitot]!=0
     
    588632        else:
    589633            state.spoilersExtension = (spoilers - 4800) * 100.0 / (16383 - 4800)
     634
     635        state.altimeter = data[self._monidx_altimeter] / 16.0
     636           
     637        state.nav1 = AircraftModel.convertFrequency(data[self._monidx_nav1])
     638        state.nav2 = AircraftModel.convertFrequency(data[self._monidx_nav2])
    590639       
    591640        return state
     641
     642#------------------------------------------------------------------------------
     643
  • src/test.py

    r4 r5  
    99    print data
    1010
    11 class ConnectionListener(fs.ConnectionListener):
    12     def __init__(self):
    13         self._simulator = None
    14         self._monitoring = False
     11def main():
     12    simulator = fs.createSimulator(const.TYPE_MSFS9, fs.ConnectionListener(),
     13                                   acft.Aircraft(const.AIRCRAFT_B737))
     14    simulator.connect()
    1515
    16     def connected(self, fsType, descriptor):
    17         print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
    18         if not self._monitoring:
    19             self._simulator.startMonitoring(acft.Aircraft(const.AIRCRAFT_B737))
    20 
    21 def main():
    22     connectionListener = ConnectionListener()
    23     simulator = fs.createSimulator(const.TYPE_MSFS9, connectionListener)
    24     connectionListener._simulator = simulator
    25     simulator.connect()
     16    time.sleep(10)
     17    simulator.startMonitoring()
    2618
    2719    while True:
    2820        time.sleep(1000)
     21    simulator.stopMonitoring()
     22    simulator.disconnect()
     23
     24    time.sleep(5)
    2925
    3026if __name__ == "__main__":
Note: See TracChangeset for help on using the changeset viewer.