Skip to content

Instantly share code, notes, and snippets.

@dj1711572002
Created July 4, 2025 15:10
Show Gist options
  • Select an option

  • Save dj1711572002/395c889b28a88b04c2f0fc8d0529f541 to your computer and use it in GitHub Desktop.

Select an option

Save dj1711572002/395c889b28a88b04c2f0fc8d0529f541 to your computer and use it in GitHub Desktop.
ubx Parsing RELPOSNED HPN HPE HPD 
# Parse_Allubx_04.py
# バージョン04:すべてのUBXメッセージをCSV出力し、NAV-RELPOSNEDはHP成分を自力パースしてmm単位で追加
import os
import struct
import pandas as pd
from tkinter import Tk, filedialog
from pyubx2 import UBXReader, UBX_PROTOCOL
def parse_allubx_with_relpos_hpmm(ubx_file, output_dir=None):
"""
UBXバイナリから全メッセージをパースし、各メッセージごとにCSVを出力。
NAV-RELPOSNEDは高精度成分(HPN/HPE/HPD)を手動抽出し、mm単位のリニア位置を追加。
"""
if output_dir is None:
output_dir = os.path.dirname(ubx_file)
base = os.path.splitext(os.path.basename(ubx_file))[0]
msg_dict = {}
with open(ubx_file, 'rb') as fh:
ubr = UBXReader(fh, protfilter=UBX_PROTOCOL, parsebitfield=True)
for raw, parsed in ubr:
if parsed is None:
continue
identity = parsed.identity # e.g. 'NAV-PVT', 'NAV-RELPOSNED'
# 基本フィールド辞書化
try:
fields = parsed.to_dict()
except AttributeError:
fields = {k: v for k, v in parsed.__dict__.items() if not k.startswith('_')}
# NAV-RELPOSNED の場合、HP成分をrawバイナリから抽出
if identity == 'NAV-RELPOSNED':
# raw: バイト列(header+length+payload+checksum)
# payload offset: 6..6+length
length = struct.unpack('<H', raw[4:6])[0]
payload = raw[6:6+length]
if len(payload) >= 35:
# relPosHP fields at offsets 32,33,34
relPosHPN = struct.unpack('<b', payload[32:33])[0]
relPosHPE = struct.unpack('<b', payload[33:34])[0]
relPosHPD = struct.unpack('<b', payload[34:35])[0]
fields['relPosHPN'] = relPosHPN
fields['relPosHPE'] = relPosHPE
fields['relPosHPD'] = relPosHPD
# combine cm->mm
if 'relPosN' in fields:
fields['relPosN_mm'] = fields['relPosN'] * 10 + relPosHPN
if 'relPosE' in fields:
fields['relPosE_mm'] = fields['relPosE'] * 10 + relPosHPE
if 'relPosD' in fields:
fields['relPosD_mm'] = fields['relPosD'] * 10 + relPosHPD
# iTOWをintにしてソートしやすく
if 'iTOW' in fields:
fields['iTOW'] = int(fields['iTOW'])
# メッセージ毎にリストへ
msg_dict.setdefault(identity, []).append(fields)
# CSV出力
for identity, records in msg_dict.items():
df = pd.DataFrame(records)
if 'iTOW' in df.columns:
df.sort_values('iTOW', inplace=True)
msg_name = identity.lower().replace('-', '_')
out_csv = os.path.join(output_dir, f"{base}_{msg_name}_v04.csv")
df.to_csv(out_csv, index=False, encoding='utf-8-sig')
print(f"Saved {out_csv}")
def main():
root = Tk()
root.withdraw()
ubx_file = filedialog.askopenfilename(
title="Select UBX binary file",
filetypes=[("UBX files", "*.ubx;*.bin"), ("All files", "*.*")]
)
if not ubx_file:
print("No file selected.")
return
parse_allubx_with_relpos_hpmm(ubx_file)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment