سؤال

لدي صديق الذي هو الانتهاء من درجة الماجستير في هندسة الطيران.عن مشروعه النهائي على فريق صغير المكلفة كتابة برنامج تتبع بالونات الطقس والصواريخ والأقمار الصناعية.البرنامج يتلقى الإدخال من جهاز لتحديد المواقع ، هل الحسابات مع البيانات و تستخدم نتائج تلك الحسابات إلى السيطرة على سلسلة من المحركات مصممة لتوجيه اتجاهي الاتصال الهوائي ، لذلك البالون ، الصواريخ أو الأقمار الصناعية يبقى دائما في التركيز.

إلى حد ما على الرغم من (الأبدية) المبتدئين نفسي, لدي خبرة في البرمجة من صديقي.حتى عندما طلب مني نصيحة أقنعته بأن كتابة البرنامج في بيثون ، اللغة التي يختارونها.

في هذه المرحلة من المشروع ، نحن نعمل على الرمز الذي يوزع الإدخال من جهاز GPS.هنا بعض الأمثلة على مدخل, مع البيانات التي تحتاج إلى استخراج بالخط العريض:

$GPRMC,092204.999,4250.5589,S,14718.5084,E,1,12,24.4,89.6، M،,, 0000*1F $GPRMC,093345.679,4234.7899 ، ن ، 11344.2567 ، ث,3,02,24.5,1000.23، M،,, 0000*1F $GPRMC,044584.936,1276.5539 ، ن ، 88734.1543,E,2,04,33.5,600.323,M,,,*00 $GPRMC,199304.973,3248.7780 ، ن ، 11355.7832 ، ث,1,06,02.2,25722.5,M,,,*00 $GPRMC,066487.954,4572.0089,S,45572.3345 ، ث,3,09,15.0,35000.00,M,,,*1F

هنا بعض مزيد من التوضيح من البيانات:

"أنا يبدو أنني سوف تحتاج خمسة أشياء من بين كل خط.و نضع في اعتبارنا أن أي واحد من هذه المنطقة قد تكون فارغة.وهذا يعني سوف يكون هناك اثنين فقط الفواصل بجوار بعضها البعض.هذه كما ',,,' هناك نوعان من الحقول التي قد تكون كاملة في أي وقت.بعض منهم فقط لديك اثنين أو ثلاثة خيارات أنهم قد يكون ولكن أنا لا أعتقد أنني يجب أن يكون أعتمد على ذلك."

قبل يومين صديقي كان قادرا على الحصول على سجل كامل من جهاز استقبال GPS تتبع الأخيرة الطقس بالون الإطلاق.البيانات طويلة جدا, لذلك أنا وضعت كل شيء في هذا pastebin.

أنا لا تزال جديدة نوعا ما مع التعبيرات العادية نفسي لذلك أنا أبحث عن بعض المساعدة.

هل كانت مفيدة؟

المحلول

تقسيم ينبغي أن تفعل خدعة.هنا هو وسيلة جيدة لاستخراج البيانات:

>>> line = "$GPRMC,199304.973,3248.7780,N,11355.7832,W,1,06,02.2,25722.5,M,,,*00"
>>> line = line.split(",")
>>> neededData = (float(line[2]), line[3], float(line[4]), line[5], float(line[9]))
>>> print neededData
(3248.7779999999998, 'N', 11355.7832, 'W', 25722.5)

نصائح أخرى

أنها أسهل للاستخدام الانقسام من regex.

>>> line="$GPRMC,092204.999,4250.5589,S,14718.5084,E,1,12,24.4,89.6,M,,,0000*1F "
>>> line.split(',')
['$GPRMC', '092204.999', '4250.5589', 'S', '14718.5084', 'E', '1', '12', '24.4', '89.6', 'M', '', '', '0000*1F ']
>>> 

تلك هي قيم مفصولة بفواصل ، وذلك باستخدام ملف csv المكتبة هو الحل الأسهل.

رميت تلك العينة البيانات لديك في /var/tmp/البيانات النموذجية ، ثم لم هذا:

