Macademia'nın robotik ve mühendislik programı · ücretsiz seviye tespiti ve kişisel öğrenme yolu

5. ünite / 10

PID I: irtifa tutma

SimülasyonYazılım

Bu ünitenin sonunda

  • P, I ve D terimlerinin her birinin yanıta etkisini simülasyonda göstermek
  • Aşım, yükselme ve oturma süresini okumak
  • İleri beslemenin ve I teriminin kalıcı hatayı nasıl kapattığını açıklamak
  • Anti-windup ve ölçüm üzerinden türevi uygulamak

Ders notları

İrtifa denetiminde kontrolcü itkiyi belirler. İyi bir başlangıç noktası ileri beslemedir: askıda kalmak için gereken itkiyi (m g) baştan ver, PID yalnız farkı düzeltsin.

T = m̂ g + Kp e + Ki ∫ e dt − Kd ż,   e = zhedef − z
  • P yay gibidir: hata büyüdükçe daha çok iter. Tek başına salınım üretir ve kontrolcünün bilmediği bir yük varsa Δm g / Kp kadar kalıcı hata bırakır.
  • D sönümleyicidir: hıza karşı koyar, aşımı azaltır. Türev hedeften değil ölçümden alınır; yoksa hedef sıçradığında itki de sıçrar ("türev tekmesi").
  • I belleğe sahiptir: süren hatayı toplar ve kalıcı hatayı sıfırlar. Ama tırmanışta biriken integral aşım yaptırır; itki doymuşken integrali durdurmak anti-winduptur.

Yanıtı okumak

Aşım (%), yükselme süresi (%10 → %90) ve oturma süresi (±%2 bandına son giriş) birbiriyle çekişir. Kp'yi artırmak yanıtı hızlandırır ama aşımı büyütür; Kd bunu dengeler; Ki kalıcı hatayı kapatır. Sıra hep aynıdır: önce P, sonra D, en son I.

PX4 gerçekte irtifayı kaskad yapar: konum hatası → dikey hız hedefi (MPC_Z_P) → hız PID'i (MPC_Z_VEL_P/I/D) → itki. Simülasyondaki tek döngü bu yapının sadeleştirilmiş halidir.

Simülasyon

İrtifa tutma PID ayarı

1,2 kg'lık drone t = 0,5 s'de 0'dan 2 m'ye çıkmak ister. Kontrolcü m·g ileri beslemesini bilir; bilmediği ek yükü kalıcı hata olarak görürsün. Önce yalnız P ve D ile oyna, sonra yük ekle ve hatayı I ile kapat. Aşım, yükselme ve oturma süresi (±%2) altta.

3B sahne yükleniyor…

Simülasyon görevi

İrtifa simülasyonunda: (1) Ki = 0, Kd = 0 yap, Kp'yi 6 bırak: yanıt ne yapıyor? (2) Kd'yi 3'e çıkar: aşım kaç oldu? (3) 0,3 kg ek yük ver: kalıcı hata Δm g / Kp = 0,49 m mi? (4) Ki'yi artırarak hatayı kapat. Hem aşımı %10'un altında hem oturmayı 3 s'nin altında tutan bir ayar bul (ipucu: Kp 8, Ki 2, Kd 5 civarı).

Kod

C++: anti-windup ve türev süzgeçli PID
#include <algorithm>
#include <cmath>

class Pid {
 public:
  Pid(float kp, float ki, float kd, float outMin, float outMax, float dCutoffHz)
      : kp_(kp), ki_(ki), kd_(kd), min_(outMin), max_(outMax), fc_(dCutoffHz) {}

  // sp: hedef, meas: ölçüm, dt: s, ff: ileri besleme (ör. askıda itki m·g)
  float update(float sp, float meas, float dt, float ff = 0.f) {
    const float e = sp - meas;
    // türev ölçümden: hedef sıçrayınca "türev tekmesi" olmaz
    const float raw = first_ ? 0.f : -(meas - prev_) / dt;
    prev_ = meas; first_ = false;
    const float a = dt / (dt + 1.f / (2.f * float(M_PI) * fc_));   // birinci derece alçak geçiren
    d_ += a * (raw - d_);
    const float iNew = i_ + ki_ * e * dt;
    const float u = ff + kp_ * e + iNew + kd_ * d_;
    const float us = std::clamp(u, min_, max_);
    // koşullu integrasyon: doymuşken integrali yalnız doymayı azaltan yönde güncelle
    if (u == us || (u > us && e < 0) || (u < us && e > 0)) i_ = iNew;
    return us;
  }
  void reset() { i_ = 0; d_ = 0; first_ = true; }

 private:
  float kp_, ki_, kd_, min_, max_, fc_;
  float i_ = 0, d_ = 0, prev_ = 0;
  bool first_ = true;
};

// İrtifa tutma, 500 Hz: thrust = pid.update(z_sp, z_est, 0.002f, m * 9.81f);
Python: aynı PID ve basamak yanıtı ölçütleri
import math

class PID:
    def __init__(self, kp, ki, kd, out_min, out_max, d_cutoff_hz=20.0):
        self.kp, self.ki, self.kd = kp, ki, kd
        self.lo, self.hi, self.fc = out_min, out_max, d_cutoff_hz
        self.i = self.d = 0.0
        self.prev = None

    def update(self, sp, meas, dt, ff=0.0):
        e = sp - meas
        raw = 0.0 if self.prev is None else -(meas - self.prev) / dt
        self.prev = meas
        a = dt / (dt + 1 / (2 * math.pi * self.fc))
        self.d += a * (raw - self.d)
        i_new = self.i + self.ki * e * dt
        u = ff + self.kp * e + i_new + self.kd * self.d
        us = min(self.hi, max(self.lo, u))
        if u == us or (u > us and e < 0) or (u < us and e > 0):
            self.i = i_new
        return us

# 1,2 kg drone, ek yük 0,3 kg, 500 Hz
m_ff, m, g, dt = 1.2, 1.5, 9.81, 0.002
pid = PID(8, 2, 5, -m_ff * g, 2 * m_ff * g - m_ff * g)
z = v = 0.0
thrust = m_ff * g
log = []
for k in range(5000):
    sp = 2.0 if k * dt >= 0.5 else 0.0
    cmd = m_ff * g + pid.update(sp, z, dt)
    thrust += (cmd - thrust) * dt / 0.05          # motor gecikmesi τ = 50 ms
    v += (thrust - m * g - 0.3 * v) / m * dt
    z = max(0.0, z + v * dt)
    log.append(z)
print(f"aşım {max(0, (max(log) - 2) / 2 * 100):.1f}%, son hata {2 - log[-1]:.3f} m")

Sık yapılan hatalar

  • Önce Ki'yi artırmak: kalıcı hatayı I kapatır ama salınımı P ve D yönetir.
  • Türevi hata üzerinden almak: hedef değişince motorlara sıçrama gider.
  • Anti-windup koymamak: itki doyumdayken integral büyür, hedefe gelince uzun bir aşım yapar.
  • Barometre gürültüsünü süzmeden D terimine vermek.

Yazılım mühendisliği bağlantısı

Ayar (tuning) bir deneydir; sonuçlarını tekrarlanabilir kıl.

  • Kazançları kodda değil parametre dosyasında tut ve sürümle.
  • Basamak yanıtı ölçütlerini (aşım, oturma) otomatik hesaplayan bir test yaz; kazanç değişikliği bir eşiği bozarsa CI kırmızı olsun. Bu dersteki stepMetrics tam olarak budur.

Kendini sına

  1. Yalnız P (Kp = 6 N/m) ile kontrolcünün bilmediği 0,3 kg yük kalıcı hata olarak yaklaşık ne bırakır?

  2. Türev terimi neden hedeften değil ölçümden alınır?

  3. Anti-windup ne işe yarar?

  4. Diğer kazançlar sabitken Kd artırılırsa aşım genellikle ne olur?

Bu ünitenin parçaları

3B modelli gerçek Hyvex parçaları:

Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç