martes, 17 de abril de 2012

Sistema de Control - Error con Suerte

Algoritmo de Control

Ya identificado el modelo se plantea un algoritmo de control generalizado (o Generalized Predictive Control - GPC) donde se plantea un funcional a minimizar y se itera desde un punto de inicio hacia una solución óptima tomando un paso del gradiente en cada iteración.  Trataremos de dar una explicación más detallada en otro post.
En este caso, la función a minimizar es la norma de los valores medidos de salida (los sensores colocados a cada lado del cilindro) más un costo por la utilización del actuador de plasma. El resultado esperado es minimizar la magnitud medida en los sensores, consiguiendo que los trazadores escurran por el eje central, utilizando la menor cantidad de energía posible en los actuadores.

Primera Implementación

La primer implementación del sistema requirió de las técnicas de comunicación ya descriptas entre Fortran y C++. En efecto, fue necesario detener el algoritmo de Code Saturne (Fortran) para informar y esperar un valor de actuación del algoritmo controlador (C++).
Como agregado, dados los cambios y correcciones frecuentes en la minimización del funcional y la identificación ARX del modelo, parte del código se realizó en Matlab por lo que se empleó MEX para su ejecución.

Un Error en el Código con Resultados Prometedores

Aún luego de emplear varias horas en revisar los cálculos y comunicación entre procesos, no se pudo evitar que se filtrara un error de programación.
En este caso el error fue tan simple como iniciar a cero la variable de acumulación para cada iteración. El efecto inmediato fue que el algoritmo no avanzara hacia una solución del funcional sino que mantuviera una relación de proporción con la magnitud de los trazadores. Por fortuna, esta relación también provee un esquema de control que, aunque rudimentario, resuelve el objetivo final. De esta forma el valor del actuador aumenta si la norma de los trazadores aumenta y disminuye si así lo hacen los trazadores.

Resultados de la Simulación

El resultado final es un actuador oscilante con frecuencia similar al experimento. A continuación se muestran los valores de actuación computados por el algoritmo de control. En este caso se plantea un control con inicio en el paso 6000 de la simulación, luego de entrar en régimen estacionario.
El algoritmo fuerza una actuación discontínua al inicio pero luego retoma un función de oscilación suave y con la frecuencia del experimento.
Los valores medidos en los sensores se pueden observar en el siguiente gráfico:
Luego de la actuación, y omitiendo el caso de discontinuidad, se puede observar una gran reducción en el valor medido, producto del soplido de plasma.

El siguiente video ilustra los resultados previos:




viernes, 6 de abril de 2012

Comunicación C++ - Matlab

Otro punto de contacto entre las plataformas fue encontrado en el algoritmo de control a realizar por lo que fue necesario investigar las librerías MEX.

El escenario es sencillo, se posee código C/C++ que debe comunicarse con Matlab enviando matrices y efectuando procesamiento con funciones de toolkits conocidos. Una vez concluido el procesamiento, se debe recuperar los valores de las matrices resultantes.

Para ilustrar este tipo de comunicación dejamos un ejemplo simple sobre cómo se efectúa una operación básica en Matlab desde C/C++.
#include <string.h>
#include <stdio.h>
#include "engine.h"
#define BUFSIZE 1024

int main(int argc, char* argv[]) {
        Engine* ep;
        if (!(ep = engOpen("\0"))) {
                fprintf(stderr, "\nCan't start MATLAB engine\n");
                return 1;
        }
        else {
                char buffer[BUFSIZE+1];
                memset(buffer, 0, sizeof(buffer));
                engOutputBuffer(ep, buffer, sizeof(buffer) - 1);
                engEvalString(ep, "pi^2");
                printf("Evaluating: pi^2. \nResult: %s\n", buffer);
                engClose(ep);
                return 0;
        }
}
 Existen ciertas compilaciones para compilar y ejecutar el código anterior. La manera más fácil es sin duda realizarlo por la consola de Matlab:
>> mex('-v', '-f', fullfile(matlabroot,'bin','engopts.sh'),'main.cpp')
 -> g++-4.0 -c  -I/Applications/MATLAB_R2010a.app/extern/include[...] -DMACI64  -DMX_COMPAT_32 -O2 -DNDEBUG  "main.cpp"
 -> gcc-4.0 -O -Wl,-twolevel_namespace -undefined error -arch x86_64[...] -mmacosx-version-min=10.5 -o  "main"  main.o  -L/Applications/MATLAB_R2010a.app/bin/maci64 -leng -lmx -lstdc++
>> !./main
Evaluating: pi^2.
Result: >>
ans =

    9.8696
Para realizar la compilación por línea de comando, notar el uso de la variable matlabroot. En su directorio bin se puede encontrar el comando mex y la librería de configuración engopts.sh.
$ /Applications/MATLAB_R2010a.app/bin/mex -v -f /Applications/MATLAB_R2010a.app/bin/engopts.sh main.cpp -o main
Si bien la compilación no se realiza con el comando gcc sino con mex, la ejecución sólo requiere que Matlab y csh estén instalados sin cambiar la línea de comando.