17 · Sensor'ler, noise ve filtering
| Bölüm | 5 · Perception ve estimation |
| Çalışma türü | CPU · Mac ya da Colab CPU |
| Önkoşul | 12 |
| Önce öğren | Probability and Distributions · Stochastic Processes |
| Süre | ~45 dk |
| Kod | experiments/17-sensors-noise-filtering/experiment.py |
| Durum | ✅ tam |
Bu derste yap
Her adımı yapınca işaretle. Yalnız bu tarayıcıda saklanır.
Her filtre daha az noise’u delay karşılığında satın alır; doğru pencere, elindeki hareket için iki hatanın eşitlendiği penceredir.
Problem
Bölüm başlığı “Problem”Bir joint controller (ders 12) eklemin konumuna ve hızına ihtiyaç duyar. Gerçek bir kol ikisini de doğrudan vermez. Küçük basamaklarla zıplayan ve elektriksel noise ile titreyen encoder okumaları verir; hızı ise ancak ardışık okumalardan sen hesaplarsan alırsın. Okumaları yumuşatmak titremeyi giderir ama onları geç bırakır; feedback loop’u ise geç veriye kötü tepki verir (ders 37). Bu ders o ödünleşimi simüle edilmiş bir SO-101 ekleminde ölçer ve filtre seçmek için bir kuralla biter.
Okumadan önce · 2 soru. Önce tahmin et; nedenini ders anlatıyor.
1. Titreyen tek bir okumanın yerine son 10 okumanın ortalamasını koyuyorsun. Ne elde edersin?
- Eklemin biraz önce nerede olduğunu anlatan, daha sakin bir sayı.
- Ham okuma kadar güncel, daha sakin bir sayı.
- Aynı noise; çünkü her okuma aynı noise seviyesini taşır.
Neden: okumalık bir moving average penceresinin ortasındaki, örnek önceki değeri raporlar; noise’u olarak düşer. Sıfırdan yaz, Adım 2 ikisini de ölçüyor.
2. Hız için en iyi pencere (n = 65), konum içinkinden (n = 5) çok daha uzun. Neden?
- Hız konumdan daha yavaş değişir, bu yüzden onun için lag önemli değildir.
- Hız ayrı ve daha gürültülü bir sensor ile ölçülür.
- Türev almak kalan noise’u küçük bir Δt’ye böler; noise terimi çok büyür ve minimumu daha uzun bir delay’e kayar.
Neden: Ham hız noise’u 3,50 rad/s, gerçek hızın RMS’i ise 0,63 rad/s. SO-101 modelinde hız sensor’ü yok; hız okumaların farkından geliyor.
Ana fikir
Bölüm başlığı “Ana fikir”Sade anlatımla
Bölüm başlığı “Sade anlatımla”Titreyen bir hız göstergesi düşün. İbreyi bir kez okursan noisy bir sayı alırsın. Son on okumanın ortalamasını alırsan sayı sakinleşir, ama artık arabanın şu anki değil biraz önceki hızını anlatır. Ne kadar çok okumanın ortalamasını alırsan sayı o kadar sakin ve o kadar eski olur.
Yani her yumuşatma filtresinde ters yöne çeken iki hata vardır:
- Noise hatası: titremeden geriye kalan. Daha çok ortalama aldıkça küçülür.
- Gecikme hatası: ortalamasını aldığın okumalardan bu yana eklemin ne kadar ilerlediği. Daha çok ortalama aldıkça büyür; eklem hızlı hareket ediyorsa daha da hızlı büyür.
En iyi filtre, ikisinin toplamının en küçük olduğu yerdir. Bu yerin neresi olduğu eklemin ne kadar hızlı hareket ettiğine bağlıdır. Dersin tamamı bu.
Sinyal zinciri
Bölüm başlığı “Sinyal zinciri”flowchart TD
Q["gerçek açı q(t)"] --> E["encoder<br/>basamağa yuvarlar"]
E --> N["+ elektriksel noise"]
N --> F["filtre<br/>(ortalama / low-pass)"]
F --> C["controller"]
F -. "iki örneğin<br/>farkı" .-> V["hız tahmini"]
V --> C
İki filtre, kod olarak
Bölüm başlığı “İki filtre, kod olarak”Bir sayı akışı üzerinde rolling average yazdıysan ilk filtreyi zaten biliyorsun. Okumalar her dt saniyede bir gelir (burada dt = 0.002, yani saniyede 500); Sıfırdan yaz iki filtreyi tam olarak yazar.
# Moving average: the mean of the last n readingsy[k] = mean(z[k - n + 1 : k + 1])# First-order low-pass: move a fraction alpha toward each new readingalpha = dt / (tau + dt) # tau = 1 / (2 pi fc); small alpha = heavy smoothingy[k] = y[k - 1] + alpha * (z[k] - y[k - 1])n okumalık bir moving average penceresinin ortasındaki, yani örnek önceki değeri raporlar; low-pass filtre yaklaşık zaman sabiti tau kadar geç kalır.
| Filtre | Ayar | Delay | Kalan noise (std) |
|---|---|---|---|
| Moving average | pencere | ||
| Birinci derece low-pass | cutoff | düştükçe azalır |
Burada iki okuma arasındaki süre, tek bir okumanın noise standart sapmasıdır. Gecikme hatası kabaca hız × delay’dir: 0,6 rad/s ile dönen bir eklem 16 ms’lik bir filtreden bakınca yaklaşık rad geride görünür.
Matematik ayrıntısı: σ/√n ve hata ödünleşimi nereden geliyor
Ortalama almak noise’u √n kadar azaltır. okuma, varyansı olan bağımsız noise’lar taşıyorsa, ortalamalarındaki noise ‘dir ve varyansı ‘dir. Standart sapma olarak düşer. Bağımsızlık önemlidir: korelasyonlu noise (örneğin yavaş bir drift) bu yolla gitmez.
Moving average’ın delay’i. Yavaş değişen bir sinyali için pencere ortalamasının şu ana göre Taylor açılımı verir: çıkış, yarım pencere kadar gecikmiş sinyaldir.
Low-pass filtre. , denkleminin ayrık hâlidir. ‘nun çok altındaki frekanslarda phase delay’i ‘ya yaklaşır; civarında ve üstünde daha küçüktür. Deney bunu 0,5 Hz’de gösteriyor.
Ödünleşim. Delay iken filtrelenmiş konum kabaca artı kalan noise’tur; dolayısıyla
burada , büyüdükçe azalır (moving average için iken ). Düşen bir terim ile büyüyen bir terimin toplamının bir minimumu vardır.
Hız daha zordur. İki okumadan hız, , onların noise’unu küçük bir sayıya böler: noise yaklaşık katı büyür. Bu yüzden hız için noise terimi çok daha büyüktür ve minimumu çok daha uzun bir delay’dedir.
Daha derine (random variable, varyans, noise süreçleri): Probability and Distributions, Stochastic Processes.
Kısaca sensor’ler
Bölüm başlığı “Kısaca sensor’ler”| Sensor | Ne raporlar | Tipik hata |
|---|---|---|
| Encoder (turda sayım) | basamaklarına yuvarlanmış açı | quantization (basamak boyu) + elektriksel noise |
| Gyroscope | açısal hız | yavaş değişen bias + noise; bias’ı integre etmek doğrusal olarak kayan bir açı verir |
| Accelerometer | specific force | durağan hâlde sıfır değil yerçekimi okur |
MuJoCo sensor’leri (jointpos, jointvel, gyro, accelerometer, …) mjData.sensordata dizisine tam değerler yazar. noise attribute’u yalnızca saklanan metadata’dır: dokümantasyon simülasyonu etkilemediğini söyler (MuJoCo Modeling · sensors). Noise’u sen eklersin.
Sıfırdan yaz
Bölüm başlığı “Sıfırdan yaz”Şimdi sensor modelini ve iki filtreyi yaklaşık 40 satır NumPy ile kendin yazacak, her birini SciPy’a ya da Ana fikir’deki bir formüle karşı kontrol edeceksin. MuJoCo’dan yalnızca eklemin gerçek hareketi gelir (Deney’in simulate fonksiyonu); böylece Sıfırdan yaz ile Deney aynı 5000 okumayı puanlar.
Adımları kendi dosyana yaz ve her adımdan sonra çalıştır. Bitmiş fonksiyonlar physai/estimation.py içinde; uv run python experiments/17-sensors-noise-filtering/build.py beş adımı kontrolleriyle çalıştırır (çıktı: build_output.txt).
Adım 1 · Encoder
Bölüm başlığı “Adım 1 · Encoder”Encoder açıyı tam sayımlara yuvarlar; elektronik üstüne noise ekler:
def encoder_reading(q, counts, sigma, rng): """What an encoder reports for true angles q: rounded to steps of 2 pi / counts, plus white noise.""" step = 2 * np.pi / counts # one count, in rad return np.round(q / step) * step + rng.normal(0, sigma, np.shape(q))basamaklarına yuvarlamak ile arasında eşit dağılmış bir hata bırakır; standart sapması ‘dir. Bunu önce bir milyon rastgele açıda, sonra dersin sinyalinde kontrol et:
== Step 1. The encoder: 4096 counts/rev, sigma 10 mrad ==step = 1.534 mrad, max |rounding error| = 0.767 mrad (step / 2 = 0.767)rounding error std 0.4427 mrad vs step / sqrt(12) = 0.4428 mradlesson signal: max |ours - Exp. encoder| = 0.0e+00 radexpected reading error sqrt(sigma^2 + step^2/12) = 10.01 mrad, measured 9.95 mradYuvarlama payı (0,44 mrad) 10 mrad’lık noise’un yanında küçük; beklenen okuma hatası 10,01 mrad. Bu seed’in noise çekilişi %0,6 düşük çıkıyor; Deney’in 9,95 mrad ölçmesinin sebebi bu.
Adım 2 · Moving average
Bölüm başlığı “Adım 2 · Moving average”Kümülatif toplam her pencere ortalamasını tek bir çıkarmaya indirir; maliyet ile büyümez:
def moving_average(x, n): """Causal moving average: the mean of the last n samples (fewer at the start), as in lesson 17.""" c = np.cumsum(np.insert(x, 0, 0.0)) i = np.arange(len(x)) lo = np.maximum(0, i + 1 - n) return (c[i + 1] - c[lo]) / (i + 1 - lo)Üç kontrol: pencereler üzerinde düz bir döngüyle aynı sayılar, saf white noise’ta kalan noise’un ile karşılaştırması ve delay. Rampa delay’i kesinleştirir: bir doğrunun son örneğinin ortalaması, onun örnek önceki değeridir.
== Step 2. Moving average: window mean, noise left, delay on a ramp ==n = 5: max |ours - loop over windows| = 2.2e-16 n noise std left 1/sqrt(n) ramp lag samples (n-1)/2 5 0.4459 0.4472 2.0 2.0 17 0.2415 0.2425 8.0 8.0 65 0.1226 0.1240 32.0 32.0Adım 3 · Birinci derece low-pass
Bölüm başlığı “Adım 3 · Birinci derece low-pass”def low_pass(x, fc, dt): """First-order low-pass with cutoff fc (Hz): move a fraction alpha toward each new sample.""" tau = 1.0 / (2 * np.pi * fc) # time constant (s) alpha = dt / (tau + dt) # small alpha = heavy smoothing y = np.empty(len(x)) y[0] = x[0] # start at the first reading for k in range(1, len(x)): y[k] = y[k - 1] + alpha * (x[k] - y[k - 1]) return yBu recursive bir filtre, ; scipy.signal.lfilter onu b = [alpha], a = [1, alpha - 1] katsayılarıyla çalıştırır. SciPy’ı lfilter_zi(b, a) * z[0] ile başlatmak, seninki gibi ilk okumadan başlamasını sağlar. Kontrol edilecek iki formül: birim varyanslı white noise varyansının ‘sını bırakır, rampada çıkış örnek geride kalır; ile bu tam olarak ‘dir.
== Step 3. First-order low-pass: vs scipy.signal.lfilter, noise left, delay on a ramp ==fc Hz alpha max |ours - lfilter| noise std left sqrt(a/(2-a)) ramp lag samples tau/dt 50 0.3859 2.2e-16 0.4878 0.4889 1.59 1.59 10 0.1116 3.3e-16 0.2423 0.2431 7.96 7.96 2 0.0245 1.8e-15 0.1103 0.1114 39.79 39.79Rampa gecikmesi her cutoff’ta iki ondalığa kadar . Kalan noise formülden yaklaşık %1 içinde (fark, sonlu noise örneğinden).
Adım 4 · Farklardan hız
Bölüm başlığı “Adım 4 · Farklardan hız”def central_difference(y, dt): """Velocity from samples: (y[k+1] - y[k-1]) / 2 dt inside, one-sided at the two ends.""" v = np.empty(len(y)) v[1:-1] = (y[2:] - y[:-2]) / (2 * dt) v[0], v[-1] = (y[1] - y[0]) / dt, (y[-1] - y[-2]) / dt return vnp.gradient(y, dt) de bunu yapar; kontrol son bitine kadar doğruluyor. Bağımsız 10,01 mrad hatalı iki okuma, = 4 ms’ye bölününce ham hız noise’unu öngörür:
== Step 4. Velocity by central differences ==max |ours - np.gradient| = 0.0e+00 rad/sraw velocity error: predicted sqrt(2) * 10.01 mrad / (2 dt) = 3.54 rad/s, measured 3.50 rad/s (true velocity RMS 0.63)Öngörülen 3,54, ölçülen 3,50 rad/s: Adım 1’deki aynı %0,6 düşük çekiliş. Noise gerçek hızın beş katından fazla; hızın konumdan çok daha ağır filtre istemesinin sebebi bu.
Adım 5 · Delay’i ve hataları ölç
Bölüm başlığı “Adım 5 · Delay’i ve hataları ölç”Deney bir filtrenin delay’ini, filtrelenmiş sinyali gerçeğiyle en iyi hizalayan kaydırma olarak tanımlar:
def delay_samples(y, ref, max_lag=400, skip=500): """The shift (in samples) that best aligns a filtered signal y with the true signal ref.""" errs = [np.mean((y[skip + lag:] - ref[skip:len(ref) - lag]) ** 2) for lag in range(max_lag)] return int(np.argmin(errs))Deney’deki her filtreyi kendi fonksiyonlarından geçir ve onun sayılarıyla karşılaştır:
== Step 5. Every filter on the lesson's signal vs the Experiment == filter delay ms theory ms pos RMS mrad vel RMS rad/s max |ours - Exp.| MA n=1 0.0 0.0 9.95 3.50 0.0e+00 MA n=3 2.0 2.0 5.91 1.65 0.0e+00 MA n=5 4.0 4.0 5.17 1.01 0.0e+00 MA n=9 8.0 8.0 6.03 0.55 0.0e+00 MA n=17 16.0 16.0 10.22 0.29 0.0e+00 MA n=33 32.0 32.0 19.76 0.16 0.0e+00 MA n=65 64.0 64.0 39.01 0.12 0.0e+00 MA n=129 128.0 128.0 76.52 0.19 0.0e+00 LPF 50 Hz 4.0 3.2 5.30 1.35 0.0e+00 LPF 20 Hz 8.0 8.0 6.02 0.71 0.0e+00 LPF 10 Hz 16.0 15.9 10.16 0.39 0.0e+00 LPF 2 Hz 78.0 79.6 47.33 0.14 0.0e+00 LPF 0.5 Hz 274.0 318.3 152.59 0.35 0.0e+00lag error of MA n=17: speed x delay = 0.61 rad/s x 16 ms = 9.8 mradHer satır Deney tablosuna son basamağına kadar eşit. Ölçülen delay’ler her pencere için ile örtüşüyor. Low-pass’te ise yalnızca hareketin çok üstündeyken ile örtüşüyor (delay’ler tam 2 ms’lik örneklerdir, bu yüzden 50 Hz satırı 3,2 ms’yi 4,0 gösteriyor; 0,5 Hz satırı 318,3 değil 274 ms). Son satır, MA n=17 için Ana fikir’deki gecikme hatası: ölçülen 10,22 mrad’ın 9,8 mrad’ı.
Elinde kalan
Bölüm başlığı “Elinde kalan”physai.estimation artık encoder_reading, moving_average, low_pass, central_difference ve delay_samples içeriyor. Ders 18 aynı encoder modelini ve baseline olarak moving_average’ı kullanır, iki filtrenin yerine öngören tek bir filtre koyar; ders 37 delay’e bir feedback döngüsü içinde döner. tests/test_17_sensors_noise_filtering.py onları SciPy’a sabitler; bir şeyi değiştirdikten sonra uv run pytest tests/test_17_sensors_noise_filtering.py çalıştır.
Kütüphaneyle kullan
Bölüm başlığı “Kütüphaneyle kullan”SciPy iki filtreyi de tek çağrıyla çalıştırır: scipy.signal.lfilter(b, a, x), yani fark denklemi:
from scipy.signal import group_delay, lfilter, lfilter_zi
y_ma = lfilter(np.ones(n) / n, 1.0, z) # moving average (first n-1 outputs differ)alpha = dt / (1 / (2 * np.pi * fc) + dt)b, a = [alpha], [1.0, alpha - 1.0]y_lp, _ = lfilter(b, a, z, zi=lfilter_zi(b, a) * z[0]) # low-pass, starting at the first reading_, gd = group_delay((b, a), w=[0.2], fs=1 / dt) # delay in samples at 0.2 Hzgroup_delay delay’i sinyal olmadan yalnızca katsayılardan verir: moving average için örnek, low-pass için düşük frekansta ; ikisi de testlerde kontrol ediliyor. Başka araçlar aynı pencereyi farklı yerleştirir:
| Çağrı | Pencere | Başlangıç |
|---|---|---|
physai moving_average(x, n) | son örnek (causal) | o ana kadar görülen örneklerin ortalaması |
scipy.signal.lfilter(np.ones(n)/n, 1, x) | son örnek (causal) | başlangıçtan önceki örnekler 0 sayılır (“initial rest”) |
scipy.ndimage.uniform_filter1d(x, n) | örneğe ortalanmış (origin=0), geleceği kullanır | kenarlarda mode='reflect'; origin=(n-1)//2 onu causal yapar (testlerde kontrol edildi) |
np.gradient(y, dt) | bir önceki ve bir sonraki örnek (central) | iki uçta tek taraflı farklar |
Kaynaklar: lfilter, group_delay, uniform_filter1d, np.gradient.
Üç tuzak:
- Ortalanmış filtre bedava görünür.
uniform_filter1dvenp.gradientgelecekteki örnekleri kullanır: offline sıfır delay gösterirler, çalışan bir controller’da o örnekler henüz yoktur. Deney’in hızınp.gradientkullanır ve bu yüzden bir örnek ileriye bakar. - “‘de birinci derece low-pass” tek bir filtre değildir.
scipy.signal.butter(1, 10, fs=500)b = [0.0592, 0.0592],a = [1, -0.8816]döndürür (bilinear transform); bu dersin ‘sıa = [1, -0.8884]verir. İkisine de 10 Hz’lik birinci derece low-pass denir. noiseattribute’u hiçbir şey eklemez. MuJoCo onu metadata olarak saklar; bu dersteki noise, Adım 1’de senin eklediğin noise’dur.
Yazdıktan sonra · 2 soru.
1. Sıfırdan yaz, Adım 3’te 10 Hz’lik low-pass bir rampayı 7,96 örnek geriden izliyor. Bu sayı nereden geliyor?
- Filtre penceresinin yarısıdır, 17 örneklik bir moving average gibi.
- Henüz sönmemiş başlangıç transient’idir.
- Rampada filtre örnek geride kalır; ile bu tam olarak = 15,9 ms / 2 ms’dir.
Neden: Adım 3, 10 Hz’de 7,96 örneklik rampa gecikmesini = 7,96 karşısında basıyor (50 ve 2 Hz’de 1,59 ve 39,79). Low-pass’in penceresi yoktur; delay’i zaman sabitidir.
2. Causal moving average’ını varsayılan ayarlarıyla scipy.ndimage.uniform_filter1d(x, n) ile değiştiriyorsun. Offline delay sıfıra iniyor. Controller’ın da bunu görecek mi?
- Evet; SciPy’ın implementasyonu sadece daha hızlı.
- Hayır; varsayılan pencere örneğe ortalanmıştır ve gelecekteki okumaları kullanır, çalışan bir controller’da bunlar henüz yoktur.
- Evet, pencere uzunluğu tek sayı olduğu sürece.
Neden: Kütüphaneyle kullan - uniform_filter1d ortalanmıştır (origin=0); origin=(n-1)//2 onu causal yapar ve o zaman Adım 2’deki aynı örneklik delay’e sahip olur.
Kurulum. MuJoCo Menagerie’den SO-101, timestep 2 ms (500 Hz örnekleme). shoulder_pan, position actuator’ü üzerinden 10 s boyunca rad izler. 12-bit bir encoder (turda 4096 sayım, basamak 1,534 mrad) artı beyaz noise mrad modelliyoruz. Bunlar datasheet değil öğretim değerleri. Hız, filtrelenmiş sinyalin np.gradient (central difference) ile türeviyle hesaplanır. Delay, filtrelenmiş sinyalle gerçek sinyali en iyi hizalayan kaydırmadır.
s = spec.add_sensor(name="q_pan", type=mujoco.mjtSensor.mjSENS_JOINTPOS, objname="shoulder_pan", objtype=mujoco.mjtObj.mjOBJ_JOINT)s.noise = 0.01 # metadata only...z = np.round(q / step) * step + rng.normal(0, SIGMA, q.shape) # our encodery = moving_average(z, n) # or low_pass(z, fc)Tahmin et. Ham hız noise’u yaklaşık rad/s olmalı, yani gerçek hızdan büyük. En iyi konum penceresi kısa, en iyi hız penceresi çok daha uzun olmalı.
Çalıştır uv run python experiments/17-sensors-noise-filtering/experiment.py (MuJoCo 3.17.0, NumPy 2.5.4, Apple M5, deterministik).
İlk kontroller: noise=0.01 ile tanımlanan jointpos sensor’ü qpos’tan tam olarak 0,0 rad farklı. (Sensor’ler mj_step’in başında, integrasyondan önceki state’ten hesaplanır; o state ile karşılaştır, yoksa bir adımlık kayma görürsün.) Ham okumanın konum RMS hatası 9,95 mrad, hız RMS hatası 3,50 rad/s; gerçek hız RMS’i ise 0,63 rad/s.

| Filtre | Delay (ms) | Konum RMS (mrad) | Hız RMS (rad/s) |
|---|---|---|---|
| ham | 0,0 | 9,95 | 3,50 |
| MA n=3 | 2,0 | 5,91 | 1,65 |
| MA n=5 | 4,0 | 5,17 | 1,01 |
| MA n=9 | 8,0 | 6,03 | 0,55 |
| MA n=17 | 16,0 | 10,22 | 0,29 |
| MA n=33 | 32,0 | 19,76 | 0,16 |
| MA n=65 | 64,0 | 39,01 | 0,12 |
| MA n=129 | 128,0 | 76,52 | 0,19 |
| LPF 50 Hz | 4,0 | 5,30 | 1,35 |
| LPF 20 Hz | 8,0 | 6,02 | 0,71 |
| LPF 10 Hz | 16,0 | 10,16 | 0,39 |
| LPF 2 Hz | 78,0 | 47,33 | 0,14 |
| LPF 0,5 Hz | 274,0 | 152,59 | 0,35 |
Gözlem.
- Moving-average delay’i her satırda ‘ye eşit. Low-pass delay’i, sinyal frekanslarına yaklaşana kadar ile örtüşür (10 Hz’de 15,9 → 16,0 ms): 0,5 Hz’de 318,3 ms değil 274 ms’dir, çünkü yalnızca düşük frekans limitidir.
- Konum hatası yaklaşık 4 ms delay’de en düşük (MA n=5, 5,17 mrad) ve sonrasında neredeyse doğrusal büyür: 17 örnekten itibaren filtre, hiç filtre olmamasından kötüdür.
- Hız 16 kat delay ister (MA n=65, 64 ms, 0,12 rad/s). Tek bir filtre ikisine birden hizmet edemez. Ders 18’deki Kalman filter bu boşluğu kapatır.
- Eşit delay’de iki filtre tipi neredeyse aynı (8 ms’de MA n=9: 6,03 mrad; LPF 20 Hz: 6,02 mrad). Filtrenin şeklinden çok, kabul ettiğin delay önemlidir.
IMU kontrolü (aynı script): durağan kolda accelerometer m/s² okur. 0,02 rad/s bias ve 0,05 rad/s noise’lu bir gyro 10 s integre edilince, hiç dönmeyen bir eklem için 0,209 rad (12,0°) dönüş raporlar.
MA n=17’yi (16 ms delay) sabit tut ve iki frekansı ile ölçekleyerek hareketi hızlandır:
| k | Gerçek hız RMS (rad/s) | Ham konum RMS (mrad) | MA17 konum RMS (mrad) |
|---|---|---|---|
| 0,5 | 0,28 | 9,94 | 5,01 |
| 1 | 0,61 | 9,95 | 10,22 |
| 2 | 1,27 | 9,95 | 20,46 |
| 4 | 2,51 | 9,95 | 40,00 |
| 8 | 3,73 | 9,94 | 59,49 |
Ham hata hıza aldırmaz. Filtrelenmiş hata hız × delay’i izler: 0,61 rad/s × 16 ms ≈ 9,8 mrad, ölçülen 10,22. Yavaş bir test hareketinde ayarlanmış pencere, hızlı harekette filtresizden kötü hâle gelir. Filtreyi robotun gerçekten yapacağı en hızlı hareket üzerinde ayarla ya da hareketi ortalamak yerine tahmin eden model tabanlı bir filtre kullan (ders 18).
Gerçek robotta
Bölüm başlığı “Gerçek robotta”- SO-101 follower, 1/345 dişli oranlı altı Feetech STS3215 servo kullanır (LeRobot SO-101 dokümanı). Konum, seri bus üzerinden servonun iç encoder’ından gelir; Menagerie modelinde hız sensor’ü ve IMU yoktur. STS3215 encoder çözünürlüğünü doğrulamadık; yukarıdaki 4096 sayım bizim modelleme seçimimiz.
- Gerçek donanımda okuma hızını 2 ms’lik timestep değil bus belirler; dolayısıyla ve yukarıdaki delay’ler değişir. Kendi loop hızın için yeniden hesapla.
- Kendi ‘nı ölçmek: kolu sabit bir pozda tut, her eklemi 10 s logla, eklem başına standart sapmayı al. Durağan hâlde saf bir quantizer sıfır varyans gösterebilir; bu durumda yavaş bir rampa komutla ve oturtulan doğrudan kalan farka bak. Gerçek kolda henüz ölçülmedi.
Kendini dene
Bölüm başlığı “Kendini dene”Hızlı kontrol · 2 soru. Bir cevaba tıkla.
1. 17 örneklik bir moving average noise’un yalnızca ‘sini bırakıyor. Konum hatası (10,22 mrad) neden ham okumadan (9,95 mrad) kötü?
- Quantize edilmiş okumaları ortalamak ek quantization hatası ekler.
- 16 ms’lik delay’i onu yaklaşık hız × delay kadar geride bırakıyor; bu, kaldırdığı noise’dan fazla.
- Noise korelasyonlu, bu yüzden ortalamak onu azaltmaz.
Neden: Lag hatası ≈ 0,61 rad/s × 16 ms ≈ 9,8 mrad (Boz). Noise ile lag’in toplamı yaklaşık 4 ms delay’de en düşük; MA n=5, 5,17 mrad.
2. MA n=17’yi yavaş bir test hareketinde ayarladın. Gerçek görev 4 kat hızlı. Konum hatasına ne olur?
- Yaklaşık 40 mrad’a çıkar; ham okumanın hatasının dört katı.
- Aynı kalır, çünkü noise hıza bağlı değildir.
- Yarıya iner, çünkü hızlı hareket noise’u ortalar.
Neden: Boz, k = 4 - MA17 40,00 mrad veriyor, ham hata ise 9,95 mrad’da kalıyor. Filtreyi robotun gerçekten yapacağı en hızlı hareket üzerinde ayarla.
- Kolay. 64 örneklik bir moving average 200 Hz’de çalışıyor. Delay’i nedir?
- Orta. Tabloda en iyi hız penceresi (65) neden en iyi konum penceresinden (5) çok daha uzun? “Noise’u Δt’ye bölmek” argümanını kullan.
- Zor.
np.gradientyerine causal backward difference kullan. Ham hız noise’unu tahmin et, sonra çalıştır. En iyi hız penceresi değişiyor mu?
Cevaplar
Bölüm başlığı “Cevaplar”- ms ms.
- Türev almak kalan noise’u yaklaşık s⁻¹ ile çarpar; gecikme terimi ise yalnızca hız × delay’den ivme × delay’e değişir. Noise terimi hızda konumdakinden çok daha büyüktür; bu yüzden noise + gecikme toplamının minimumu çok daha uzun bir delay’e kayar.
- Tahmin edilen ham noise rad/s; central difference iki örnek aralığını kapsadığı için onun iki katı. Yeni optimumu görmek için çalıştır; biz çalıştırmadık.
Akılda kalanlar ve kaynaklar
Bölüm başlığı “Akılda kalanlar ve kaynaklar”- MuJoCo sensor’leri tamdır;
noisemetadata’dır. Quantization, beyaz noise ve gyro bias’ını sen eklersin. - Bir filtrenin delay’i tahmin edilebilir ( ya da ) ve gecikme hatası yaklaşık hız × delay’dir. En iyi pencere eklemin ne kadar hızlı hareket ettiğine bağlıdır ve konum ile hız için farklıdır.
- Bias’lı bir gyro’yu integre etmek doğrusal drift üretir; düzeltmek için ikinci bir sensor ya da model gerekir.
Sıradaki: ders 18, Kalman filter.
Kaynaklar:
- MuJoCo Modeling · Sensors: sensor’ler simülasyonu etkilemez;
noiseyalnızca saklanan standart sapmadır. - MuJoCo XML reference · accelerometer: site frame’inde yerçekimi dahil doğrusal ivme verir.
- LeRobot SO-101 dokümanı: altı STS3215 servolu follower kol.
- MuJoCo Menagerie · robotstudio_so101 (Apache-2.0).
- Yukarıdaki tüm sayılar:
experiment.py, çıktıoutput.txt.