โมดูล 2/5 · สัปดาห์ 4–6 · 27 ชม.

Cascade control

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

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

บทเรียน

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

  1. อธิบายโครงสร้างตัวควบคุมท่าทางของ ArduPilot จากมุมไปอัตราหมุน
  2. จำลองลูป cascade และเห็นผลของอัตราขยายลูปนอกต่อการตอบสนอง
  3. คำนวณเวลาหมุนถึงมุมเป้าหมายเมื่อจำกัดความเร่งเชิงมุม
  4. เลือกค่าพารามิเตอร์ของตัวควบคุมท่าทางให้เหมาะกับภารกิจ

ความรู้พื้นฐานที่ควรมี: UAT 305 โมดูล 1 · UAT 206 โมดูล 3 (ตัวควบคุม PID)

ทำไมต้องรู้

ออโตไพลอตทุกตัวใช้ การควบคุมแบบ cascade คือลูปซ้อนกันหลายชั้น ลูปนอกสร้างคำสั่งให้ลูปใน ถ้าเข้าใจว่าลูปแต่ละชั้นคุยกันอย่างไร จะรู้ว่าควรปรับค่าใดเมื่อโดรนแกว่ง ตอบสนองช้า หรือหมุนกระตุก หน่วยความรู้เรื่องการควบคุมแบบ cascade และการปรับจูนของคลังความรู้โดรนอธิบายลูป rate, attitude และ position และการอ่าน log เพื่อจูน ตำราของ Beard และ McLain ใช้หลักเดียวกันกับอากาศยานปีกตรึง

ตัวควบคุมท่าทางของ ArduPilot

เอกสารนักพัฒนาของ ArduPilot อธิบายว่า ตัวควบคุม P แปลงความคลาดของมุมเป็นอัตราหมุนที่ต้องการ แล้วตัวควบคุม PID แปลงความคลาดของอัตราหมุนเป็นคำสั่งมอเตอร์ ค่าเริ่มต้นใน Copter 4.6.3 คือ ATC_ANG_RLL_P = 4.5 (ช่วง 3–12) และลูปอัตราหมุน ATC_RAT_RLL_P = 0.135, I = 0.135, D = 0.0036 นอกจากนี้ยังมีการป้อนไปข้างหน้า (feedforward) ของอัตราหมุนที่ต้องการ และตัวควบคุมรากที่สอง (square root controller) ที่ทำให้การเข้าหาเป้าหมายไม่เกินความเร่งที่กำหนด PX4 ใช้โครงสร้างคล้ายกัน: ลูปอัตราหมุนเป็น PID และลูปท่าทางเป็นกฎ P บนควอเทอร์เนียน

แผนภาพบล็อก มุมเป้าหมายเข้าตัวเปรียบเทียบ ผ่าน P มุม ได้อัตราหมุนที่ต้องการ เข้าตัวเปรียบเทียบที่สอง ผ่าน PID อัตรา ไปมอเตอร์และตัวอากาศยาน ผลอัตราหมุนป้อนกลับไปตัวเปรียบเทียบที่สอง และอินทิเกรตเป็นมุมป้อนกลับไปตัวเปรียบเทียบแรก
ภาพที่ 1 ลูปมุมซ้อนลูปอัตราหมุน

ตัวอย่างที่ 1 เพิ่มอัตราขยายลูปนอกเกินไปเกิดอะไร

แบบจำลองอย่างง่ายของการหมุนแกน roll: ลูปอัตราหมุนแบบ PI มอเตอร์มีค่าคงตัวเวลา 30 ms และเวลาหน่วง 10 ms สั่งเอียง 20° แล้วเปลี่ยนเฉพาะอัตราขยายมุม (ค่าในแบบจำลองไม่ใช่หน่วยของ ArduPilot ยกเว้นอัตราขยายมุมที่ใช้ช่วงเดียวกัน)

import math
import numpy as np

