source: src/mlx/fs.py@ 209:3172e5cab96e

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

The position of the gear control lever is logged

File size: 9.4 KB
RevLine 
[3]1# Module for generic flight-simulator interfaces
2
[4]3#-------------------------------------------------------------------------------
[3]4
[4]5import const
[133]6from sound import startSound
[3]7
[59]8import fsuipc
[133]9import threading
10import time
[59]11
[4]12#-------------------------------------------------------------------------------
[3]13
[4]14class ConnectionListener(object):
[3]15 """Base class for listeners on connections to the flight simulator."""
16 def connected(self, fsType, descriptor):
17 """Called when a connection has been established to the flight
18 simulator of the given type."""
19 print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
20
[59]21 def connectionFailed(self):
22 """Called when the connection could not be established."""
23 print "fs.ConnectionListener.connectionFailed"
24
[3]25 def disconnected(self):
26 """Called when a connection to the flight simulator has been broken."""
27 print "fs.ConnectionListener.disconnected"
28
[4]29#-------------------------------------------------------------------------------
30
31class SimulatorException(Exception):
32 """Exception thrown by the simulator interface for communication failure."""
33
34#-------------------------------------------------------------------------------
35
[15]36def createSimulator(type, connectionListener):
[4]37 """Create a simulator instance for the given simulator type with the given
38 connection listener.
39
40 The returned object should provide the following members:
41 FIXME: add info
42 """
[15]43 assert type in [const.SIM_MSFS9, const.SIM_MSFSX], \
44 "Only MS Flight Simulator 2004 and X are supported"
[59]45 return fsuipc.Simulator(connectionListener, connectAttempts = 3)
[4]46
47#-------------------------------------------------------------------------------
48
[133]49class MessageThread(threading.Thread):
50 """Thread to handle messages."""
51 def __init__(self, config, simulator):
52 """Initialize the message thread with the given configuration and
53 simulator."""
54 super(MessageThread, self).__init__()
55
56 self._config = config
57 self._simulator = simulator
58
59 self._requestCondition = threading.Condition()
60 self._messages = []
61 self._nextMessageTime = None
62 self._toQuit = False
63
64 self.daemon = True
65
[152]66 def add(self, messageType, text, duration, disconnect):
[133]67 """Add the given message to the requested messages."""
68 with self._requestCondition:
[152]69 self._messages.append((messageType, text, duration,
70 disconnect))
[133]71 self._requestCondition.notify()
72
73 def quit(self):
74 """Quit the thread."""
75 with self._requestCondition:
76 self._toQuit = True
77 self._requestCondition.notifty()
78 self.join()
79
80 def run(self):
81 """Perform the thread's operation."""
82 while True:
[152]83 (messageType, text, duration, disconnect) = (None, None, None, None)
[133]84 with self._requestCondition:
85 now = time.time()
86 while not self._toQuit and \
87 ((self._nextMessageTime is not None and \
88 self._nextMessageTime>now) or \
89 not self._messages):
90 self._requestCondition.wait(1)
91 now = time.time()
92
93 if self._toQuit: return
94 if self._nextMessageTime is None or \
95 self._nextMessageTime<=now:
96 self._nextMessageTime = None
97
98 if self._messages:
[152]99 (messageType, text,
100 duration, disconnect) = self._messages[0]
[133]101 del self._messages[0]
102
103 if text is not None:
[152]104 self._sendMessage(messageType, text, duration, disconnect)
[133]105
[152]106 def _sendMessage(self, messageType, text, duration, disconnect):
[133]107 """Send the message and setup the next message time."""
108 messageLevel = self._config.getMessageTypeLevel(messageType)
109 if messageLevel==const.MESSAGELEVEL_SOUND or \
110 messageLevel==const.MESSAGELEVEL_BOTH:
[170]111 startSound(const.SOUND_NOTIFY
112 if messageType==const.MESSAGETYPE_VISIBILITY
113 else const.SOUND_DING)
[133]114 if (messageLevel==const.MESSAGELEVEL_FS or \
115 messageLevel==const.MESSAGELEVEL_BOTH):
[152]116 if disconnect:
117 self._simulator.disconnect("[MLX] " + text,
118 duration = duration)
119 else:
120 self._simulator.sendMessage("[MLX] " + text,
121 duration = duration)
122 elif disconnecte:
123 self._simulator.disconnect()
[133]124 self._nextMessageTime = time.time() + duration
125
126#-------------------------------------------------------------------------------
127
128_messageThread = None
129
130#-------------------------------------------------------------------------------
131
132def setupMessageSending(config, simulator):
133 """Setup message sending with the given config and simulator."""
134 global _messageThread
135 if _messageThread is not None:
136 _messageThread.quit()
137 _messageThread = MessageThread(config, simulator)
138 _messageThread.start()
139
140#-------------------------------------------------------------------------------
141
[152]142def sendMessage(messageType, text, duration = 3, disconnect = False):
[133]143 """Send the given message of the given type into the simulator and/or play
144 a corresponding sound."""
145 global _messageThread
146 if _messageThread is not None:
[152]147 _messageThread.add(messageType, text, duration, disconnect)
[133]148
149#-------------------------------------------------------------------------------
150
[4]151class AircraftState(object):
152 """Base class for the aircraft state produced by the aircraft model based
153 on readings from the simulator.
154
155 The following data members should be provided at least:
156 - timestamp: the simulator time of the measurement in seconds since the
157 epoch (float)
[89]158 - latitude (in degrees, North is positive)
159 - longitude (in degrees, East is positive)
[4]160 - paused: a boolean indicating if the flight simulator is paused for
161 whatever reason (it could be a pause mode, or a menu, a dialog, or a
162 replay, etc.)
163 - trickMode: a boolean indicating if some "trick" mode (e.g. "SLEW" in
164 MSFS) is activated
165 - overspeed: a boolean indicating if the aircraft is in overspeed
166 - stalled: a boolean indicating if the aircraft is stalled
[89]167 - onTheGround: a boolean indicating if the aircraft is on the ground
[9]168 - zfw: the zero-fuel weight in kilograms (float)
[4]169 - grossWeight: the gross weight in kilograms (float)
170 - heading: the heading of the aircraft in degrees (float)
171 - pitch: the pitch of the aircraft in degrees. Positive means pitch down,
172 negative means pitch up (float)
173 - bank: the bank of the aircraft in degrees. Positive means bank left,
174 negative means bank right (float)
[197]175 - ias: the indicated airspeed in knots (float)
176 - smoothedIAS: the smoothed IAS in knots (float)
[9]177 - mach: the airspeed in mach (float)
[5]178 - groundSpeed: the ground speed (float)
[4]179 - vs: the vertical speed in feet/minutes (float)
[197]180 - smoothedVS: the smoothed VS in feet/minutes (float)
[8]181 - radioAltitude: the radio altitude of the aircraft in feet (float)
[4]182 - altitude: the altitude of the aircraft in feet (float)
[5]183 - gLoad: G-load (float)
[4]184 - flapsSet: the selected degrees of the flaps (float)
185 - flaps: the actual degrees of the flaps (float)
[5]186 - fuelWeight[]: the fuel weights in the different tanks in kgs (array of
187 floats of as many items as the number fuel tanks)
[4]188 - n1[]: the N1 values of the turbine engines (array of floats
189 of as many items as the number of engines, present only for aircraft with
190 turbines)
191 - rpm[]: the RPM values of the piston engines (array of floats
192 of as many items as the number of engines, present only for aircraft with
193 pistons)
194 - reverser[]: an array of booleans indicating if the thrust reversers are
195 activated on any of the engines. The number of items equals to the number
[11]196 of engines with a reverser.
[4]197 - navLightsOn: a boolean indicating if the navigation lights are on
198 - antiCollisionLightsOn: a boolean indicating if the anti-collision lights are on
199 - strobeLightsOn: a boolean indicating if the strobe lights are on
[15]200 - landingLightsOn: a boolean indicating if the landing lights are on
[4]201 - pitotHeatOn: a boolean indicating if the pitot heat is on
[8]202 - parking: a boolean indicating if the parking brake is set
[209]203 - gearControlDown: a boolean indicating if the gear control is set to down
[4]204 - gearsDown: a boolean indicating if the gears are down
205 - spoilersArmed: a boolean indicating if the spoilers have been armed for
206 automatic deployment
207 - spoilersExtension: the percentage of how much the spoiler is extended
208 (float)
[5]209 - altimeter: the altimeter setting in hPa (float)
210 - nav1: the frequency of the NAV1 radio in MHz (string)
211 - nav2: the frequency of the NAV1 radio in MHz (string)
[15]212 - squawk: the transponder code (string)
[9]213 - windSpeed: the speed of the wind at the aircraft in knots (float)
214 - windDirection: the direction of the wind at the aircraft in degrees (float)
[134]215 - visibility: the visibility in metres (float)
[4]216
217 FIXME: needed when taxiing only:
[5]218 - payload weight
[4]219
[5]220 FIXME: needed rarely:
221 - latitude, longitude
222 - transporter
223 - visibility
[4]224 """
225
Note: See TracBrowser for help on using the repository browser.