Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nmea2pmtiles #564

Closed
hfu opened this issue Aug 4, 2024 · 1 comment
Closed

nmea2pmtiles #564

hfu opened this issue Aug 4, 2024 · 1 comment
Assignees

Comments

@hfu
Copy link
Contributor

hfu commented Aug 4, 2024

Raspberry Pi に接続した安価な GNSS 受信機から GeoJSON Text Sequence を生成するスクリプトを作りました。
NMEA の勉強のついでという感じになりました。無駄な部分も多いと思います。

Makefile

SRC = /dev/ttyACM0
DST = a.geojsons

parse:
        cat $(SRC) | ruby parse.rb > $(DST)

parse.rb

require 'json'
require 'time'

$dict = Hash.new {|h, k| h[k] = 0}

$satellites = {
  :number => 0
}

$receiver = {
  :texts => [],
}

def separate
  $stderr.print <<-EOS
>>>
  #{JSON.pretty_generate($receiver)}
  #{JSON.generate($satellites)}
<<<
  EOS
end

def sequence
  time = Time.utc(
    2000 + $receiver[:_date][4..5].to_i,
    $receiver[:_date][2..3].to_i,
    $receiver[:_date][0..1].to_i,
    $receiver[:_time][0..1].to_i,
    $receiver[:_time][2..3].to_i,
    $receiver[:_time][4..5].to_i,
    $receiver[:_time][7..8].to_i * 10000
  )
  f = {
    :type => 'Feature',
    :geometry => {
      :type => 'Point',
      :coordinates => [
        ($receiver[:_EW] == 'E' ? 1 : -1) *
        ($receiver[:_long][0..2].to_i +
         $receiver[:_long][3..-1].to_f / 60),
       ($receiver[:_NS] == 'N' ? 1 : -1) *
        ($receiver[:_lat][0..1].to_i +
         $receiver[:_lat][2..-1].to_f / 60)
      ]
    },
    :properties => {
      :time => time.iso8601,
      :alt => $receiver[:alt],
      :pdop => $receiver[:pdop],
      :numSV => $receiver[:numSV],
      :kph => $receiver[:kph]
    }
  }
  print JSON.generate(f), "\n"
end

def dump(r)
  $dict[r[0]] += 1

  case r[0]
  when 'TXT'
    $receiver[:texts].push(r[4])
  when 'GSV'
    $satellites[:number] = r[3].to_i
    r[4..-1].each_slice(4).each {|s|
      $satellites[s[0]] = {
        :elevation => s[1].to_i,
        :azimuth => s[2].to_i,
        :snr => s[3].to_i,
        :active => nil
      }
    }
  when 'GSA'
    $receiver[:opMode] = r[1]
    $receiver[:navMode] = r[2]
    $satellites.each {|k, v|
      next unless k.size == 2
      v[:active] = false
    }
    r[3..14].delete_if(&:empty?).each {|sv|
      if $satellites[sv]
        $satellites[sv][:active] = true
      end
    }
    $receiver[:pdop] = r[15].to_f
    $receiver[:hdop] = r[16].to_f
    $receiver[:vdop] = r[17].to_f
  when 'VTG'
    $receiver[:knots] = r[5].to_f
    $receiver[:kph] = r[7].to_f
    $receiver[:posMode] = r[9]
  when 'GGA'
    $receiver[:_time] = r[1]
    $receiver[:_lat] = r[2]
    $receiver[:_NS] = r[3]
    $receiver[:_long] = r[4]
    $receiver[:_EW] = r[5]
    $receiver[:quality] = r[6].to_i
    $receiver[:numSV] = r[7].to_i
    $receiver[:hdop] = r[8].to_f
    $receiver[:alt] = r[9].to_f
    $receiver[:sep] = r[11].to_f
    $receiver[:diffAge] = r[13] #.empty? ? nil : r[12].to_f
    $receiver[:diffStation] = r[14]
  when 'GLL'
    $receiver[:_lat] = r[1]
    $receiver[:_NS] = r[2]
    $receiver[:_long] = r[3]
    $receiver[:_EW] = r[4]
    $receiver[:_time] = r[5]
    $receiver[:status] = r[6]
    $receiver[:posMode] = r[7]
  when 'RMC'
    $receiver[:_time] = r[1]
    $receiver[:status] = r[2]
    $receiver[:_lat] = r[3]
    $receiver[:_NS] = r[4]
    $receiver[:_long] = r[5]
    $receiver[:_EW] = r[6]
    $receiver[:knots] = r[7].to_f
    $receiver[:cog] = r[8].to_f
    $receiver[:_date] = r[9]
    $receiver[:posMode] = r[12]
    sequence
  else
    p r
  end
end

# Information Source: 
# https://content.u-blox.com/sites/default/files/products/documents/u-blox7-V14_ReceiverDescriptionProtocolSpec_%28GPS.G7-SW-12001%29_Public.pdf

while gets
  next unless /\$GP(.*)\*\d*$/.match($_)
  r = $1.strip.split(',')
  next if r[0] == 'TXT' and r[4] == 'NMEA unknown msg'
  dump(r)
  separate if r[0] == 'GLL'
end
@hfu
Copy link
Contributor Author

hfu commented Aug 11, 2024

本件は #567 で継続しているが、#567 では gpsd を使うことにしており、/dev/ttyACM0 を直接読むことはやめています。この結果、QZSS を活用できるようになっているようです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant