Skip to content

Instantly share code, notes, and snippets.

@timtrueman
Created November 8, 2009 00:49
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save timtrueman/228998 to your computer and use it in GitHub Desktop.
This is just meant as an example to get you started. You will need to install Twisted ("sudo easy_install twisted").
#!/usr/bin/env python
# encoding: utf-8
import socket
from struct import *
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
import math
UDP_IP="127.0.0.1"
UDP_PORT=49045 # I'm not sure if there's a default so you'll have to set it like this: http://dronedynamics.com/xplane_config.png
UDP_SENDTO_PORT=49000 # This is the port X-Plane is listening on for commands (such as the data select packet we send to tell it what data to send us).
class XplaneConnector(DatagramProtocol):
def __init__(self):
"""
This will send a packet to X-Plane to select the data you need to read.
Once it's sent X-Plane will output data automatically at a default of 20Hz.
In this string, "\x03\x00\x00\x00", we are selecting the third checkbox in the
"Settings" > "Data Input and Output" menu item ("speeds" in this example). And
don't forget that these numbers are in hexadecimal!
"""
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((UDP_IP,49999)) # this is the port we're sending from and it doesn't really matter
data_selection_packet = "DSEL0" # this is the xplane packet type
data_selection_packet += "\x03\x00\x00\x00" # airspeed
data_selection_packet += "\x04\x00\x00\x00" # accelerometers
data_selection_packet += "\x06\x00\x00\x00" # temperature
data_selection_packet += "\x11\x00\x00\x00" # gyros
data_selection_packet += "\x12\x00\x00\x00" # pitch and roll (for sanity check)
data_selection_packet += "\x14\x00\x00\x00" # altimeter and GPS
self.sock.sendto(data_selection_packet,(UDP_IP,UDP_SENDTO_PORT))
def datagramReceived(self, data, (host, port)):
"""
We've received a UDP packet from X-Plane (which is in binary so printing it
won't help). This is where we unpack and then do whatever with the data.
"""
self.unpack(data)
self.display()
# self.log() # uncomment this line if you want to log to a file
def unpack(self, data):
"""
When we receive a UDP packet from X-Plane we'll need to unpack the data.
See http://www.grc.nasa.gov/WWW/K-12/airplane/rotations.html for which body
axes are which (please don't invent your own). X-Plane gives some of the data
in a funny order (q before p and r?!).
"""
self.Vair = unpack_from('<f', data, 9)[0]
self.Vtgs = unpack_from('<f', data, 9+12)[0]
self.az = unpack_from('<f', data, 9+16+36)[0]
self.ax = unpack_from('<f', data, 9+20+36)[0]
self.ay = unpack_from('<f', data, 9+24+36)[0]
self.temperature = unpack_from('<f', data, 9+72+0)[0]
self.q = math.radians(unpack_from('<f', data, 9+108+0)[0])
self.p = math.radians(unpack_from('<f', data, 9+108+4)[0])
self.r = math.radians(unpack_from('<f', data, 9+108+8)[0])
self.pitch = math.radians(unpack_from('<f', data, 9+144+0)[0])
self.roll = math.radians(unpack_from('<f', data, 9+144+4)[0])
self.altitude = unpack_from('<f', data, 9+180+20)[0]
self.latitude = unpack_from('<f', data, 9+180+0)[0]
self.longitude = unpack_from('<f', data, 9+180+4)[0]
def display(self):
"""
Use the curses library if you want to format and update the data nicely on the
screen (similar to the "top" command in *nix)
"""
print "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f" % (self.Vair, self.ax, self.ay, self.az, self.p, self.q, self.r, self.altitude, self.latitude, self.longitude)
def log(self):
"""
Yeah I'll get to file logging later but for now you can do it yourself (delete the "pass" line).
"""
pass
if __name__ == "__main__":
"""
If you call this file directly (from the command line using "python xplane.py") then
it will sleep until a packet is received and then call datagramReceived when one arrives.
"""
print "Listening to X-Plane..."
xplane_connector = XplaneConnector()
reactor.listenUDP(UDP_PORT, xplane_connector)
reactor.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment