การประมาณสถานะและ EKF
UAT 305 เทคโนโลยีออโตไพลอตและระบบควบคุม
บทเรียน
เมื่อเรียนจบโมดูลนี้ ผู้เรียนจะสามารถ
- อธิบายขั้นทำนายและขั้นปรับแก้ของ Kalman filter
- เขียน Kalman filter หาความสูงจากแอกเซเลอโรมิเตอร์ร่วมกับบารอมิเตอร์
- คำนวณอัตราส่วนทดสอบ (test ratio) ของ innovation และตัดสินว่าข้อมูลถูกใช้หรือถูกปฏิเสธ
- อ่านค่าความสอดคล้องของ EKF3 ใน log ของ ArduPilot
ทำไมต้องรู้
ออโตไพลอตไม่รู้ตำแหน่งและท่าทางของตัวเองโดยตรง แต่ ประมาณ จากเซนเซอร์หลายตัวที่แต่ละตัวมีจุดอ่อน แอกเซเลอโรมิเตอร์ตอบเร็วแต่ถ้าอินทิเกรตนานจะลอยเพราะ bias บารอมิเตอร์ไม่ลอยแต่มีสัญญาณรบกวนมาก GNSS แม่นระยะยาวแต่อัปเดตช้าและหายได้ ตัวกรองคาลมานรวมจุดแข็งของทุกตัว หน่วยความรู้เรื่องการประมาณสถานะด้วย Kalman filter และ EKF ของคลังความรู้โดรนครอบคลุมการรวม IMU GNSS และบารอมิเตอร์ และการวินิจฉัย EKF ส่วนตำรา Groves อธิบายการนำทางแบบรวมหลายเซนเซอร์ละเอียด
Kalman filter สองขั้น
ตามบทนำของ Welch และ Bishop ตัวกรองคาลมานทำสองขั้นซ้ำกัน ขั้นทำนาย ใช้แบบจำลองและอินพุต (เช่น ความเร่งที่วัดได้) คาดสถานะถัดไป พร้อมความไม่แน่นอน ที่โตขึ้นตามสัญญาณรบกวนของกระบวนการ ขั้นปรับแก้ เทียบค่าที่วัดได้ กับที่คาด ส่วนต่างเรียกว่า innovation แล้วปรับสถานะด้วยอัตราขยายคาลมาน ซึ่งชั่งน้ำหนักระหว่างความไม่แน่นอนของการทำนายกับของการวัด EKF (extended Kalman filter) ใช้หลักเดียวกันกับแบบจำลองไม่เป็นเชิงเส้น โดยประมาณเป็นเชิงเส้นรอบสถานะปัจจุบัน
ตัวอย่างที่ 1 ความสูงจากแอกเซเลอโรมิเตอร์และบารอมิเตอร์
จำลองโดรนลอยตัว แล้วไต่ระดับ 4 m ช่วงวินาทีที่ 5–9 แอกเซเลอโรมิเตอร์มี bias 0.05 m/s² และสัญญาณรบกวน 0.3 m/s² บารอมิเตอร์มีสัญญาณรบกวน 0.5 m (ข้อมูลจำลอง)
import numpy as np
rng = np.random.default_rng(3)
dt, T = 0.01, 30.0
n = int(T / dt)
t = np.arange(n) * dt
true_a = np.where((t > 5) & (t < 7), 1.0, 0.0) - np.where((t > 7) & (t < 9), 1.0, 0.0)
true_v = np.cumsum(true_a) * dt
true_h = np.cumsum(true_v) * dt
acc = true_a + 0.05 + rng.normal(0, 0.3, n) # m/s² มี bias
baro = true_h + rng.normal(0, 0.5, n) # m
A = np.array([[1, dt], [0, 1]]) # สถานะ [ความสูง, ความเร็ว]
B = np.array([0.5 * dt * dt, dt])
H = np.array([[1.0, 0.0]])
Q = np.diag([1e-5, 1e-3])
R = np.array([[0.25]])
x, P, est = np.zeros(2), np.eye(2), []
for k in range(n):
x = A @ x + B * acc[k] # ทำนาย
P = A @ P @ A.T + Q
S = H @ P @ H.T + R # ปรับแก้
K = P @ H.T @ np.linalg.inv(S)
x = x + (K @ (baro[k] - H @ x)).ravel()
P = (np.eye(2) - K @ H) @ P
est.append(x[0])
rms = lambda e: float(np.sqrt(np.mean(e ** 2)))
drift = (np.cumsum(np.cumsum(acc) * dt) * dt)[-1] - true_h[-1]
print(f"true height at end {true_h[-1]:.2f} m")
print(f"accelerometer only: error at end {drift:.1f} m")
print(f"barometer only: RMS error {rms(baro - true_h):.2f} m")
print(f"Kalman filter: RMS error {rms(np.array(est) - true_h):.2f} m")
true height at end 3.98 m
accelerometer only: error at end 26.7 m
barometer only: RMS error 0.50 m
Kalman filter: RMS error 0.08 m
แอกเซเลอโรมิเตอร์อย่างเดียวลอยไปหลายสิบเมตรใน 30 วินาทีเพราะ bias เล็ก ๆ ถูกอินทิเกรตสองครั้ง บารอมิเตอร์อย่างเดียวสั่นราวครึ่งเมตร ตัวกรองคาลมานได้ความคลาดเคลื่อนน้อยกว่าทั้งสองแหล่งหลายเท่า เพราะใช้ความเร่งตามการเปลี่ยนแปลงระยะสั้น และใช้บารอมิเตอร์ดึงค่ากลับในระยะยาว
ทดสอบ innovation ก่อนใช้ข้อมูล
EKF3 ของ ArduPilot ไม่ใช้ค่าที่วัดได้ทุกค่า ก่อนปรับแก้ มันตรวจว่า innovation ใหญ่เกินที่ความไม่แน่นอนรองรับหรือไม่ ในซอร์สโค้ดรุ่น 4.6.3 อัตราส่วนทดสอบคือ innovation กำลังสอง หารด้วยความแปรปรวนของ innovation คูณ (gate/100)² ค่านี้ต้องน้อยกว่า 1 ข้อมูลจึงถูกใช้ ค่า gate ตั้งด้วย EK3_POS_I_GATE, EK3_VEL_I_GATE, EK3_HGT_I_GATE (ค่าเริ่มต้น 500 คือ 5 เท่าของส่วนเบี่ยงเบนมาตรฐาน) และ EK3_MAG_I_GATE (ค่าเริ่มต้น 300) ข้อความ XKF4 ใน log บันทึก รากที่สอง ของอัตราส่วนนี้ในช่อง SV SP SH SM ดังนั้นค่าเกิน 1 แปลว่าข้อมูลนั้นถูกปฏิเสธ ส่วน XKF3 บันทึกค่า innovation เอง
ตัวอย่างที่ 2 ตำแหน่ง GNSS ค่าใดถูกปฏิเสธ
ความแปรปรวนของ innovation ของตำแหน่ง 4 m² (ส่วนเบี่ยงเบนมาตรฐาน 2 m) gate 500 (ข้อมูลจำลอง)
import math
GATE, S = 500, 4.0 # EK3_POS_I_GATE, m²
innovations = [0.8, -1.5, 3.9, 9.2, 12.0] # m
for nu in innovations:
ratio = nu ** 2 / (S * (GATE / 100) ** 2)
logged = math.sqrt(ratio) # ค่าที่เห็นใน XKF4.SP
print(f"innovation {nu:+5.1f} m: test ratio {ratio:.3f}, logged {logged:.2f} -> {'used' if ratio < 1 else 'REJECTED'}")
print(f"largest accepted innovation: {GATE / 100 * math.sqrt(S):.1f} m")
innovation +0.8 m: test ratio 0.006, logged 0.08 -> used
innovation -1.5 m: test ratio 0.022, logged 0.15 -> used
innovation +3.9 m: test ratio 0.152, logged 0.39 -> used
innovation +9.2 m: test ratio 0.846, logged 0.92 -> used
innovation +12.0 m: test ratio 1.440, logged 1.20 -> REJECTED
largest accepted innovation: 10.0 m
ค่าที่ห่างจากที่คาดเกิน 5 เท่าของส่วนเบี่ยงเบนมาตรฐานถูกปฏิเสธ ซึ่งปกป้อง EKF จากค่า GNSS ที่กระโดดเพราะสัญญาณสะท้อน แต่ถ้าถูกปฏิเสธต่อเนื่องนาน EKF จะลอยตามแอกเซเลอโรมิเตอร์และอาจรีเซ็ตไปใช้ค่า GNSS ใหม่ การขยาย gate ให้กว้างเพื่อ “ไม่ให้เตือน” จึงไม่ใช่วิธีแก้ ต้องหาสาเหตุที่ค่าไม่สอดคล้อง
ปฏิบัติการประจำโมดูล
ปฏิบัติการ: อ่านสุขภาพของ EKF
- ปรับค่า และ ในตัวอย่างที่ 1 สังเกตว่าตัวกรองเชื่อบารอมิเตอร์หรือแอกเซเลอโรมิเตอร์มากขึ้นเมื่อใด
- เปิด log จาก SITL ดูช่อง SV SP SH SM ของ XKF4 ตลอดเที่ยวบิน
- จำลอง GPS glitch ใน SITL แล้วดูว่าค่า SP เกิน 1 เมื่อใดและ EKF ทำอย่างไร
- คำนวณค่าที่ใหญ่ที่สุดที่ถูกใช้ด้วยตัวอย่างที่ 2 จากค่าความแปรปรวนใน log
- เขียนสรุปวิธีอ่านสุขภาพ EKF สำหรับทีมภาคสนาม
ข้อผิดพลาดที่พบบ่อย
ระวัง
- เชื่อว่าค่าจากเซนเซอร์เดียวคือความจริง
- ขยาย gate ให้กว้าง เพื่อปิดคำเตือน
- อ่านค่าใน XKF4 เป็นความแปรปรวน ทั้งที่เป็นรากที่สองของอัตราส่วนทดสอบ
- ตั้ง ของเซนเซอร์เล็กเกินจริง จนตัวกรองไล่ตามสัญญาณรบกวน
- มองข้ามการสั่น ซึ่งทำให้ค่าความเร่งผิดและ EKF เสียหาย
สรุป
- Kalman filter ทำนายด้วยแบบจำลองและอินพุต แล้วปรับแก้ด้วยค่าวัด โดยชั่งน้ำหนักด้วยความไม่แน่นอน
- การรวมแอกเซเลอโรมิเตอร์กับบารอมิเตอร์ได้ความสูงที่แม่นกว่าแหล่งใดแหล่งหนึ่ง
- EKF3 ใช้ข้อมูลเมื่ออัตราส่วนทดสอบน้อยกว่า 1 gate 500 คือ 5 เท่าของส่วนเบี่ยงเบนมาตรฐาน
- ช่อง SV SP SH SM ของ XKF4 คือรากที่สองของอัตราส่วนทดสอบ ค่าเกิน 1 แปลว่าถูกปฏิเสธ
แบบฝึกตรวจความเข้าใจ
- ทำไมการอินทิเกรตความเร่งอย่างเดียวจึงลอย
- ถ้า ของบารอมิเตอร์เพิ่มขึ้น ตัวกรองจะเชื่อบารอมิเตอร์มากขึ้นหรือน้อยลง
- innovation 6 m ความแปรปรวน 4 m² gate 500 อัตราส่วนทดสอบเท่าใด
- ค่า SP ใน log เท่ากับ 0.6 หมายความว่าอะไร
- ทำไมไม่ควรแก้คำเตือน EKF ด้วยการขยาย gate
เฉลย
- bias เล็ก ๆ ถูกอินทิเกรตสองครั้ง ความคลาดเคลื่อนจึงโตตามเวลากำลังสอง
- น้อยลง
- innovation อยู่ที่ 60% ของขอบ gate ข้อมูลถูกใช้
- ข้อมูลที่ผิดจะถูกใช้และทำให้การประมาณเสีย ต้องหาสาเหตุที่ค่าไม่สอดคล้อง
สรุปสูตรสำคัญ
| ขั้นทำนาย | |
| ขั้นปรับแก้ | |
| อัตราส่วนทดสอบใน EKF3 |
แหล่งอ้างอิงหลัก
- Welch, G., & Bishop, G. (2004). An introduction to the Kalman filter (TR 95-041). University of North Carolina at Chapel Hill. link
- Groves, P. D. (2013). Principles of GNSS, inertial, and multisensor integrated navigation systems (2nd ed.). Artech House. link
- ArduPilot Dev Team. Extended Kalman filter (EKF) overview. ArduPilot Copter documentation. link
- ArduPilot Dev Team. Onboard message log messages. ArduPilot Copter documentation. link
- ArduPilot Dev Team. ArduPilot source code, tag Copter-4.6.3 [Computer software]. GitHub. link
- PX4 Autopilot. Using the ECL EKF. PX4 user guide (main). link
อ่านเพิ่มเติม
ศึกษาหน่วยความรู้ที่กำหนดล่วงหน้า ดูสื่อประกอบ และทำ quiz ประจำโมดูล
ในชั้นเรียน / ภาคสนาม
ปฏิบัติการในห้องแล็บหรือภาคสนามตามใบงาน พร้อม checklist ความปลอดภัย
หลักฐานการเรียนรู้: ใบงานที่ผ่านการตรวจและผล quiz