Unidad 1 · Filtrado digital · H(z) factorizada, la lectura geométrica de |H|, la estabilidad y el FIR todo ceros
Un filtro LTI con ecuación en diferencias tiene una función de transferencia que es un cociente de dos polinomios. Las raíces de arriba son los ceros; las de abajo, los polos. Con esa lista de puntos en el plano complejo, más una ganancia, está todo el filtro: el módulo de su respuesta en frecuencia se lee como un cociente de distancias, la fase como una suma de ángulos, y la estabilidad como una sola pregunta sobre los polos.
La ecuación en diferencias, pasada a , convierte cada retardo en un factor y deja un cociente:
Los son la parte no recursiva y los la recursiva, como en filter(b, a, x) y en los scripts de la clase. La filmina los nombra al revés — arriba, abajo—; la cuenta es la misma.
Todo polinomio se factoriza por sus raíces. Hacerlo arriba y abajo da la forma en polos y ceros:
Los son los ceros: donde . Los son los polos: donde se va a infinito. Con coeficientes reales, los que no son reales vienen de a pares conjugados. Los ceros salen de los coeficientes que multiplican a la entrada; los polos, de los que multiplican a la salida realimentada. Sin realimentación no hay de dónde sacar un polo, salvo el caso trivial del origen, que tiene su propia sección más abajo.
El ejemplo es el IIR del script Clase.m, con b = [1 1] y a = [1 -sqrt(2)/2]:
Paso 1: pasar a potencias positivas. Las raíces de un polinomio en se buscan mejor en . Se multiplica arriba y abajo por , con la mayor de las dos potencias negativas, que acá es 1:
Paso 2: las raíces. Arriba, : un cero. Abajo, : un polo. Es lo que devuelven roots(b) y roots(a).
Paso 3: contar. En potencias positivas, el numerador y el denominador quedan del mismo grado , así que siempre hay tantos polos como ceros. Si y son distintos, el que tiene menos recibe raíces en . Esas raíces en el origen no se ven en roots, que sólo mira un polinomio por vez, y son el origen de la confusión de la sección 06.
Un ejemplo con pares conjugados, el del apunte: b = [1 0 1] y a = [1 -1.6 0.8], o sea . Los ceros son , sobre el círculo unitario. Los polos son , de módulo y ángulo . tf2zpk los devuelve así, con ganancia 1.
La respuesta en frecuencia es evaluada sobre el círculo unitario, en . Recorrer las frecuencias de 0 a es recorrer la mitad de arriba del círculo, de a .
Paso 1: sacar de cada factor. Como , la forma factorizada queda
Paso 2: tomar módulo en . El módulo de un producto es el producto de los módulos, y . Cada factor es la distancia entre el punto del círculo y la raíz:
Paso 3: tomar ángulo. El ángulo de un producto es la suma de los ángulos, y el de un cociente, la resta. Cada factor aporta el ángulo del segmento que va de la raíz al punto :
Con el ejemplo de los ceros en y los polos en , en : las distancias a los ceros son 1,0450 y 1,7053, y a los polos, 0,1058 y 0,8588. El cociente da 19,61, y freqz da 19,6088. Sobre 200 001 frecuencias entre 0 y , el cociente de distancias y freqz difieren en 4,3×10⁻¹⁴ como máximo en el módulo y en 1,2×10⁻¹² en la fase. Es la misma función, calculada por otro camino.
De la fórmula salen tres lecturas que se usan todo el tiempo:
freqz da 7,6×10⁻¹⁷ ahí. En Clase.m, el cero en mata . Un cero cerca del círculo, sin tocarlo, hace un valle.Un par de polos en , con numerador 1. En la distancia al polo de arriba es exactamente , y la del de abajo tiende a :
Medido con freqz sobre 2 000 001 frecuencias entre 0 y , con el ancho a −3 dB medido respecto del pico:
| r | pico | dónde cae (ω/π) | |H| en π/3 | ancho a −3 dB | 2(1 − r) |
|---|---|---|---|---|---|
| 0,50 | 3,75 dB | 0,2851 | 3,59 dB | no hay | 1,00 |
| 0,80 | 10,12 dB | 0,3287 | 10,11 dB | 0,4625 | 0,40 |
| 0,90 | 15,67 dB | 0,3323 | 15,67 dB | 0,2123 | 0,20 |
| 0,95 | 21,47 dB | 0,3331 | 21,47 dB | 0,1028 | 0,10 |
| 0,99 | 35,27 dB | 0,3333 | 35,27 dB | 0,0201 | 0,02 |
Cada vez que la distancia se parte a la mitad, el pico sube casi 6 dB —que es un factor 2 en el denominador— y el ancho se parte a la mitad. El ancho tiende a radianes. Con no hay ancho que medir: está apenas 1,25 dB debajo del pico, y el pico mismo se corre hasta 0,285π, porque el polo de abajo pesa casi lo mismo que el de arriba. Con chico el máximo no está en el ángulo del polo; con cerca de 1, sí. Así consigue un IIR una transición angosta con dos coeficientes, casi gratis contra un FIR.
Un sistema LTI causal con racional, sin polos y ceros que se cancelen, es estable BIBO si y sólo si todos sus polos están adentro del círculo unitario: para todo .
Paso 1: fracciones parciales. Con polos simples y , el cociente se abre en una suma de términos de un solo polo:
Paso 2: antitransformar cada término. es una serie geométrica, así que la parte causal de cada término es una exponencial:
Paso 3: sumar los módulos. Estable BIBO es , y converge a sólo si . Un solo polo afuera alcanza para que la suma diverja. Con polos repetidos aparecen factores , que con también se apagan: la condición es la misma.
Con un polo real, . Con la suma de módulos es . Con es el acumulador: para siempre, marginal y no estable. Con , , y sigue creciendo.
no avisa. Reflejar un polo del otro lado del círculo, , cambia cada distancia por el mismo factor para todo :
Así que la forma de no cambia: sólo la escala. Con el par y su reflejo en , el cociente de los dos módulos de freqz vale 1,5625 en las 4096 frecuencias, igual hasta el decimal doce: es . Pero en las primeras 60 muestras, la del original nunca pasa de 1 y la del reflejado llega a 4,18×10⁵. La estabilidad se lee en el plano o en , no en el módulo.
Es al revés de lo que parece a veces: un FIR es un filtro todo ceros. No tiene denominador, , y sin realimentación no hay de dónde salgan polos. Lo que sí tiene son polos en el origen, y vale la pena ver de dónde vienen.
Paso 1: el FIR en potencias negativas. Con coeficientes:
Paso 2: pasarlo a potencias positivas. Es el paso 1 de la sección 02: se multiplica arriba y abajo por . Arriba queda un polinomio en ; abajo, lo que era un 1 pasa a ser :
Paso 3: leer las raíces. Arriba hay ceros, donde caigan. Abajo, tiene una sola raíz, , con multiplicidad . Esos son todos los polos de un FIR, y los tres hechos que importan salen de la lectura geométrica:
La media móvil, en polos y ceros. Con coeficientes iguales a , el numerador en potencias positivas es una serie geométrica:
Las raíces de son las raíces de la unidad, , repartidas parejo sobre el círculo. La de , , se cancela con el de abajo. Quedan ceros sobre el círculo en los ángulos , : son exactamente los ceros de la sinc periódica de la media móvil, vistos desde el plano . Y polos en el origen. Con , tf2zpk da 7 ceros cuyos ángulos difieren de en 8,9×10⁻¹⁶ como máximo, y 7 polos en exactamente 0. Y el módulo de freqz contra , sin ningún polo, difiere en 1,2×10⁻¹⁵ sobre 4096 frecuencias.
El contraste: el IIR todo polos. Es el caso espejo, con el numerador constante. El IIR de Ejemplo_filtros.m tiene b = 0.1 y a = [1 -0.9]:
Un polo en 0,9, que es el que hace todo el trabajo, y un cero trivial en el origen, que aparece por la misma cuenta y tampoco toca el módulo. El FIR tiene sus ceros donde quiera y los polos amontonados en 0; el IIR todo polos, al revés.
De dónde sale la confusión. Hay tres lugares donde un FIR parece tener polos:
zplane los dibuja. zplane(h, 1) con la media móvil de 8 pone siete círculos sobre el círculo unitario y una cruz en el origen con un 7 al lado: son los siete polos triviales, apilados. La cruz es lo que se ve primero, y es la que no importa.tf2zpk reporta un polo en 1. Pero el numerador tiene un cero justo ahí —a 4,4×10⁻¹⁶— y se cancelan: filter da la misma que el FIR, con diferencia 0. Es un FIR escrito con un polo que no está.fir1(10, 0.3) de más abajo pone sus cuatro ceros sobre el círculo en ±0,674π y ±0,899π, los dos ángulos arriba del corte en 0,3π.Los ceros de un FIR de fase lineal vienen en pares recíprocos. Si , invertir el orden de los coeficientes no cambia nada, y eso dice . Entonces si es cero, también; y con coeficientes reales, sus conjugados. Cada cero fuera del círculo viene con su espejo , al mismo ángulo y a radio inverso; los que están sobre el círculo son su propio espejo. Con fir1(10, 0.3), 11 coeficientes simétricos, los 10 ceros son: 4 sobre el círculo (en ±0,899π y ±0,674π), un par real en 3,2352 y 0,3091, y cuatro en ±0,654π de radios 1,7253 y 0,5796. Cada cero está a 9,3×10⁻¹⁵ o menos del recíproco conjugado de algún cero de la lista. El control: con 11 coeficientes al azar (rand, semilla 1), sin simetría, el peor cero queda a 0,382 del espejo más cercano.
El FIR de Ejemplo_filtros.m, h = [1 2 3 4 3 2 1]/16, es el caso extremo: los seis ceros están sobre el círculo, dobles, en y en . Es que es la media móvil de 4 convolucionada consigo misma, , así que tiene los ceros de dos veces cada uno. Y seis polos en el origen. Qué más hace un FIR como filtro, y cómo se diseña, está en el filtro FIR; lo mismo para el IIR en el filtro IIR.
Llevá el polo hacia el círculo y mirá cómo sale el pico en su ángulo: el punto azul, al pasarle cerca, divide por una distancia chica. Llevá el cero encima del círculo y el valle baja hasta el fondo del gráfico. Después prendé «FIR»: los polos se van al origen, la distancia a ellos se clava en 1 para todo , y queda hecho sólo de ceros. Y con el polo cerca del círculo, reflejalo: la curva de sube o baja entera sin cambiar de forma, mientras , abajo, explota. El botón del ejemplo deja las raíces del apunte; en las lecturas dan el 19,6088 de freqz.
Un FIR y un IIR de los scripts de la clase, de punta a punta. Lo que figura como comentario es la salida real de correrlo en R2026a.
%% 1. Un FIR: el de Ejemplo_filtros.m h = [1 2 3 4 3 2 1] / 16; [z, p, k] = tf2zpk(h, 1); disp(round(z.', 4)) disp(p.') fprintf('k = %g\n', k) fprintf('max ||z| - 1| = %.1e\n', max(abs(abs(z) - 1))) % -1.0000 + 0.0000i -1.0000 + 0.0000i 0.0000 + 1.0000i 0.0000 - 1.0000i 0.0000 + 1.0000i 0.0000 - 1.0000i % 0 0 0 0 0 0 % k = 0.0625 % max ||z| - 1| = 2.9e-08 %% 2. tf2zp no es para filtros digitales try tf2zp(h, 1); catch e disp(e.message) end [z2, p2] = tf2zp(h, [1 zeros(1, 6)]); % mismo largo arriba y abajo: ahí sí fprintf('%d ceros, %d polos\n', numel(z2), numel(p2)) % Transfer function not proper. % 6 ceros, 6 polos %% 3. La media móvil de 8: ceros en 2*pi*k/8, polos en el origen M = 8; [zm, pm] = tf2zpk(ones(1, M) / M, 1); ang = sort(mod(angle(zm), 2*pi)).'; fprintf('max |arg - 2*pi*k/M| = %.1e\n', max(abs(ang - 2*pi*(1:M-1)/M))) fprintf('%d polos, max |p| = %g\n', numel(pm), max(abs(pm))) % max |arg - 2*pi*k/M| = 8.9e-16 % 7 polos, max |p| = 0 %% 4. Un IIR: el de Clase.m b = [1 1]; a = [1 -sqrt(2)/2]; [zc, pc, kc] = tf2zpk(b, a); fprintf('cero %g, polo %.4f, k = %g, estable: %d\n', zc, pc, kc, all(abs(pc) < 1)) % cero -1, polo 0.7071, k = 1, estable: 1 %% 5. Un IIR todo polos: el de Ejemplo_filtros.m [zt, pt] = tf2zpk(0.1, [1 -0.9]); fprintf('cero %g, polo %g\n', zt, pt) % cero 0, polo 0.9 %% 6. zplane: fila o columna no es lo mismo figure; [hz, hp] = zplane(h, 1); fprintf('fila: %d ceros, %d polos\n', numel(hz.XData), numel(hp.XData)) figure; [hz, hp] = zplane(h.', 1); fprintf('columna: %d ceros, %d polos\n', numel(hz.XData), numel(hp.XData)) % fila: 6 ceros, 6 polos % columna: 7 ceros, 1 polos %% 7. freqz contra la lectura geométrica, con el IIR de Clase.m w = [0 0.25 0.5 0.75 1] * pi; % un vector, nunca un escalar H = freqz(b, a, w); E = exp(1j * w); G = abs(kc) * abs(E - zc) ./ abs(E - pc); disp(round(abs(H), 4)) fprintf('max | |H| - por distancias | = %.1e\n', max(abs(abs(H) - G))) % 6.8284 2.6131 1.1547 0.4841 0 % max | |H| - por distancias | = 2.2e-16 %% 8. Los polos en el origen no tocan el módulo del FIR w = linspace(0, 2*pi, 4096); E = exp(1j * w); G = abs(k) * prod(abs(E - z), 1); % sólo los ceros fprintf('max | |H| - desde los ceros | = %.1e\n', max(abs(abs(freqz(h, 1, w)) - G))) % max | |H| - desde los ceros | = 2.8e-15 %% 9. Y de vuelta, con zp2tf [b9, a9] = zp2tf(z, p, k); disp(round(b9 * 16, 10)); disp(a9) % 1 2 3 4 3 2 1 % 1 0 0 0 0 0 0
El del bloque 7 tiene forma cerrada: la distancia de al cero es 2 y al polo es , y . Cinco detalles que muerden:
tf2zp lee los vectores como polinomios en potencias positivas, como en tiempo continuo. Un FIR, con numerador más largo que el denominador, le parece impropio y da error (bloque 2). Y un IIR todo polos le parece sin ceros: tf2zp(1, [1 -1.6 0.8]) no devuelve ninguno, mientras tf2zpk devuelve los dos del origen. Para un filtro digital va tf2zpk, o tf2zp con los dos vectores rellenados al mismo largo.zplane cambia de significado con la forma del vector. Con vectores fila los toma como coeficientes; con vectores columna, como las raíces mismas. zplane(h.', 1) dibuja siete «ceros» en los valores de los coeficientes, 0,0625 a 0,25 sobre el eje real, y un polo: un dibujo que no es de nada (bloque 6).roots separados a una distancia del orden de sqrt(eps), 1,5×10⁻⁸: el módulo de alguno se aparta de 1 en 2,9×10⁻⁸ (bloque 1). Una raíz doble es numéricamente frágil; round lo esconde, zplane igual la marca con un 2.freqz no avisa de la inestabilidad. Evalúa sobre el círculo aunque un polo esté afuera, y devuelve una curva prolija. La estabilidad se mira en los polos, con abs(roots(a)) o con los de tf2zpk, como en el bloque 4.freqz no es una frecuencia. freqz(b, a, 0.3) lee el escalar como la cantidad de puntos. Para evaluar en frecuencias puntuales, un vector de al menos dos, como en el bloque 7.roots o tf2zpk.tf2zpk y no tf2zp; zplane con vectores fila; freqz con un vector de frecuencias.