Esta libreria implementa el algoritmo de mínimos cuadrados recursivos para identificar los parametros de un filtro IIR de la forma:
El algoritmo es una implementación directa del siguiente conjunto de ecuaciones adaptando el tamaño de las matrices y vectores para el caso de una entrada una salida y con menos operaciones
https://onlinegdb.com/7fJCHsTIm
Se incluye una libreta en Mathematica que genera los archivos dataInput.txt y dataOutput.txt que corresponden a las "mediciones" de la entrada y salida del sistema a identificar que son usadas en el archivo main.cpp, este a su vez genera el historial de la identificacion de parametros almacenado en estimatedParams.txt archivo usado en la libreta Mathematica para ser graficados y comparar el modelo "real" contra el modelo estimado. A continuación el modelo real
En la grafica se muestra como se sobreponen las señales generados por ambos filtros para la misma señal de entrada
y la grafica de actualización de parametros donde se observa la convergencia de cada uno, solo aparecen 5 trayectorias porque el uno del denominador es fijo, por ello se estiman 3 parametros para el numerador
Para hacer uso hay que agregarla al proyecto con:
#include "estimationFilters.h"
Se construye el estimador con 4 parametros y el vector
estimationFilters(N,M,lambda,gain,theta_hat);
- N : numero de parámetros en el denominador a estimar
- M : numero de parámetros en el numerador a estimar
- lambda : Factor de olvido entre 0 y 1
- gain : ganancia inicial de la matriz de covarianza diagonal
- theta_hat : el arreglo que guarda los parametros estimados
void _estimationRLS(double u, double y, double* theta_hat);
Asigna al array theta_hat los parametros estimados para la medicion de entrada u y salida y actual
#include "fractionalOrderFilter.h"
int main() {
int L = cantidad de mediciones;
double u[L] = {mediciones entrada};
double y[L] = {mediciones salida};
int M = Cantidad de coeficientes de numerador a estimar
int N = Cantidad de coeficientes de denominador a estimar
int lambda = 1; //sin olvido
int gain = 100000;
double theta_hat[M+N]; //Vector de parametros estimados
estimationFilters RLS(N,M,lambda,gain,theta_hat);
for(int i = 0; i < L;i++){
RLS._estimationRLS(u[i],y[i],theta_hat); //Estimacion para cada muestra
}
return 0;
}
Al ser una implementación "Vanilla" la matriz de covarianza puede crecer exponencialmente al no estar acotada y el vector de Ganancia no está condicionado, por lo que no puede estimar donde existan cambios bruscos o donde la señal sea constante para un largo periodo de tiempo.
Hacer uso de una señal en la entrada que cumpla la condición de excitación persistente (en la practica una señal con varios armónicos). Si se trata de un sistema lineal variante en el tiempo usar un valor menor a uno para que el pasado tenga menos importancia. El valor de la ganancia puede ser pequeño (ej. 1, 10, 50) si se cuenta con una gran cantidad de datos, si son pocos hacer uso de valores mas grandes (1000,10000,1000000) para acelerar la convergencia.
Las contribuciones son bienvenidas. Por favor, abre un issue o envía un pull request para contribuir al desarrollo de esta librería.
Adaptive Control: Second Edition. Karl J. Åström, Björn Wittenmark. Addison - Wesley Publishing Company, 1995.
- C++11 o superior
Para utilizar esta librería, simplemente clona el repositorio y compila el archivo main.cpp
.
git clone [https://github.com/jafetrd/recursiveLeastSquares]
cd recursiveLeastSquares
g++ -std=c++11 main.cpp -o main