โมดูล 1/5 · สัปดาห์ 1–3 · 27 ชม.

สถาปัตยกรรมออโตไพลอต

UAT 305 เทคโนโลยีออโตไพลอตและระบบควบคุม

เวลาเรียนประมาณ 85 นาทีร่าง รอตรวจปรับปรุงล่าสุด 28 กันยายน 2569

บทเรียน

เมื่อเรียนจบโมดูลนี้ ผู้เรียนจะสามารถ

  1. อธิบายโครงสร้างซอฟต์แวร์ของ ArduPilot และ PX4 ตั้งแต่เซนเซอร์ถึงมอเตอร์
  2. คำนวณภาระของตัวจัดลำดับงาน (scheduler) จากอัตราและเวลาของแต่ละงาน
  3. คำนวณมุมเฟสที่เสียไปจากเวลาหน่วงในลูปควบคุม
  4. อ่านพารามิเตอร์ที่กำหนดอัตราลูปของออโตไพลอตทั้งสองระบบ

ความรู้พื้นฐานที่ควรมี: UAT 206 (ระบบควบคุมและออโตไพลอตเบื้องต้น) · UAT 204 (RTOS)

ทำไมต้องรู้

UAT 206 สอนว่าออโตไพลอตควบคุมเป็นชั้นและโหมดการบินใช้ลูปใด วิชานี้มองลึกลงไปว่า ซอฟต์แวร์ทำงานอย่างไรในเวลาจริง เพราะปัญหาการบินหลายอย่างไม่ได้มาจากค่าจูนผิด แต่มาจากลูปทำงานไม่ทันหรือมีเวลาหน่วงมากเกินไป หน่วยความรู้เรื่องสถาปัตยกรรม PX4 และ ArduPilot ของคลังความรู้โดรนครอบคลุมโครงสร้างซอฟต์แวร์ พารามิเตอร์ โหมดการบิน failsafe และ geofence ตัวเลขในโมดูลนี้อ้างรุ่นเฟิร์มแวร์ ArduPilot Copter 4.6.3 ถ้าใช้รุ่นอื่นต้องตรวจชื่อและค่าเริ่มต้นใหม่

จากเซนเซอร์ถึงมอเตอร์

ArduPilot ทำงานเป็นวงรอบหลัก (main loop) อัตรา SCHED_LOOP_RATE ซึ่งค่าเริ่มต้นของ Copter คือ 400 Hz (ช่วงที่ตั้งได้ 50–400 Hz) ในแต่ละรอบ งานเร่งด่วน (FAST_TASK) เช่น ตัวควบคุมอัตราหมุนและการส่งค่าไปมอเตอร์ทำทุกรอบ ส่วนงานอื่นอยู่ในตารางงานของตัวจัดลำดับงาน แต่ละงานระบุอัตรา (Hz) เวลาที่คาดว่าจะใช้ (ไมโครวินาที) และลำดับความสำคัญ เช่น rc_loop 250 Hz 130 µs fence_check 25 Hz 100 µs และ ekf_check 10 Hz 75 µs ตามซอร์สโค้ดของรุ่น 4.6.3

PX4 แยกซอฟต์แวร์เป็นโมดูลที่สื่อสารกันผ่าน uORB ซึ่งเป็นระบบส่งข้อความแบบ publish/subscribe ระหว่างเธรด ตัวควบคุมอัตราหมุนทำงานที่อัตราที่ gyro เผยแพร่ข้อมูล กำหนดด้วย IMU_GYRO_RATEMAX ค่าเริ่มต้น 400 Hz ขณะที่ข้อมูลดิบของเซนเซอร์อาจอ่านและกรองที่อัตราสูงกว่านั้นมาก

ห้ากล่องเรียงจากซ้ายไปขวา IMU กรองสัญญาณ ประมาณสถานะ EKF ตัวควบคุม และมอเตอร์ ใต้แต่ละช่วงมีป้ายเวลาหน่วยมิลลิวินาที รวมกันเป็นเวลาหน่วงทั้งลูป
ภาพที่ 1 เส้นทางข้อมูลจากเซนเซอร์ถึงมอเตอร์และเวลาหน่วง

ตัวอย่างที่ 1 ภาระของตัวจัดลำดับงาน

ใช้งานสามอย่างจากตารางของ Copter 4.6.3 กับเวลาของลูปเร่งด่วนที่วัดได้จากบอร์ดหนึ่ง (ค่าสมมติ 700 µs) ตารางจริงมีงานมากกว่านี้มาก ตัวอย่างนี้ใช้เพื่อฝึกคิด

