MAVLink และการวิเคราะห์แพ็กเก็ต
UAT 207 ระบบสื่อสารและเครือข่ายข้อมูล
บทเรียน
เมื่อเรียนจบโมดูลนี้ ผู้เรียนจะสามารถ
- คำนวณอัตราแพ็กเก็ตหายจากลำดับแพ็กเก็ต MAVLink ที่วนกลับหลัง 255
- แยกเฟรม MAVLink 2 จากสตรีมไบต์และตรวจ CRC ด้วย CRC_EXTRA
- ติดตั้งเส้นทางข้อมูล SITL, MAVProxy, GCS และ Wireshark เพื่อวิเคราะห์ข้อความ
- แยกอัตราแพ็กเก็ตที่เห็นในเครือข่ายออกจากความสดของข้อมูลในแอปพลิเคชัน
ทำไมต้องรู้
เมื่อ telemetry กระตุก คำถามแรกคือแพ็กเก็ตหายจริงหรือแค่ช้า และหายที่ส่วนใดของเส้นทาง MAVLink ใส่ข้อมูลช่วยตอบคำถามนี้ไว้ในทุกเฟรม คือ ลำดับแพ็กเก็ต (sequence number) และ CRC โมดูลนี้สอนการใช้ข้อมูลเหล่านี้วิเคราะห์ลิงก์ ต่อจาก UAT 104 ที่อ่านข้อความด้วย pymavlink
ลำดับแพ็กเก็ตที่วนกลับ
คู่มือ MAVLink ระบุว่าลำดับแพ็กเก็ตเป็น uint8 มีค่า 0–255 ผู้ส่งเพิ่มค่าทุกข้อความ และใช้ตรวจการหายของแพ็กเก็ต เมื่อถึง 255 ข้อความถัดไปจะเป็น 0 การนับที่ถูกต้องจึงต้องใช้เลขคณิตมอดุโล 256 ถ้าลบตรง ๆ จะเห็น 255 → 0 เป็นการหาย 255 แพ็กเก็ต
ตัวอย่างที่ 1 อัตราแพ็กเก็ตหายจากลำดับ
ลำดับที่สถานีรับได้จากโดรนหนึ่งตัว (system 1, component 1) ในช่วงหนึ่ง
seqs = [250, 251, 252, 253, 254, 255, 0, 1, 3, 4, 5, 9, 10, 11, 12, 13]
lost = 0
for prev, cur in zip(seqs, seqs[1:]):
gap = (cur - prev - 1) % 256
if gap:
print(f"after {prev:>3} came {cur:>3}: {gap} packet(s) lost")
lost += gap
naive = sum(max(cur - prev - 1, 0) + (255 if cur < prev else 0) for prev, cur in zip(seqs, seqs[1:]))
print(f"received {len(seqs)}, lost {lost}, loss rate {lost / (lost + len(seqs)):.1%}")
print(f"(a naive count that ignores the wrap would report {naive} lost)")
after 1 came 3: 1 packet(s) lost
after 5 came 9: 3 packet(s) lost
received 16, lost 4, loss rate 20.0%
(a naive count that ignores the wrap would report 259 lost)
ต้องแยกนับตามผู้ส่งแต่ละราย (system ID และ component ID) เพราะแต่ละรายมีลำดับของตัวเอง ถ้าเครื่องมือเช่น MAVProxy รวมหลายผู้ส่งไว้ด้วยกัน อัตราที่คำนวณจะผิด
แยกเฟรมจากสตรีมไบต์
วิทยุแบบอนุกรมส่งไบต์ต่อกันโดยไม่มีขอบเขตของเฟรม ตัวรับต้องหาไบต์เริ่ม 0xFD ของ MAVLink 2 อ่านความยาว แล้วตรวจ CRC ซึ่งคำนวณจากส่วนหัว (ยกเว้นไบต์เริ่ม) ข้อมูล และ CRC_EXTRA ประจำชนิดข้อความ ค่านี้ได้จากนิยามของข้อความ เช่น HEARTBEAT = 50 และ ATTITUDE = 39 ถ้าผู้ส่งและผู้รับใช้นิยามข้อความต่างรุ่นกัน CRC จะไม่ผ่าน จึงช่วยจับความไม่เข้ากันได้ด้วย
ตัวอย่างที่ 2 แยกเฟรมและจับเฟรมเสีย
สร้างสตรีมจากสี่เฟรม มีไบต์ขยะคั่น และทำให้ไบต์หนึ่งของเฟรมที่สามผิด ผู้สอนตรวจแล้วว่า pymavlink 2.4.50 อ่านเฟรมที่สร้างนี้ได้ถูกต้อง
import struct
def crc_x25(data, crc=0xFFFF):
for b in data:
tmp = b ^ (crc & 0xFF)
tmp = (tmp ^ (tmp << 4)) & 0xFF
crc = ((crc >> 8) ^ (tmp << 8) ^ (tmp << 3) ^ (tmp >> 4)) & 0xFFFF
return crc
CRC_EXTRA = {0: 50, 30: 39} # HEARTBEAT, ATTITUDE
NAMES = {0: "HEARTBEAT", 30: "ATTITUDE"}
def frame(seq, msgid, payload):
hdr = bytes([0xFD, len(payload), 0, 0, seq, 1, 1]) + msgid.to_bytes(3, "little")
crc = crc_x25(hdr[1:] + payload + bytes([CRC_EXTRA[msgid]]))
return hdr + payload + struct.pack("<H", crc)
hb = struct.pack("<IBBBBB", 0, 2, 3, 0x81, 4, 3)
att = struct.pack("<Iffffff", 12000, 0.05, -0.02, 1.57, 0.01, 0.0, 0.02)
stream = bytearray(b"\x00\x13" + frame(10, 0, hb) + frame(11, 30, att) + b"\x55" + frame(12, 30, att) + frame(13, 0, hb))
bad_at = stream.index(bytes([0xFD, 28, 0, 0, 12])) + 15
stream[bad_at] ^= 0xFF # ทำให้ข้อมูลของเฟรมลำดับ 12 เสีย
i, good, bad = 0, {}, 0
while i < len(stream):
if stream[i] != 0xFD or i + 12 > len(stream):
i += 1
continue
n = stream[i + 1]
fr = stream[i:i + 12 + n]
msgid = int.from_bytes(fr[7:10], "little")
crc = struct.unpack("<H", fr[10 + n:12 + n])[0]
if msgid in CRC_EXTRA and crc_x25(fr[1:10 + n] + bytes([CRC_EXTRA[msgid]])) == crc:
good[NAMES[msgid]] = good.get(NAMES[msgid], 0) + 1
print(f"seq {fr[4]:>3}: {NAMES[msgid]:<9} ok")
i += 12 + n
else:
bad += 1
print(f"seq {fr[4]:>3}: CRC failed, resync")
i += 1
print("good frames:", good, "| bad frames:", bad)
seq 10: HEARTBEAT ok
seq 11: ATTITUDE ok
seq 12: CRC failed, resync
seq 13: HEARTBEAT ok
good frames: {'HEARTBEAT': 2, 'ATTITUDE': 1} | bad frames: 1
เมื่อ CRC ไม่ผ่าน ตัวรับเลื่อนไปทีละไบต์เพื่อหาไบต์เริ่มใหม่ ไบต์ขยะจึงไม่ทำให้เฟรมถัดไปเสีย และเฟรมที่เสียถูกทิ้งแทนที่จะส่งค่าผิดให้แอปพลิเคชัน
วิเคราะห์ในเครื่องจำลอง
ปฏิบัติการ L09 ของคลังความรู้โดรนให้เชื่อม SITL กับ MAVProxy แล้วส่งต่อไปยัง GCS และสคริปต์ Python ขณะใช้ Wireshark จับแพ็กเก็ตบน loopback เพื่อเทียบอัตราแพ็กเก็ตในเครือข่ายกับอัตราที่แอปพลิเคชันอ่านได้ หน่วยความรู้ย้ำว่า อัตราแพ็กเก็ตไม่เท่ากับความสดของข้อมูล ข้อความอาจมาถี่แต่ค่าข้างในค้างอยู่ก็ได้
ปฏิบัติการประจำโมดูล
ปฏิบัติการ: จับและวิเคราะห์ MAVLink (L09)
- เปิด SITL และ MAVProxy บันทึก endpoint, port และ system ID ที่ใช้
- เขียนสคริปต์ pymavlink อ่าน ATTITUDE และเก็บลำดับแพ็กเก็ตกับเวลาลง CSV
- ใช้โค้ดตัวอย่างที่ 1 คำนวณอัตราแพ็กเก็ตหาย แยกตามผู้ส่ง
- จับแพ็กเก็ต loopback ด้วย Wireshark เทียบอัตราแพ็กเก็ตกับอัตราที่สคริปต์อ่านได้
- บันทึกไบต์ดิบจากพอร์ตอนุกรมของวิทยุ (ถ้ามี) แล้วใช้ตัวอย่างที่ 2 นับเฟรมเสีย
ข้อผิดพลาดที่พบบ่อย
ระวัง
- ลบลำดับตรง ๆ โดยไม่คิดการวนกลับ
- รวมหลายผู้ส่งเป็นลำดับเดียว
- ใช้นิยามข้อความต่างรุ่นกัน จน CRC ไม่ผ่าน
- ถือว่าอัตราแพ็กเก็ตคือความสดของข้อมูล
- เปิดพอร์ตควบคุมออกสู่อินเทอร์เน็ต ระหว่างทดลอง
สรุป
- ลำดับแพ็กเก็ต MAVLink เป็น uint8 ต้องนับการหายด้วยมอดุโล 256 แยกตามผู้ส่ง
- CRC ของ MAVLink รวม CRC_EXTRA ประจำชนิดข้อความ จึงจับทั้งข้อมูลเสียและนิยามไม่ตรงกัน
- ตัวรับหาไบต์เริ่มใหม่เมื่อเฟรมเสีย
- เทียบข้อมูลจาก Wireshark กับแอปพลิเคชัน และแยกอัตราแพ็กเก็ตออกจากความสดของข้อมูล
แบบฝึกตรวจความเข้าใจ
- ลำดับ 254 ตามด้วย 2 หายกี่แพ็กเก็ต
- รับได้ 95 แพ็กเก็ต หาย 5 แพ็กเก็ต อัตราหายเท่าใด
- CRC_EXTRA ใช้ทำอะไร
- ทำไมต้องแยกนับลำดับตามผู้ส่ง
- ข้อความมาถี่ 10 Hz แต่ค่าตำแหน่งไม่เปลี่ยนเลย บอกอะไร
เฉลย
- แพ็กเก็ต (255, 0, 1)
- เพิ่มค่าประจำชนิดข้อความเข้าไปใน CRC เพื่อตรวจว่าผู้ส่งและผู้รับใช้นิยามข้อความเดียวกัน
- แต่ละผู้ส่งมีลำดับของตัวเอง ถ้ารวมกันจะดูเหมือนหายหรือซ้ำผิด
- ข้อมูลอาจค้าง เช่น เซนเซอร์หรือตัวประมาณค่าหยุดอัปเดต แม้ลิงก์ยังทำงาน
สรุปสูตรสำคัญ
| แพ็กเก็ตที่หายระหว่างสองลำดับ | |
| อัตราแพ็กเก็ตหาย |
แหล่งอ้างอิงหลัก
- MAVLink Development Team. Packet serialization. MAVLink developer guide. link
- MAVLink Development Team. MAVLink developer guide. link
- ArduPilot and MAVLink contributors. (2026). pymavlink (Version 2.4.50) [Computer software]. PyPI. link
- Kurose, J. F., & Ross, K. W. (2025). Computer networking: A top-down approach (9th ed.). Pearson. link
อ่านเพิ่มเติม
ศึกษาหน่วยความรู้ที่กำหนดล่วงหน้า ดูสื่อประกอบ และทำ quiz ประจำโมดูล
อ่าน MAVLink telemetry จาก SITL
MAVProxy + MAVExplorer
Wireshark
ในชั้นเรียน / ภาคสนาม
ปฏิบัติการในห้องแล็บหรือภาคสนามตามใบงาน พร้อม checklist ความปลอดภัย
หลักฐานการเรียนรู้: ใบงานที่ผ่านการตรวจและผล quiz