PCQ-HGR3S のログから Google Map 対応 XML を作る

PCQ-GPS3S とも言うらしい。 Sony 謹製の古い GPS ユニット。随分前に知人から譲って貰って以来しばらく眠らせていたのですが、前に Python でログ CSV を XML に変換するツールを書いたのでちょくちょく使用中。

とりあえずコード@Python 3.0

#!/usr/bin/python
# coding: utf-8

import os, re, csv, sys, math, codecs

arg = sys.argv

if (len(arg) < 2):
  print('Usage: python %s [.csv file]' % sys.argv[0])
  exit()


RAD = math.pi / 180

EqTKY = 6377397.155
tireT = 1/299.152813
ecT = tireT * (2 - tireT)

EqWGS = 6378137
tireW = 1/298.257223
ecW = tireW * (2 - tireW)

def E2R(B, L, H):
  # 楕円体(B, L, H)から直行座標系(X, Y, Z)へ
  # Ellipoid to Rectangular Coordinate System
  
  Eq = EqTKY
  Ec = ecT

  Brad = B * RAD
  Lrad = L * RAD
  
  rN = Eq / math.sqrt(1 - Ec * (math.sin(Brad) ** 2))
  
  x = (rN + H) * math.cos(Brad) * math.cos(Lrad)
  y = (rN + H) * math.cos(Brad) * math.sin(Lrad)
  z = (rN * (1 - Ec) + H) * math.sin(Brad)
  
  return (x, y, z)


def R2E(X, Y, Z):
  # 直行座標系(X, Y, Z)から楕円体(B, L, H)へ
  # Rectangular Coordinate System to Ellipoid
  
  Eq = EqWGS
  Ec = ecW
  
  BdA = math.sqrt(1 - Ec)
  
  P = math.sqrt(X * X + Y * Y)
  T = math.atan2(Z, P * BdA)
  
  B = math.atan2(Z + Ec * Eq / BdA * (math.sin(T) ** 3), P - Ec * Eq * (math.cos(T) ** 3))
  L = math.atan2(Y, X)

  H = P / math.cos(B) - Eq / math.sqrt(1 - Ec * (math.sin(B) ** 2))

  return (B / RAD, L / RAD, H)


def TKY2WGS(lat, lng, hgt):
  dx = -148
  dy = 507
  dz = 681

  RCS = E2R(lat, lng, hgt)
  Ellips = R2E(RCS[0] + dx, RCS[1] + dy, RCS[2] + dz)
  return(Ellips)


if __name__ == '__main__':

  try:
    f = os.path.abspath(arg[1])
    data = csv.reader(open(f, 'r'))
  
  except:
    print("Error: Can't open target file '%s'" % arg[1])
    exit()


  xml = '<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://earth.google.com/kml/2.1">\n<Document>\n'
  xml += """
  <Style id="marked"><IconStyle><Icon>
  <href>http://maps.google.com/intl/en_ALL/mapfiles/ms/icons/red-dot.png</href>
  </Icon></IconStyle></Style>
  <Style id="point"><IconStyle><scale>1.2</scale>
  <Icon><href>http://maps.google.com/intl/en_ALL/mapfiles/ms/icons/blue-dot.png</href>
  </Icon></IconStyle></Style>

  <Folder>
  """

  xml += '<name>' + os.path.basename(f) + '</name>\n'
  xml += '<description>' + os.path.basename(f) + '</description>\n'
# http://maps.google.com/intl/en_ALL/mapfiles/ms/icons/blue-dot.png

  track = ''
  points = ''

  L = list(data)
  c = len(L)

  for row in L:

    if (len(row) != 13 ): continue

    r = re.compile(r'(\w)\s?(\d{2,3})°(\d{2})′(\d{2})″')

    # 緯度
    laT = r.split(row[8])

    # 経度
    lgT = r.split(row[9])

    if ( (len(laT) < 3) or (len(lgT) < 3) ): continue

    latitude = int(laT[2]) + int(laT[3]) / 60 + int(laT[4]) / 3600
    longitude = int(lgT[2]) + int(lgT[3]) / 60 + int(lgT[4]) / 3600

    if (laT[1] == 'S'): latitude  = -latitude
    if (lgT[1] == 'W'): longitude = -longitude

    WGS = TKY2WGS(latitude, longitude, 0)

    lg = str(WGS[1])
    la = str(WGS[0])

    track += lg + ',' + la + ',0.00\n'

    if (c < 50):
      t = 0
    else:
      t = int(row[0]) % 20

    if ( (row[1] == '1') or (row[0] == '2') or (int(row[0]) == c - 2) or (t == 0) ):

      if (row[1] == '1'):
        title = 'Marked Point: ' + row[0]
        style = 'marked'
      elif (row[0] == '2'):
        title = 'Start Point'
        style = 'marked'
      elif (int(row[0]) == c - 2):
        title = 'End Point'
        style = 'marked'
      else:
        title = row[0]
        style = 'point'

      points += '<Placemark><styleUrl>#' + style + '</styleUrl><name>' + title + '</name><Snippet maxLines="2"></Snippet>\n<description><![CDATA[<table>'
      points += '<tr><td>経度: ' + lg + '</td></tr>\n'
      points += '<tr><td>緯度: ' + la + '</td></tr>\n'
      points += '<tr><td>累積距離: ' + row[4] + ' (km) </td></tr>\n'
      points += '<tr><td>時速: ' + row[5] + ' (km/h) </td></tr>\n'
      points += '<tr><td>進行方向: ' + row[6] + '</td></tr>\n'
      points += '<tr><td>日時: ' + row[2].replace('/', '-') + 'T' + row[3] + '+09:00' + '</td></tr></table>]]></description>\n'
      points += '<LookAt><longitude>' + lg + '</longitude><latitude>' + la + '</latitude><altitude>0</altitude>\n'
      points += '<range>0</range><tilt>' + row[6] + '</tilt><heading>0</heading></LookAt>\n'
      points += '<TimeStamp><when>' + row[2].replace('/', '-') + 'T' + row[3] + '+09:00' + '</when></TimeStamp><styleUrl>#track</styleUrl><Point><coordinates>'
      points += lg + ',' + la + ',0.00</coordinates></Point></Placemark>\n'


  pathxml = '<Placemark><name>Path</name>\n<LineString><tessellate>1</tessellate><coordinates>\n'
  pathxml += track
  pathxml += '</coordinates></LineString></Placemark>'

  #xml += '<Folder><name>Points</name>' + points + '</Folder><Folder><name>LineStrings</name>' + pathxml + '</Folder>\n'
  xml += '<Folder><name>LineStrings</name>' + pathxml + '</Folder><Folder><name>Points</name>' + points + '</Folder>\n'
  xml += '</Folder></Document></kml>\n'
  
  outdir = os.path.dirname(f) + '\\xml\\'

  try:
    os.mkdir(outdir)
  except os.error as msg:
    pass

  rc = re.compile('\d+')
  fname = os.path.splitext(f)[0]
  no = rc.findall(fname[int(fname.rindex('\\')):])

  for df in no:
    outdir += str(int(df)) + '-'

  try:
    fh = codecs.open(outdir.rstrip('-') + '.xml', 'w', 'utf-8')
    fh.write(xml)
    fh.close()
  
  except:
    print("Error: Can't write to file '%s'. Check permission." % outdir.rstrip('-') + '.xml')

まぁそのまんま変換掛けてるだけ。 Navin' you 系のログなら殆ど対応できるんじゃないかと。サポート打ち切りになって久しいし、適当に使ってくだしあ。