LOOP_HZ = 400
tasks = {   # งาน: (อัตรา Hz, เวลาที่คาด µs)
    "fast loop (rate ctrl + motors)": (400, 700),
    "rc_loop": (250, 130),
    "fence_check": (25, 100),
    "ekf_check": (10, 75),
}
period_us = 1e6 / LOOP_HZ
load = 0.0
for name, (hz, us) in tasks.items():
    share = hz * us / 1e6
    load += share
    print(f"{name:<31} {hz:>3} Hz x {us:>3} us = {share:6.1%} of CPU time")
print(f"loop period {period_us:.0f} us, total load of these tasks {load:.1%}")
for hz in (400, 800):
    print(f"if the loop ran at {hz} Hz, the fast loop alone would need {hz * 700 / 1e6:.0%}")
fast loop (rate ctrl + motors)  400 Hz x 700 us =  28.0% of CPU time
rc_loop                         250 Hz x 130 us =   3.2% of CPU time
fence_check                      25 Hz x 100 us =   0.2% of CPU time
ekf_check                        10 Hz x  75 us =   0.1% of CPU time
loop period 2500 us, total load of these tasks 31.6%
if the loop ran at 400 Hz, the fast loop alone would need 28%
if the loop ran at 800 Hz, the fast loop alone would need 56%

งานเพียงไม่กี่อย่างก็ใช้เวลาประมวลผลเกือบหนึ่งในสาม ลูปเร่งด่วนเป็นส่วนใหญ่ เพราะทำทุกรอบ ถ้าเพิ่มอัตราลูปโดยไม่เปลี่ยนบอร์ด เวลาที่เหลือให้งานอื่นจะหายไปเร็วมาก นี่คือเหตุผลที่เอกสารเตือนว่าค่าเกิน 400 Hz ยังเป็นการทดลอง ถ้างานใช้เวลาเกินที่คาด ตัวจัดลำดับงานจะเลื่อนงานความสำคัญต่ำออกไป ซึ่งดูได้จากข้อความประสิทธิภาพใน log

เวลาหน่วงกินมุมเฟส

ทุกขั้นตอนตั้งแต่อ่าน IMU กรองสัญญาณ คำนวณ จนมอเตอร์เปลี่ยนแรงขับใช้เวลา เวลาหน่วงบริสุทธิ์ ไม่ลดขนาดสัญญาณ แต่ทำให้เฟสล้าหลัง เรเดียน (บันทึกประกอบการสอนของ Caltech) หรือ องศาที่ความถี่ มุมเฟสที่เสียไปตรงความถี่ครอสโอเวอร์ของลูปจะลดส่วนเผื่อเฟส (phase margin) ลงตรง ๆ ตามที่เรียนใน UAT 206

ตัวอย่างที่ 2 เวลาหน่วงเท่าใดจึงกินส่วนเผื่อเฟสหมด

ลูปอัตราหมุนมีความถี่ครอสโอเวอร์ 8 Hz และส่วนเผื่อเฟสเมื่อไม่มีเวลาหน่วง 60° (ค่าสมมติ)

F_C, PM0 = 8.0, 60.0                           # Hz, องศา
for tau_ms in (8, 12, 20):
    lag = 360 * F_C * tau_ms / 1000
    print(f"delay {tau_ms:>2} ms: phase lag {lag:5.1f} deg, remaining margin {PM0 - lag:5.1f} deg")
tau_zero = PM0 / (360 * F_C) * 1000
print(f"delay that removes all margin: {tau_zero:.1f} ms")
delay  8 ms: phase lag  23.0 deg, remaining margin  37.0 deg
delay 12 ms: phase lag  34.6 deg, remaining margin  25.4 deg
delay 20 ms: phase lag  57.6 deg, remaining margin   2.4 deg
delay that removes all margin: 20.8 ms

เวลาหน่วงเพียง 20 ms ทำให้ส่วนเผื่อเฟสเหลือน้อยมากจนลูปแกว่ง ตัวกรองสัญญาณที่ตั้งความถี่ตัดต่ำเกินไป ลูปที่ทำงานช้า หรือ ESC ที่ตอบสนองช้า ล้วนเพิ่มเวลาหน่วง การลดเวลาหน่วงจึงช่วยให้จูนค่าได้แรงขึ้นโดยไม่แกว่ง

กราฟเส้นตรงของมุมเฟสที่เสียตามเวลาหน่วง 0 ถึง 25 มิลลิวินาทีที่ 8 เฮิรตซ์ เส้นประสีชมพูแนวนอนที่ 60 องศาคือส่วนเผื่อเฟสเดิม ตัดกันที่ประมาณ 20.8 มิลลิวินาที
ภาพที่ 2 มุมเฟสที่เสียตามเวลาหน่วงที่ความถี่ครอสโอเวอร์ 8 Hz

ปฏิบัติการประจำโมดูล