def step(k_angle, k_rp=0.15, k_ri=0.1, T=2.0, dt=0.0025, tau=0.03, J=0.02, delay=0.01):
    n = int(T / dt)
    ang = rate = u_act = integ = 0.0
    buf = [0.0] * int(delay / dt)
    out = []
    for _ in range(n):
        rate_cmd = k_angle * (math.radians(20) - ang)      # ลูปนอก: มุม -> อัตราหมุน
        e = rate_cmd - rate
        integ += e * dt
        buf.append(k_rp * e + k_ri * integ)                # ลูปใน: PI ของอัตราหมุน
        u_act += (buf.pop(0) - u_act) * dt / tau           # มอเตอร์ตอบสนองช้า
        rate += u_act / J * dt
        ang += rate * dt
        out.append(math.degrees(ang))
    out = np.array(out)
    overshoot = (out.max() - 20) / 20
    outside = np.where(abs(out - 20) > 0.4)[0]
    settle = (outside[-1] + 1) * dt
    rise = np.argmax(out >= 18) * dt
    return overshoot, settle, rise

for k in (3, 4.5, 9, 12):
    os_, ts, tr = step(k)
    print(f"angle P {k:>4}: rise {tr:.2f} s, overshoot {os_:5.1%}, settle (2%) {ts:.2f} s")
angle P    3: rise 0.53 s, overshoot  1.8%, settle (2%) 0.64 s
angle P  4.5: rise 0.37 s, overshoot 12.3%, settle (2%) 1.25 s
angle P    9: rise 0.23 s, overshoot 40.0%, settle (2%) 1.55 s
angle P   12: rise 0.20 s, overshoot 54.4%, settle (2%) 1.96 s

อัตราขยายลูปนอกยิ่งสูง ยิ่งเข้าหาเป้าหมายเร็ว แต่เกินเป้ามากขึ้นและใช้เวลานิ่งนานขึ้น เพราะลูปนอกสั่งอัตราหมุนเร็วกว่าที่ลูปในตามทัน ลูปในต้องเร็วกว่าลูปนอกพอสมควร จึงควรจูนลูปในให้ดีก่อน แล้วค่อยเพิ่มลูปนอก ตัวเลขนี้เป็นของแบบจำลอง โดรนจริงต้องทดสอบด้วย log

จำกัดความเร่งเชิงมุม

ถ้าสั่งเปลี่ยนมุมทันที มอเตอร์จะรับคำสั่งกระชาก ArduPilot จึงจำกัดความเร่งเชิงมุมด้วย ATC_ACCEL_R_MAX (Copter 4.6.3 หน่วย cdeg/s² ค่าเริ่มต้น 110000 คือ 1,100 deg/s²) และทำให้คำสั่งนุ่มด้วยค่าคงตัวเวลา ATC_INPUT_TC (ค่าเริ่มต้น 0.15 s) รุ่นพัฒนาถัดไปเปลี่ยนชื่อเป็น ATC_ACC_R_MAX หน่วย deg/s² เวลาหมุนต่ำสุดถึงมุม เมื่อเร่งเต็มที่ครึ่งทางแล้วเบรกเต็มที่อีกครึ่งคือ

ตัวอย่างที่ 2 เอียง 20° ด้วยความเร่งต่างกัน

import math

presets = {"default 110000": 110000, "Medium 108000": 108000, "Slow 72000": 72000, "VerySlow 30000": 30000}   # cdeg/s²
ANGLE = 20                                      # องศา
for name, cdeg in presets.items():
    a = cdeg / 100                              # deg/s²
    t = 2 * math.sqrt(ANGLE / a)
    peak = math.sqrt(ANGLE * a)
    print(f"{name:<15} {a:6.0f} deg/s2: {t:.2f} s to {ANGLE} deg, peak rate {peak:5.1f} deg/s")