>>> import csv
>>> for line in csv.reader(open('/var/tmp/sampledata')):
...   print line
['$GPRMC', '092204.999', '**4250.5589', 'S', '14718.5084', 'E**', '1', '12', '24.4', '**89.6**', 'M', '', '', '0000\\*1F']
['$GPRMC', '093345.679', '**4234.7899', 'N', '11344.2567', 'W**', '3', '02', '24.5', '**1000.23**', 'M', '', '', '0000\\*1F']
['$GPRMC', '044584.936', '**1276.5539', 'N', '88734.1543', 'E**', '2', '04', '33.5', '**600.323**', 'M', '', '', '\\*00']
['$GPRMC', '199304.973', '**3248.7780', 'N', '11355.7832', 'W**', '1', '06', '02.2', '**25722.5**', 'M', '', '', '\\*00']
['$GPRMC', '066487.954', '**4572.0089', 'S', '45572.3345', 'W**', '3', '09', '15.0', '**35000.00**', 'M', '', '', '\\*1F']

يمكنك ثم معالجة البيانات ومع ذلك كنت ترغب في ذلك.يبدو من الغريب قليلا مع '**' في بداية ونهاية بعض القيم قد ترغب في غزة أن الأشياء يمكنك القيام به:

>> eastwest = 'E**'
>> eastwest = eastwest.strip('*')
>> print eastwest
E

عليك أن يلقي بعض القيم كما يطفو.لذلك على سبيل المثال ، 3 القيمة في السطر الأول من بيانات العينة هو:

>> data = '**4250.5589'
>> print float(data.strip('*'))
4250.5589

كما يجب أولا التحقق من المجموع الاختباري من البيانات.ويتم حسابه عن طريق XORing الشخصيات بين $ و * (لا بما في ذلك لهم) و مقارنتها عرافة القيمة في نهاية المطاف.

الخاص بك pastebin يبدو أنه لديه بعض الفاسدين الخطوط في ذلك.هنا هو فحص بسيط ، فإنه يفترض أن الخط يبدأ من $ و لا CR/LF في نهاية المطاف.لبناء أكثر قوة محلل تحتاج إلى البحث عن '$' والعمل من خلال سلسلة حتى ضرب '*'.

def check_nmea0183(s):
    """
    Check a string to see if it is a valid NMEA 0183 sentence
    """
    if s[0] != '$':
        return False
    if s[-3] != '*':
        return False

    checksum = 0
    for c in s[1:-3]:
        checksum ^= ord(c)

    if int(s[-2:],16) != checksum:
        return False

    return True

يمكنك استخدام مكتبة مثل pynmea2 من أجل تحليل سجل نميا.

>>> import pynmea2
>>> msg = pynmea2.parse('$GPGGA,142927.829,2831.4705,N,08041.0067,W,1,07,1.0,7.9,M,-31.2,M,0.0,0000*4F')
>>> msg.timestamp, msg.latitude, msg.longitude, msg.altitude
(datetime.time(14, 29, 27), 28.524508333333333, -80.683445, 7.9)

تنويه:أنا صاحب pynmea2

إذا كنت بحاجة إلى القيام ببعض أكثر اتساعا تحليل بيانات نظام تحديد المواقع تيارات هنا هو pyparsing الحل الذي يكسر البيانات الخاصة بك في اسمه حقول البيانات.أنا المستخرج الخاص بك pastebin'ned البيانات إلى ملف gpsstream.txt و تحليل ذلك بما يلي:

"""
 Parse NMEA 0183 codes for GPS data
 http://en.wikipedia.org/wiki/NMEA_0183

 (data formats from http://www.gpsinformation.org/dale/nmea.htm)
"""
from pyparsing import *

lead = "$"
code = Word(alphas.upper(),exact=5)
end = "*"
COMMA = Suppress(',')
cksum = Word(hexnums,exact=2).setParseAction(lambda t:int(t[0],16))

# define basic data value forms, and attach conversion actions
word = Word(alphanums)
N,S,E,W = map(Keyword,"NSEW")
integer = Regex(r"-?\d+").setParseAction(lambda t:int(t[0]))
real = Regex(r"-?\d+\.\d*").setParseAction(lambda t:float(t[0]))
timestamp = Regex(r"\d{2}\d{2}\d{2}\.\d+")
timestamp.setParseAction(lambda t: t[0][:2]+':'+t[0][2:4]+':'+t[0][4:])
def lonlatConversion(t):
    t["deg"] = int(t.deg)
    t["min"] = float(t.min)
    t["value"] = ((t.deg + t.min/60.0) 
                    * {'N':1,'S':-1,'':1}[t.ns] 
                    * {'E':1,'W':-1,'':1}[t.ew])
