summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gps.py313
-rw-r--r--gps_serial.py~80
-rw-r--r--gpspoller.py88
-rw-r--r--gpspoller.pycbin0 -> 2696 bytes
-rw-r--r--gpstest.py14
-rw-r--r--indexmapV1.gifbin0 -> 3235 bytes
-rw-r--r--latLng.pycbin0 -> 1095 bytes
-rw-r--r--layers.py29
-rw-r--r--layers.pycbin0 -> 3862 bytes
-rw-r--r--testreceive.pd18
-rwxr-xr-xtomorrowtheground.py35
-rw-r--r--tomorrowthegroundGUI/data/indexmapV1.gifbin0 -> 3233 bytes
-rw-r--r--tomorrowthegroundGUI/tomorrowthegroundGUI.pde24
-rw-r--r--ttg01.xml8
-rw-r--r--xml2obj.pycbin0 -> 3905 bytes
15 files changed, 589 insertions, 20 deletions
diff --git a/gps.py b/gps.py
new file mode 100644
index 0000000..336615c
--- /dev/null
+++ b/gps.py
@@ -0,0 +1,313 @@
+# ******!*********!*********!*********!*********!*********!*********!*********
+#
+# Copyright (c) IBM Corporation, 2006. All Rights Reserved.
+# Author: Simon Johnston (skjohn@us.ibm.com)
+#
+# Simple class which can interface to a serially connected GPS device that
+# implements the NMEA standard. The reference I used was found at:
+# http://www.gpsinformation.org/dale/nmea.htm
+# The class currently decodes the following sentences:
+# GLL, GSA, GSV, RMC
+#
+# Classes:
+# GPSError - exception for GPSDevice (also wraps serial errors).
+# GPSDevice - GPS device interface (serial) class.
+#
+# Functions:
+# format_date - convert date from NMEA to ISO format.
+# format_time - convert time from NMEA to ISO format.
+# format_latlong - convert date from NMEA to standard decimal format.
+#
+# ******!*********!*********!*********!*********!*********!*********!*********
+
+import datetime
+
+import serial
+
+class GPSError(Exception):
+ """ Signal errors in the GPS communication, both NMEA sentence errors
+ as well as wrapping up underlying serial I/O errors.
+ """
+ pass
+
+class GPSDevice(object):
+ """ General GPS Device interface for connecting to serial port GPS devices
+ using the default communication params specified by the National Marine
+ Electronics Association (NMEA) specifications.
+ """
+ def __init__(self, commport):
+ """ GPSDevice(port)
+ Connects to the serial port specified, as the port numbers are
+ zero-based on windows the actual device string would be "COM" +
+ port+1.
+ """
+ self.commport = commport
+ self.port = None
+
+ def open(self):
+ """ open()
+ open the GPS device port, the NMEA default serial I/O parameters are
+ defined as 4800,8,N,1.
+ """
+ nmea_params = {
+ 'port': self.commport,
+ 'baudrate': 4800,
+ 'bytesize': serial.EIGHTBITS,
+ 'parity': serial.PARITY_NONE,
+ 'stopbits': serial.STOPBITS_ONE
+ }
+ if self.port:
+ raise GPSError, 'Device port is already open'
+ try:
+ self.port = serial.Serial(**nmea_params)
+ self.port.open()
+ except serial.SerialException:
+ raise GPSError, 'Caught serial error opening port, is device connected?'
+
+ def read(self):
+ """ read() -> dict
+ rRad a single NMEA sentence from the device returning the data as a
+ dictionary. The 'sentence' key will identify the sentence type itself
+ with other parameters extracted and nicely formatted where possible.
+ """
+ sentence = 'error'
+ line = self._read_raw()
+ if line:
+ parsed = self._validate(line)
+ if parsed:
+ if _decode_func.has_key(parsed[0]):
+ return _decode_func[parsed[0]](parsed)
+ else:
+ sentence = parsed[0]
+ return {
+ 'sentence': sentence
+ }
+
+ def read_all(self):
+ """ read_all() -> dict
+ A generator allowing the user to read data from the device in a for loop
+ rather than having to craft their own looping method.
+ """
+ while 1:
+ try:
+ record = self.read()
+ except IOError:
+ raise StopIteration
+ yield record
+
+ def close(self):
+ """ close()
+ Close the port, note you can no longer read from the device until you
+ re-open it.
+ """
+ if not self.port:
+ raise GPSError, 'Device port not open, cannot close'
+ self.port.close()
+ self.port = None
+
+ def _read_raw(self):
+ """ _read_raw() -> str
+ Internal method which reads a line from the device (line ends in \r\n).
+ """
+ if not self.port:
+ raise GPSError, 'Device port not open, cannot read'
+ return self.port.readline()
+
+ def _checksum(self, data):
+ """ _checksum(data) -> str
+ Internal method which calculates the XOR checksum over the sentence (as
+ a string, not including the leading '$' or the final 3 characters, the
+ ',' and checksum itself).
+ """
+ checksum = 0
+ for character in data:
+ checksum = checksum ^ ord(character)
+ hex_checksum = "%02x" % checksum
+ return hex_checksum.upper()
+
+ def _validate(self, sentence):
+ """ _validate(sentence) -> str
+ Internal method.
+ """
+ sentence.strip()
+ if sentence.endswith('\r\n'):
+ sentence = sentence[:len(sentence)-2]
+ if not sentence.startswith('$GP'):
+ #
+ # Note that sentences that start with '$P' are proprietary
+ # formats and are described as $P<MID><SID> where MID is the
+ # manufacturer identified (Magellan is MGN etc.) and then the
+ # SID is the manufacturers sentence identifier.
+ #
+ return None
+ star = sentence.rfind('*')
+ if star >= 0:
+ check = sentence[star+1:]
+ sentence = sentence[1:star]
+ sum = self._checksum(sentence)
+ if sum <> check:
+ return None
+ sentence = sentence[2:]
+ return sentence.split(',')
+
+#
+# The internal decoder functions start here.
+#
+def format_date(datestr):
+ """ format_date(datestr) -> str
+ Internal function. Turn GPS DDMMYY into DD/MM/YY
+ """
+ year = int(datestr[4:])
+ now = datetime.date.today()
+ if year + 2000 > now.year:
+ year = year + 1900
+ else:
+ year = yeat + 2000
+ the_date = datetime.date(year, int(datestr[2:4]), int(datestr[:2]))
+ return the_date.isoformat()
+
+def format_time(timestr):
+ """ format_time(timestr) -> str
+ Internal function. Turn GPS HHMMSS into HH:MM:SS UTC
+ """
+ utc_str = '+00:00'
+ the_time = datetime.time(int(timestr[:2]), int(timestr[2:4]), int(timestr[4:]))
+ return the_time.strftime('%H:%M:%S') + utc_str
+
+def format_latlong(data, direction):
+ """ format_latlong(data, direction) -> str
+ Internal function. Turn GPS HHMM.nnnn into standard HH.ddddd
+ """
+ # Check to see if it's HMM.nnnn or HHMM.nnnn or HHHMM.nnnn
+ dot = data.find('.')
+ if (dot > 5) or (dot < 3):
+ raise ValueError, 'Incorrect formatting of "%s"' % data
+ hours = data[0:dot-2]
+ mins = float(data[dot-2:])
+ if hours[0] == '0':
+ hours = hours[1:]
+ if direction in ['S', 'W']:
+ hours = '-' + hours
+ decimal = mins / 60.0 * 100.0
+ decimal = decimal * 10000.0
+ return '%s.%06d' % (hours, decimal)
+
+def _convert(v, f, d):
+ """ convert(v, f, d) -> value
+ Internal function.
+ """
+ try:
+ return f(v)
+ except:
+ return d
+
+def _decode_gll(data):
+ """ decode_gll(date) -> dict
+ Internal function.
+ """
+ return {
+ 'sentence': data[0],
+ 'latitude': '%s' % format_latlong(data[1], data[2]),
+ 'longitude': '%s' % format_latlong(data[3], data[4]),
+ 'time': format_time(data[5]),
+ 'active': data[6]
+ }
+
+def _decode_gga(data):
+ """ decode_gga(date) -> dict
+ Internal function.
+ """
+ quality = ['invalid', 'GPS', 'DGPS', 'PPS', 'Real TIme', 'Float RTK',
+ 'Estimated', 'Manual', 'Simulation']
+ qindex = _convert(data[6], int, '')
+ if qindex >= len(quality):
+ qstring = str(qindex)
+ else:
+ qstring = quality[qindex]
+ return {
+ 'sentence': data[0],
+ 'time': format_time(data[1]),
+ 'latitude': '%s' % format_latlong(data[2], data[3]),
+ 'longitude': '%s' % format_latlong(data[4], data[5]),
+ 'quality': qstring,
+ 'tracked': _convert(data[7], int, ''),
+ 'dilution': _convert(data[8], float, ''),
+ 'altitude': '%s,%s' % (data[9], data[10]),
+ 'geoid_height': '%s,%s' % (data[11], data[12])
+ }
+
+def _decode_gsa(data):
+ """ decode_gsa(date) -> dict
+ Internal function.
+ """
+ return {
+ 'sentence': data[0],
+ 'selection': data[1],
+ '3dfix': _convert(data[2], int, ''),
+ 'prns': data[3:14],
+ 'pdop': convert(data[15], float, ''),
+ 'horizontal_dilution': _convert(data[16], float, ''),
+ 'vertical_dilution': _convert(data[17], float, ''),
+ }
+
+def _decode_gsv(data):
+ """ decode_gsv(date) -> dict
+ Internal function.
+ """
+ return {
+ 'sentence': data[0],
+ 'satelite': _convert(data[2], int, ''),
+ 'inuse': _convert(data[1], int, ''),
+ 'inview': _convert(data[3], int, ''),
+ 'prn': _convert(data[4], int, ''),
+ 'elevation': _convert(data[5], float, ''),
+ 'azimuth': _convert(data[6], float, ''),
+ 'snr': _convert(data[7], int, '')
+ }
+
+def _decode_rmc(data):
+ """ decode_rmc(date) -> dict
+ Internal function.
+ """
+ return {
+ 'sentence': data[0],
+ 'time': format_time(data[1]),
+ 'active': data[2],
+ 'latitude': '%s' % format_latlong(data[3], data[4]),
+ 'longitude': '%s' % format_latlong(data[5], data[6]),
+ 'speed': _convert(data[7], float, ''),
+ 'angle': _convert(data[8], float, ''),
+ 'date': format_date(data[9]),
+ 'variation': '%s,%s' % (data[10], data[11])
+ }
+
+#
+# Simple dictionary mapping the sentence types to their
+# corresponding decoder functions.
+#
+_decode_func = {
+ 'GLL': _decode_gll,
+ 'GSA': _decode_gsa,
+ 'GSV': _decode_gsv,
+ 'RMC': _decode_rmc,
+}
+
+#
+# Simple test case, this can be used to run indefinitely (formatting and printing
+# each record) or run until it gets a GLL response and print the machines location.
+#
+if __name__ == '__main__':
+ import sys
+ port = 4
+ gps = GPSDevice(port)
+ gps.open()
+ for record in gps.read_all():
+ if sys.argv[0] == 'forever':
+ print record
+ else:
+ if record['sentence'] == 'GLL':
+ print 'I was at long %s, lat %s at %s' % (
+ record['longitude'],
+ record['latitude'],
+ record['time'])
+ break
diff --git a/gps_serial.py~ b/gps_serial.py~
new file mode 100644
index 0000000..c25581b
--- /dev/null
+++ b/gps_serial.py~
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+
+# Copyright (C) 2007 by Jaroslaw Zachwieja
+# Published under the terms of GNU General Public License v2 or later.
+# License text available at http://www.gnu.org/licenses/licenses.html#GPL
+
+import serial
+import string
+
+gps = serial.Serial('/dev/ttyUSB0', 4800, timeout=1)
+file = '/tmp/nmea.kml'
+
+print "Serving data"
+
+latitude = 0
+longitude = 0
+speed = 0
+heading = 0
+altitude = 0
+range = 1000
+tilt = 30
+
+while 1:
+ line = gps.readline()
+ datablock = line.split(',')
+
+ if line[0:6] == '$GPRMC':
+ latitude_in = string.atof(datablock[3])
+ longitude_in = string.atof(datablock[5])
+ altitude = string.atof(datablock[8])
+ speed_in = string.atof(datablock[7])
+ heading = string.atof(datablock[8])
+
+ if datablock[4] == 'S':
+ latitude_in = -latitude_in
+ if datablock[6] == 'W':
+ longitude_in = -longitude_in
+
+ latitude_degrees = int(latitude_in/100)
+ latitude_minutes = latitude_in - latitude_degrees*100
+
+ longitude_degrees = int(longitude_in/100)
+ longitude_minutes = longitude_in - longitude_degrees*100
+
+ latitude = latitude_degrees + (latitude_minutes/60)
+ longitude = longitude_degrees + (longitude_minutes/60)
+
+ speed = int(speed_in * 1.852)
+ range = ( ( speed / 100 ) * 350 ) + 650
+ tilt = ( ( speed / 120 ) * 43 ) + 30
+
+ if speed < 10:
+ range = 200
+ tilt = 30
+ heading = 0
+
+ output = """<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://earth.google.com/kml/2.0">
+ <Placemark>
+ <name>%s km/h</name>
+ <description>^</description>
+ <LookAt>
+ <longitude>%s</longitude>
+ <latitude>%s</latitude>
+ <range>%s</range>
+ <tilt>%s</tilt>
+ <heading>%s</heading>
+ </LookAt>
+ <Point>
+ <coordinates>%s,%s,%s</coordinates>
+ </Point>
+ </Placemark>
+</kml>""" % (speed,longitude,latitude,range,tilt,heading,longitude,latitude,altitude)
+
+ f=open(file, 'w')
+ f.write(output)
+ f.close()
+
+ser.close()
+
diff --git a/gpspoller.py b/gpspoller.py
new file mode 100644
index 0000000..6f7c19c
--- /dev/null
+++ b/gpspoller.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+# Copyright (C) 2007 by Jaroslaw Zachwieja
+# Modified (C) 2012 by Tim Redfern
+# Published under the terms of GNU General Public License v2 or later.
+# License text available at http://www.gnu.org/licenses/licenses.html#GPL
+
+import serial,string,threading,time,sys,random
+
+class GpsPoller(threading.Thread):
+
+ latitude = 0
+ longitude = 0
+ changed = False
+
+ def __init__(self,port,test=False):
+ self.test=test
+ self.port=port
+ self.gps = serial.Serial(port, 9600, timeout=1)
+ threading.Thread.__init__(self)
+
+ def check(self):
+ if self.changed:
+ self.changed=False
+ return (self.latitude,self.longitude)
+ else:
+ return False
+
+ def run(self):
+ if self.test:
+ print "GpsPoller: serving random data"
+ else:
+ print "GpsPoller: serving data from",self.port
+ try:
+ while True:
+ if self.test:
+ self.latitude=random.random()*90
+ self.longitude=random.random()*90
+ self.changed=True
+ time.sleep(0.5)
+ else:
+ line = self.gps.read(1)
+ line = line+self.gps.readline()
+ datablock = line.split(',')
+
+ if line[0:6] == '$GPRMC':
+ latitude_in = string.atof(datablock[3])
+ longitude_in = string.atof(datablock[5])
+ altitude = string.atof(datablock[8])
+ speed_in = string.atof(datablock[7])
+ heading = string.atof(datablock[8])
+
+ if datablock[4] == 'S':
+ latitude_in = -latitude_in
+ if datablock[6] == 'W':
+ longitude_in = -longitude_in
+
+ latitude_degrees = int(latitude_in/100)
+ latitude_minutes = latitude_in - latitude_degrees*100
+
+ longitude_degrees = int(longitude_in/100)
+ longitude_minutes = longitude_in - longitude_degrees*100
+
+ latitude = latitude_degrees + (latitude_minutes/60)
+ longitude = longitude_degrees + (longitude_minutes/60)
+
+ if latitude!=self.latitude or longitude!=self.longitude:
+ self.latitude=latitude
+ self.longitude=longitude
+ self.changed=True
+
+
+ except StopIteration:
+ pass
+
+ def __del__():
+ self.gps.close()
+
+if __name__ == '__main__':
+
+ gpsp = GpsPoller(sys.argv[1])
+ gpsp.start()
+ while 1:
+ # In the main thread, every 5 seconds print the current value
+ time.sleep(0.1)
+ check=gpsp.check()
+ if check!=False:
+ print "changed:",check[0],check[1]
diff --git a/gpspoller.pyc b/gpspoller.pyc
new file mode 100644
index 0000000..e8cda43
--- /dev/null
+++ b/gpspoller.pyc
Binary files differ
diff --git a/gpstest.py b/gpstest.py
new file mode 100644
index 0000000..88c5198
--- /dev/null
+++ b/gpstest.py
@@ -0,0 +1,14 @@
+import sys,gps
+port = 6
+gps = GPSDevice(port)
+gps.open()
+for record in gps.read_all():
+ if sys.argv[0] == 'forever':
+ print record
+ else:
+ if record['sentence'] == 'GLL':
+ print 'I am hanging out at long %s, lat %s at %s' % (
+ record['longitude'],
+ record['latitude'],
+ record['time'])
+ break \ No newline at end of file
diff --git a/indexmapV1.gif b/indexmapV1.gif
new file mode 100644
index 0000000..63363bb
--- /dev/null
+++ b/indexmapV1.gif
Binary files differ
diff --git a/latLng.pyc b/latLng.pyc
new file mode 100644
index 0000000..11ac9e8
--- /dev/null
+++ b/latLng.pyc
Binary files differ
diff --git a/layers.py b/layers.py
index 38aeba4..6c1d33f 100644
--- a/layers.py
+++ b/layers.py
@@ -18,7 +18,7 @@ class layer:
except:
print "gps layer: failed to parse", file
def findpixel(self,pos):
- return latLng(int((pos.lng-self.tl.lng)/self.pixsize.lng),int((pos.lat-self.br.lat)/self.pixsize.lat))
+ return (int((pos.lng-self.tl.lng)/self.pixsize.lng),int((pos.lat-self.br.lat)/self.pixsize.lat))
def checkcoord(self,pos):
p=self.findpixel(pos)
if p!=self.pixel:
@@ -27,7 +27,10 @@ class layer:
else:
return None
def setcoord(self,pos):
- return str(1.0)
+ """constructs a list of messages when values change"
+ returns None otherwise"""
+ result=None
+ return r
class trigger():
"""a generic trigger -
@@ -43,6 +46,26 @@ class trigger():
return None
class indexlayer(layer):
+ """generates gps triggers from an index colour image
+ triggers when colour changes"""
triggers=[]
+ colour=-1
def setcoord(self,pos):
- return str(1) \ No newline at end of file
+ result=None
+ #210 35 5 185
+ c=self.image.getpixel(pos)
+ if c!=self.colour:
+ self.colour=c
+ print "indexlayer: new colour",c
+ for t in self.triggers:
+ if c==t.id:
+ result=t.command
+ return result
+
+class scalelayer(layer):
+ """generates a varying signal based on interpolating a greyscale image
+ uses sub pixel position"""
+ def findpixel(self,pos):
+ return (int((pos.lng-self.tl.lng)/self.pixsize.lng),int((pos.lat-self.br.lat)/self.pixsize.lat))
+ def setcoord(self,pos):
+ result=None \ No newline at end of file
diff --git a/layers.pyc b/layers.pyc
new file mode 100644
index 0000000..e95e372
--- /dev/null
+++ b/layers.pyc
Binary files differ
diff --git a/testreceive.pd b/testreceive.pd
index c375170..d53a273 100644
--- a/testreceive.pd
+++ b/testreceive.pd
@@ -1,4 +1,14 @@
-#N canvas 796 273 450 300 10;
-#X obj 126 54 netreceive 5401 1;
-#X obj 126 96 print udp;
-#X connect 0 0 1 0;
+#N canvas 915 509 450 300 10;
+#X obj 169 92 print udp;
+#X msg 29 61 /pd 1;
+#X msg 82 26 /other 1;
+#X obj 169 50 netreceive 5401 1;
+#X obj 148 141 OSCroute /play;
+#X obj 145 210 print play;
+#X obj 230 204 print other;
+#X connect 1 0 4 0;
+#X connect 2 0 4 0;
+#X connect 3 0 0 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 4 1 6 0;
diff --git a/tomorrowtheground.py b/tomorrowtheground.py
index 2ffdf7e..5553b42 100755
--- a/tomorrowtheground.py
+++ b/tomorrowtheground.py
@@ -1,6 +1,21 @@
#!/usr/bin/python
#UDP listener
+import signal,sys
+
+def signal_handler(signal, frame):
+ insock.close()
+ print "tomorrowtheground: interrupted"
+ sys.exit(0)
+
+signal.signal(signal.SIGINT, signal_handler)
+
+import gpspoller
+gpsp=""
+if len(sys.argv)>1:
+ gpsp = GpsPoller(sys.argv[1])
+ gpsp.start()
+
from latLng import *
from layers import *
from xml2obj import *
@@ -8,7 +23,7 @@ from xml2obj import *
doc=xml2obj(open("ttg01.xml"))
gpslayers=[]
for i in doc.gps.index:
- #should catch invalid xml
+ #catch invalid xml
g=indexlayer(i.file,i.ll1,i.ll2)
for t in i.trigger:
g.triggers.append(trigger(int(t.id),t.command,t.param))
@@ -20,7 +35,7 @@ GUI_IP="127.0.0.1"
GUI_PORT=5400
insock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
insock.bind( (GUI_IP,GUI_PORT) )
-insock.settimeout(0.01)
+insock.settimeout(0.01) #non blocking
PD_IP="127.0.0.1"
PD_PORT=5401
outsock = socket.socket( socket.AF_INET,socket.SOCK_DGRAM )
@@ -35,11 +50,17 @@ while True:
pos.parse(data)
posChanged=True
except:
- nothing=None
+ nothing=None
+ if gpsp!="":
+ check=gpsp.check()
+ if check!=False:
+ pos=latLng(check[0],check[1])
+ posChanged=True
if posChanged:
- print "received message:", data
+ posChanged=False
for layer in gpslayers:
- r=layer.checkcoord(pos)
- if layer.checkcoord!=None:
- outsock.sendto( r, (PD_IP, PD_PORT) )
+ r=layer.checkcoord(pos) #returns a message or None
+ if r!=None:
+ #pd needs \n at end of message
+ outsock.sendto( str(r[0])+' '+str(r[1])+'\n', (PD_IP, PD_PORT) )
\ No newline at end of file
diff --git a/tomorrowthegroundGUI/data/indexmapV1.gif b/tomorrowthegroundGUI/data/indexmapV1.gif
new file mode 100644
index 0000000..3fcc16f
--- /dev/null
+++ b/tomorrowthegroundGUI/data/indexmapV1.gif
Binary files differ
diff --git a/tomorrowthegroundGUI/tomorrowthegroundGUI.pde b/tomorrowthegroundGUI/tomorrowthegroundGUI.pde
index 0fe919e..b359409 100644
--- a/tomorrowthegroundGUI/tomorrowthegroundGUI.pde
+++ b/tomorrowthegroundGUI/tomorrowthegroundGUI.pde
@@ -1,15 +1,19 @@
import hypermedia.net.*;
-PImage bgmap;
+PImage[] bgmaps;
+int usemap;
UDP udp;
int x,y;
float lat1,lng1,lat2,lng2,fw,fh;
void setup()
{
- bgmap = loadImage("gentmap.png");
+ bgmaps=new PImage[2];
+ bgmaps[0] = loadImage("gentmap.png");
+ bgmaps[1] = loadImage("indexmapV1.gif");
+ usemap=0;
size(bgmap.width,bgmap.height);
- frameRate(30);
+ frameRate(15);
udp = new UDP(this);
x=width/2;
y=height/2;
@@ -23,7 +27,7 @@ void setup()
void draw()
{
- background(bgmap);
+ background(bgmaps[usemap]);
fill(255);
stroke(255,0,0);
ellipse(x,y,5,5);
@@ -39,3 +43,15 @@ void mouseDragged()
udp.send(((fy*fh)+lat2)+","+((fx*fw)+lng1)+"\n","127.0.0.1",5400);
}
}
+
+void keyPressed() {
+ switch(key) {
+ case '0':
+ usemap=0;
+ break;
+ case '1':
+ usemap=1;
+ break;
+ }
+}
+
diff --git a/ttg01.xml b/ttg01.xml
index 3b3daa0..7b49bda 100644
--- a/ttg01.xml
+++ b/ttg01.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<tomorrowtheground>
<gps>
- <index file="x01.png" ll1="51.050608,3.724698" ll2="51.046878,3.732852">
+ <index file="indexmapV1.gif" ll1="51.050608,3.724698" ll2="51.046878,3.732852">
<trigger id="01" command="play" param="b01.wav">
</trigger>
- <trigger id="02" command="play" param="b02.wav">
+ <trigger id="03" command="play" param="b02.wav">
+ </trigger>
+ <trigger id="28" command="play" param="b03.wav">
+ </trigger>
+ <trigger id="29" command="play" param="b04.wav">
</trigger>
</index>
<scale file="x02.png" ll1="51.050608,3.724698" ll2="51.046878,3.732852" freq="1.0" command="cc01">
diff --git a/xml2obj.pyc b/xml2obj.pyc
new file mode 100644
index 0000000..180a0bb
--- /dev/null
+++ b/xml2obj.pyc
Binary files differ