source: src/mlx/fs.py@ 263:7ee78a903649

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

RPM is handled properly and the fuel tanks of Li-2 match the simulator

File size: 9.5 KB
Line 
1# Module for generic flight-simulator interfaces
2
3#-------------------------------------------------------------------------------
4
5import const
6from sound import startSound
7
8import fsuipc
9import threading
10import time
11
12#-------------------------------------------------------------------------------
13
14class ConnectionListener(object):
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
21 def connectionFailed(self):
22 """Called when the connection could not be established."""
23 print "fs.ConnectionListener.connectionFailed"
24
25 def disconnected(self):
26 """Called when a connection to the flight simulator has been broken."""
27 print "fs.ConnectionListener.disconnected"
28
29#-------------------------------------------------------------------------------
30
31class SimulatorException(Exception):
32 """Exception thrown by the simulator interface for communication failure."""
33
34#-------------------------------------------------------------------------------
35
36def createSimulator(type, connectionListener):
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 """
43 assert type in [const.SIM_MSFS9, const.SIM_MSFSX], \
44 "Only MS Flight Simulator 2004 and X are supported"
45 return fsuipc.Simulator(connectionListener, connectAttempts = 3)
46
47#-------------------------------------------------------------------------------
48
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
66 def add(self, messageType, text, duration, disconnect):
67 """Add the given message to the requested messages."""
68 with self._requestCondition:
69 self._messages.append((messageType, text, duration,
70 disconnect))
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:
83 (messageType, text, duration, disconnect) = (None, None, None, None)
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:
99 (messageType, text,
100 duration, disconnect) = self._messages[0]
101 del self._messages[0]
102
103 if text is not None:
104 self._sendMessage(messageType, text, duration, disconnect)
105
106 def _sendMessage(self, messageType, text, duration, disconnect):
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:
111 startSound(const.SOUND_NOTIFY
112 if messageType==const.MESSAGETYPE_VISIBILITY
113 else const.SOUND_DING)
114 if (messageLevel==const.MESSAGELEVEL_FS or \
115 messageLevel==const.MESSAGELEVEL_BOTH):
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()
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
142def sendMessage(messageType, text, duration = 3, disconnect = False):
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:
147 _messageThread.add(messageType, text, duration, disconnect)
148
149#-------------------------------------------------------------------------------
150
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)
158 - latitude (in degrees, North is positive)
159 - longitude (in degrees, East is positive)
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
167 - onTheGround: a boolean indicating if the aircraft is on the ground
168 - zfw: the zero-fuel weight in kilograms (float)
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)
175 - ias: the indicated airspeed in knots (float)
176 - smoothedIAS: the smoothed IAS in knots (float)
177 - mach: the airspeed in mach (float)
178 - groundSpeed: the ground speed (float)
179 - vs: the vertical speed in feet/minutes (float)
180 - smoothedVS: the smoothed VS in feet/minutes (float)
181 - radioAltitude: the radio altitude of the aircraft in feet (float)
182 - altitude: the altitude of the aircraft in feet (float)
183 - gLoad: G-load (float)
184 - flapsSet: the selected degrees of the flaps (float)
185 - flaps: the actual degrees of the flaps (float)
186 - fuelWeight[]: the fuel weights in the different tanks in kgs (array of
187 floats of as many items as the number fuel tanks)
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, for other aircraft it is None)
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, for other aircraft it is None)
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
196 of engines with a reverser.
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
200 - landingLightsOn: a boolean indicating if the landing lights are on
201 - pitotHeatOn: a boolean indicating if the pitot heat is on
202 - parking: a boolean indicating if the parking brake is set
203 - gearControlDown: a boolean indicating if the gear control is set to down
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)
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)
212 - squawk: the transponder code (string)
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)
215 - visibility: the visibility in metres (float)
216 - cog: the centre of gravity
217
218 FIXME: needed when taxiing only:
219 - payload weight
220
221 FIXME: needed rarely:
222 - latitude, longitude
223 - transporter
224 - visibility
225 """
226
Note: See TracBrowser for help on using the repository browser.