lat = Regex(r"(?P<deg>\d{2})(?P<min>\d{2}\.\d+),(?P<ns>[NS])").setParseAction(lonlatConversion)
lon = Regex(r"(?P<deg>\d{3})(?P<min>\d{2}\.\d+),(?P<ew>[EW])").setParseAction(lonlatConversion)

# define expression for a complete data record
value = timestamp | Group(lon) | Group(lat) | real | integer | N | S | E | W | word
item = lead + code("code") + COMMA + delimitedList(Optional(value,None))("datafields") + end + cksum("cksum")


def parseGGA(tokens):
    keys = "time lat lon qual numsats horiz_dilut alt _ geoid_ht _ last_update_secs stnid".split()
    for k,v in zip(keys, tokens.datafields):
        if k != '_':
            tokens[k] = v
    #~ print tokens.dump()

def parseGSA(tokens):
    keys = "auto_manual _3dfix prn prn prn prn prn prn prn prn prn prn prn prn pdop hdop vdop".split()
    tokens["prn"] = []
    for k,v in zip(keys, tokens.datafields):
        if k != 'prn':
            tokens[k] = v
        else:
            if v is not None:
                tokens[k].append(v)
    #~ print tokens.dump()

def parseRMC(tokens):
    keys = "time active_void lat lon speed track_angle date mag_var _ signal_integrity".split()
    for k,v in zip(keys, tokens.datafields):
        if k != '_':
            if k == 'date' and v is not None:
                v = "%06d" % v
                tokens[k] = '20%s/%s/%s' % (v[4:],v[2:4],v[:2])
            else:
                tokens[k] = v
    #~ print tokens.dump()


# process sample data
data = open("gpsstream.txt").read().expandtabs()

count = 0
for i,s,e in item.scanString(data):
    # use checksum to validate input 
    linebody = data[s+1:e-3]
    checksum = reduce(lambda a,b:a^b, map(ord, linebody))
    if i.cksum != checksum:
        continue
    count += 1

    # parse out specific data fields, depending on code field
    fn = {'GPGGA' : parseGGA, 
          'GPGSA' : parseGSA,
          'GPRMC' : parseRMC,}[i.code]
    fn(i)

    # print out time/position/speed values
    if i.code == 'GPRMC':
        print "%s %8.3f %8.3f %4d" % (i.time, i.lat.value, i.lon.value, i.speed or 0) 


print count

دولار GPRMC السجلات في pastebin لا يبدو أن تتطابق تماما مع تلك التي شملت في ما بعد ، ولكن يجب أن تكون قادرة على ضبط هذا المثال عند الضرورة.

أقترح صغيرة الإصلاح في التعليمات البرمجية الخاصة بك لأنه إذا المستخدمة في تحليل البيانات من القرن الماضي تاريخ يبدو في وقت ما في المستقبل (على سبيل المثال 2094 بدلا من 1994)

بلدي الإصلاح ليست دقيقة تماما ، ولكن أن أقف أنه قبل 70 لا يوجد بيانات GPS موجودة.

في مواطنه تحليل وظيفة RMC الجمل مجرد استبدال شكل الخط:

p = int(v[4:])
print "p = ", p
if p > 70:
    tokens[k] = '19%s/%s/%s' % (v[4:],v[2:4],v[:2])
else:
    tokens[k] = '20%s/%s/%s' % (v[4:],v[2:4],v[:2])

هذا سوف ننظر في اثنين من yy أرقام السنة و نفترض أن العام الماضي 70 أننا نتعامل مع الجمل من القرن الماضي.يمكن أن يكون من الأفضل القيام بمقارنة إلى تاريخ اليوم و على افتراض أن كل مرة كنت تتعامل مع بعض البيانات في المستقبل ، فهي في الواقع من القرن الماضي

شكرا على كل قطعة من التعليمات البرمجية الخاصة بك المقدمة أعلاه...لدي بعض المتعة مع هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top