I wrote a python script (a very messy one…) that takes KinetaMap data and plots the route in Google Earth. It also puts placemarks at points where the acceleration values have breached a certain threshold.
The script assumes you are using version 1.1 or earlier firmware. If you used a later firmware version, than you’ll have to remove the ‘toG’ function from the main routine.
Let me know if you want help getting this to work:
# Link to Google Earth Placemark: http://maps.google.com/mapfiles/kml/pal2/icon18.png
import sys
import math
coordinate_list=[]
line_list=[]
test_list=[]
filename=[]
G_thresh=0.5
Distance_thresh=100
#Radius of the Earth in Feet (This can be changed to any unit to have the 'getDistance' function return the distance in the given unit
Radius=20925656.2
def GPStoDec(coordinate, direction):
test_list=coordinate.split('.')
if direction != 'N' and direction != 'S' and direction !='E' and direction != 'W': return 0
if (len(str(test_list[0])) < 4):return 0
if (coordinate.count('.') <= 1) and str(test_list[0]).isdigit():
Degree=int(float(coordinate)/100)
Decimal=Degree+((float(coordinate)-(Degree*100))/60)
if direction == 'S':
Decimal=Decimal*-1
if direction == 'W':
Decimal=Decimal*-1
return Decimal
else: return 0
def getBitValue(n, p):
return (n >> p) & 1
def getDistance(lat1, long1, lat2, long2):
#Make sure we actually received values
#if (lat1==0) or (lat2==0) or (long1==0) or (long2==0):return 0
#Convert the Coordinates to Radians (from degrees)
lat1=math.radians(lat1)
long1 = math.radians(long1)
lat2 = math.radians(lat2)
long2 = math.radians(long2)
#Calculate the distance between the two points
dlat=lat1-lat2
dlong=long1-long2
A = math.sin(dlat/2)**2 + math.cos(lat1)*math.cos(lat2)*math.sin(dlong/2)**2
C = 2*math.atan2(math.sqrt(A), math.sqrt(1-A))
return Radius*C
def toG(value):
#Check to see if the value is a negative number. If it it, get the two's compliment
if(getBitValue(value, 7)):
acceleration=-128
if(getBitValue(value, 6)):acceleration+=pow(2,6)
if(getBitValue(value, 5)):acceleration+=pow(2,5)
if(getBitValue(value, 4)):acceleration+=pow(2,4)
if(getBitValue(value, 3)):acceleration+=pow(2,3)
if(getBitValue(value, 2)):acceleration+=pow(2,2)
if(getBitValue(value, 1)):acceleration+=pow(2,1)
if(getBitValue(value, 0)):acceleration+=pow(2,0)
return float(acceleration)*18/1000 #Convert to G's
else: return float(value)*18/1000 #Convert to Gs
def putCustomPlacemark(Handle, Name, Lat, Long, X, Y, Z):
Handle.write("\t<Placemark>\n")
Handle.write("\t\t<name>"+str(Name)+"</name>\n")
if (abs(float(X)) < 0.66) and (abs(float(Y)) < 0.66) and (abs(float(Z)) < 0.66):Handle.write("\t\t<styleUrl>#Green Dot</styleUrl>\n")
elif (abs(float(X)) < 1.33) and (abs(float(Y)) < 1.33) and (abs(float(Z)) < 1.33):Handle.write("\t\t<styleUrl>#Yellow Dot</styleUrl>\n")
else:Handle.write("\t\t<styleUrl>#Red Dot</styleUrl>\n")
Handle.write("\t\t<ExtendedData>\n")
Handle.write("\t\t\t<Data name=\"X Acceleration\">\n")
Handle.write("\t\t\t\t<value>"+str(round(float(X),2))+"g</value>\n")
Handle.write("\t\t\t</Data>\n")
Handle.write("\t\t\t<Data name=\"Y Acceleration\">\n")
Handle.write("\t\t\t\t<value>"+str(round(float(Y),2))+"g</value>\n")
Handle.write("\t\t\t</Data>\n")
Handle.write("\t\t\t<Data name=\"Z Acceleration\">\n")
Handle.write("\t\t\t\t<value>"+str(round(float(Z),2))+"g</value>\n")
Handle.write("\t\t\t</Data>\n")
Handle.write("\t\t</ExtendedData>\n")
Handle.write("\t\t<Point>\n")
Handle.write("\t\t\t<coordinates>")
Handle.write(str(Long))
Handle.write(",")
Handle.write(str(Lat))
Handle.write("</coordinates>\n")
Handle.write("\t\t</Point>\n")
Handle.write("\t</Placemark>\n")
def main():
#Define the line offset positions of the values in the input file
time_offset=0; x_offset=1; y_offset=2; z_offset=3; batt_offset=4; latitude=6; lat_dir=7; longitude=8; long_dir=9;
#Keep track of last plotted placemark position
old_lat=0; old_long=0; distance=0;
current_lat=0; current_long=0;
#Runnning tallie of acceleration values
xMax=0; yMax=0; zMax=0;
#Get the input file to retrieve the KinetaMap Data from
f = open(sys.argv[1])
#Create the filename for the KML output file. Use the filename of the input file and just change the extension to .kml
filename=sys.argv[1].split('.')
kml_filename=str(filename[0])+".kml"
#Open the kml file to write to
fo=open(kml_filename, "w")
#Write the KML File Header
fo.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
fo.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n")
fo.write("<Document>\n")
fo.write("\t<name>KinetaMap Path</name>\n")
fo.write("\t<description>Manual Conversion of a GPS Coordinate (DDMM.MMMM) to Decimal</description>\n")
#Create Icon Styles
fo.write("\t<Style id=\"Red Dot\">\n")
fo.write("\t\t<IconStyle>\n")
fo.write("\t\t\t<Icon>\n")
fo.write("\t\t\t\t<href>http://maps.google.com/mapfiles/kml/pal2/icon18.png</href>\n")
fo.write("\t\t\t</Icon>\n")
fo.write("\t\t\t<scale>0.25</scale>\n")
fo.write("\t\t\t<color>ff0000ff</color>\n")
fo.write("\t\t</IconStyle>\n")
fo.write("\t</Style>\n")
fo.write("\t<Style id=\"Green Dot\">\n")
fo.write("\t\t<IconStyle>\n")
fo.write("\t\t\t<Icon>\n")
fo.write("\t\t\t\t<href>http://maps.google.com/mapfiles/kml/pal2/icon18.png</href>\n")
fo.write("\t\t\t</Icon>\n")
fo.write("\t\t\t<scale>0.25</scale>\n")
fo.write("\t\t\t<color>ff00ff00</color>\n")
fo.write("\t\t</IconStyle>\n")
fo.write("\t</Style>\n")
fo.write("\t<Style id=\"Yellow Dot\">\n")
fo.write("\t\t<IconStyle>\n")
fo.write("\t\t\t<Icon>\n")
fo.write("\t\t\t\t<href>http://maps.google.com/mapfiles/kml/pal2/icon18.png</href>\n")
fo.write("\t\t\t</Icon>\n")
fo.write("\t\t\t<scale>0.25</scale>\n")
fo.write("\t\t\t<color>ff00ffff</color>\n")
fo.write("\t\t</IconStyle>\n")
fo.write("\t</Style>\n")
#Go through each line of the input file
for line in f.xreadlines():
#Seperate each value in the line of data into a list
line_list=line.strip('\n').split(',') #Create a list of the elements in the line of data
#Check to see if there was any data in this line received from the input file
if(len(line_list) > 1):
#Keep track of the maximum acceleration
if line_list[x_offset].isdigit() and abs(toG(int(line_list[x_offset]))) > abs(xMax):
xMax=toG(int(line_list[x_offset]))
print str(line_list[time_offset]) + " Bin X=" + str(line_list[x_offset]) + " G=" + str(xMax)
if line_list[y_offset].isdigit() and abs(toG(int(line_list[y_offset]))) > abs(yMax):
yMax=toG(int(line_list[y_offset]))
print str(line_list[time_offset]) + " Bin Y=" + str(line_list[y_offset])+ " G=" + str(yMax)
if line_list[z_offset].isdigit() and abs(toG(int(line_list[z_offset]))) > abs(zMax):
zMax=toG(int(line_list[z_offset]))
print str(line_list[time_offset]) + " Bin Z=" + str(line_list[z_offset])+ " G=" + str(zMax)
#If there is GPS data is this line of data then we need to analyze the coordinates and the current acceleration values
#if (len(line_list[longitude]) > 0) and (len(line_list[latitude]) > 0) and ((line_list[lat_dir]=='N') or (line_list[lat_dir]=='S')) and ((line_list[long_dir]=='W') or (line_list[long_dir]=='E')):
current_lat=GPStoDec(line_list[latitude], line_list[lat_dir])
current_long=GPStoDec(line_list[longitude], line_list[long_dir])
if (current_lat != 0) and (current_long !=0):
#Copy the GPS coordinates to a seperate list in Degree Format. This list will be used to create the KML Path
coordinate_list.append('\t\t\t\t')
coordinate_list.append(current_long)
coordinate_list.append(',')
coordinate_list.append(current_lat)
coordinate_list.append('\n')
#Find the distance between the last 'logged' placemark and the current position
distance=getDistance(old_lat, old_long, current_lat, current_long)
#Check to see if we have a acceleration that vioates the threshold, and see if we've traveled far enough to plot a new point
if ((abs(xMax) > G_thresh) or (abs(yMax) > G_thresh) or (abs(zMax) > G_thresh)) and (distance > Distance_thresh):
#print "Time: " + str(line_list[time_offset]) + " X="+str(round(xMax,2)) +" Y=" + str(round(yMax,2)) + " Z=" + str(round(zMax,2)) + " Distance: " + str(round(distance,2))
putCustomPlacemark(fo, line_list[time_offset], current_lat, current_long, xMax, yMax, zMax)
old_lat=GPStoDec(line_list[latitude], line_list[lat_dir])
old_long=GPStoDec(line_list[longitude], line_list[long_dir])
#Reset the Max Acceleration Values every time we get a new GPS Position. Max Values are just keeping track of the maximum acceleration values for each GPS point
xMax=0
yMax=0
zMax=0
#Overlay the path onto the placemarks
fo.write("\t<Placemark>\n")
fo.write("\t\t<LineString>\n")
fo.write("\t\t\t<tessellate>1</tessellate>\n")
fo.write("\t\t\t<coordinates>\n")
for item in coordinate_list:
fo.write(str(item))
fo.write("\t\t\t</coordinates>\n")
fo.write("\t\t</LineString>\n")
fo.write("\t</Placemark>\n")
f.close()
fo.write("</Document>\n")
fo.write("</kml>\n")
fo.close
if __name__ == "__main__":
main()