ปฏิบัติการ: สำรวจเวลาในออโตไพลอต

  1. เปิดซอร์สโค้ด ArduCopter/Copter.cpp ของรุ่นที่ใช้ อ่านตาราง scheduler_tasks เลือกงาน 10 อย่างมาคำนวณภาระด้วยตัวอย่างที่ 1
  2. รัน SITL แล้วดูข้อความประสิทธิภาพ (PM) ใน log เทียบเวลาลูปจริงกับที่คาด
  3. เปลี่ยน SCHED_LOOP_RATE ใน SITL แล้วสังเกตผล จากนั้นคืนค่าเดิม
  4. ประมาณเวลาหน่วงรวมของลูปจากขั้นตอนในภาพที่ 1 และคำนวณมุมเฟสที่เสียด้วยตัวอย่างที่ 2
  5. เปรียบเทียบกับโครงสร้างของ PX4 จากเอกสาร uORB และแผนภาพตัวควบคุม

ข้อผิดพลาดที่พบบ่อย

ระวัง

  • เพิ่มอัตราลูปเกินขีดของบอร์ด โดยไม่ดูภาระของตัวจัดลำดับงาน
  • ตั้งตัวกรองต่ำมากเพื่อลดสัญญาณรบกวน โดยลืมว่าเพิ่มเวลาหน่วง
  • ใช้ค่าเริ่มต้นจากเฟิร์มแวร์รุ่นอื่น
  • มองว่าเวลาหน่วงเล็กน้อยไม่สำคัญ
  • สรุปว่าค่าจูนผิด ทั้งที่ปัญหาคือลูปทำงานไม่ทัน

สรุป

  • ArduPilot Copter ใช้วงรอบหลัก 400 Hz ตามค่าเริ่มต้น งานเร่งด่วนทำทุกรอบ งานอื่นอยู่ในตารางที่ระบุอัตรา เวลา และลำดับความสำคัญ
  • PX4 ใช้ uORB ส่งข้อความระหว่างโมดูล และตัวควบคุมอัตราหมุนทำงานที่อัตรา IMU_GYRO_RATEMAX
  • ภาระของตัวจัดลำดับงานคือผลรวมของอัตราคูณเวลาของทุกงาน
  • เวลาหน่วง กินมุมเฟส องศา และลดส่วนเผื่อเฟสของลูป

แบบฝึกตรวจความเข้าใจ

  1. งาน 50 Hz ใช้เวลา 400 µs คิดเป็นกี่เปอร์เซ็นต์ของเวลาประมวลผล
  2. ลูป 400 Hz มีคาบเท่าใด
  3. เวลาหน่วง 10 ms ที่ 10 Hz ทำให้เฟสล้าหลังกี่องศา
  4. ส่วนเผื่อเฟส 45° ที่ครอสโอเวอร์ 5 Hz ทนเวลาหน่วงได้เท่าใดก่อนหมด
  5. ทำไมการลดความถี่ตัดของตัวกรองจึงอาจทำให้ลูปแกว่ง
เฉลย
  1. ms
  2. s = 25 ms
  3. ตัวกรองเพิ่มเวลาหน่วงและเฟสล้าหลัง ทำให้ส่วนเผื่อเฟสลดลง

สรุปสูตรสำคัญ

ภาระของตัวจัดลำดับงาน
มุมเฟสที่เสียจากเวลาหน่วง

แหล่งอ้างอิงหลัก

  1. ArduPilot Dev Team. Scheduling code to run intermittently. ArduPilot developer documentation. link
  2. ArduPilot Dev Team. ArduPilot source code, tag Copter-4.6.3 [Computer software]. GitHub. link
  3. PX4 Autopilot. uORB messaging. PX4 guide (main). link
  4. PX4 Autopilot. Controller diagrams. PX4 user guide (main). link
  5. PX4 Autopilot. Parameter reference. PX4 user guide (main). link
  6. Christalin, B. (2015). Time delays and Nyquist plots review (CDS 110 recitation notes). California Institute of Technology. link
  7. Beard, R. W., & McLain, T. W. (2012). Small unmanned aircraft: Theory and practice. Princeton University Press. link

อ่านเพิ่มเติม

ศึกษาหน่วยความรู้ที่กำหนดล่วงหน้า ดูสื่อประกอบ และทำ quiz ประจำโมดูล

ในชั้นเรียน / ภาคสนาม

ปฏิบัติการในห้องแล็บหรือภาคสนามตามใบงาน พร้อม checklist ความปลอดภัย

หลักฐานการเรียนรู้: ใบงานที่ผ่านการตรวจและผล quiz

แบบทดสอบประจำโมดูล

แบบทดสอบนี้ใช้ตรวจความเข้าใจ (formative) ไม่ใช่การสอบเก็บคะแนน

โดเมนความรู้: การควบคุม ออโตไพลอต และการนำทาง · การวางแผนภารกิจ การบิน และการจำลอง