default 110000    1100 deg/s2: 0.27 s to 20 deg, peak rate 148.3 deg/s
Medium 108000     1080 deg/s2: 0.27 s to 20 deg, peak rate 147.0 deg/s
Slow 72000         720 deg/s2: 0.33 s to 20 deg, peak rate 120.0 deg/s
VerySlow 30000     300 deg/s2: 0.52 s to 20 deg, peak rate  77.5 deg/s

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

กราฟมุมตามเวลา 0 ถึง 2 วินาที สี่เส้นสำหรับอัตราขยายมุม 3 4.5 9 และ 12 เส้นประแนวนอนที่ 20 องศาคือเป้าหมาย เส้นที่อัตราขยายสูงขึ้นไปถึงเร็วกว่าแต่เกินเป้ามากกว่าและแกว่งนานกว่า
ภาพที่ 2 ผลตอบสนองขั้นของมุมตามอัตราขยายลูปนอก (แบบจำลอง)

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

ปฏิบัติการ: ลูปซ้อนใน SITL

  1. เปิด SITL บันทึก log ขณะสั่งเอียงแบบขั้นในโหมด Stabilize หรือ AltHold
  2. ดูข้อความ RATE และ ATT เทียบค่าที่ต้องการกับค่าจริงของทั้งสองลูป
  3. เปลี่ยน ATC_ANG_RLL_P สามค่าในช่วงที่อนุญาต เทียบผลกับตัวอย่างที่ 1
  4. เปลี่ยน ATC_ACCEL_R_MAX ตามค่าที่เอกสารแนะนำ เทียบเวลาหมุนกับตัวอย่างที่ 2
  5. คืนค่าเริ่มต้นทั้งหมด และบันทึกข้อสรุปว่าค่าใดควรใช้กับโดรนฝึก

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

ระวัง

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

สรุป

  • ArduPilot แปลงความคลาดของมุมเป็นอัตราหมุนด้วย P แล้วควบคุมอัตราหมุนด้วย PID พร้อม feedforward
  • ลูปนอกที่แรงเกินลูปในทำให้เกินเป้าและแกว่ง ต้องจูนลูปในก่อน
  • การจำกัดความเร่งเชิงมุมทำให้คำสั่งนุ่ม เวลาหมุนต่ำสุดคือ
  • ชื่อและหน่วยของพารามิเตอร์เปลี่ยนตามรุ่นเฟิร์มแวร์

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

  1. อัตราขยายมุม 4.5 และความคลาดของมุม 10° สั่งอัตราหมุนเท่าใด
  2. ATC_ACCEL_R_MAX = 72000 เท่ากับกี่ deg/s²
  3. หมุน 45° ด้วยความเร่ง 900 deg/s² ใช้เวลาต่ำสุดเท่าใด
  4. ทำไมต้องจูนลูปในก่อนลูปนอก
  5. ความเร่งสูงเกินกำลังมอเตอร์ทำให้เกิดอะไร
เฉลย
  1. deg/s
  2. 720 deg/s²
  3. s
  4. ลูปนอกสั่งงานลูปใน ถ้าลูปในยังตามไม่ทัน การปรับลูปนอกจะแก้ผิดจุด
  5. มอเตอร์อิ่มตัว ควบคุมได้แย่ลง และอาจแกว่ง

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

ลูปนอก (มุม) สร้างคำสั่งอัตราหมุน
เวลาหมุนต่ำสุดเมื่อจำกัดความเร่ง

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

  1. ArduPilot Dev Team. Copter attitude control. ArduPilot developer documentation. link
  2. ArduPilot Dev Team. ArduPilot source code, tag Copter-4.6.3 [Computer software]. GitHub. link
  3. ArduPilot Dev Team. Parameter list (Copter stable V4.6.3). ArduPilot Copter documentation. link
  4. PX4 Autopilot. Controller diagrams. PX4 user guide (main). link
  5. Beard, R. W., & McLain, T. W. (2012). Small unmanned aircraft: Theory and practice. Princeton University Press. link

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

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

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

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

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

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

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

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