{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "## Libreria de control\n", "try:\n", " from control.matlab import *\n", "except:\n", " !pip install control\n", " from control.matlab import *\n", " \n", "## Libreria para graphicar\n", "import matplotlib.pyplot as plt\n", "import numpy\n", "\n", "## Libreria para calculo simbolico\n", "import sympy\n", "\n", "## Libreria de control\n", "import control\n", "\n", "## Libreria para widgets\n", "import ipywidgets as widgets\n", "\n", "## Libreria para animaciones\n", "from matplotlib.animation import FuncAnimation\n", "plt.rcParams[\"animation.html\"] = \"html5\"#\"jshtml\"\n", "\n", "## Libreria para importar Iframe de Youtube\n", "from IPython.display import IFrame" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Diseño de controladores\n", "_controlemos el mundo_\n", "\n", "![](pinky-and-the-brain.jpg)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Estabilizando una masa puntual\n", "\n", "Dado un sistema lineal: \n", "\n", "$$\\dot{x}=A\\,x+B\\,u \\qquad y \\qquad y=C\\,x$$\n", "\n", "- El dilema es que necesitamos $x$ pero lo único de tenemos es $y$\n", "- El plan es diseñar el controlador $u$ como si tuvieramos $x$\n", "- Decifrar $x$ a partir de $y$\n", "\n", "**Paso #1** : Diseña la realimentación de estados usando el posicionamiento de polos. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Retomando la masa puntual\n", "\n", "$$\\dot{x}=A\\,x+B\\,u \\qquad A=\\left[\\array{0&1\\\\0&0}\\right] \\qquad B=\\left[\\array{0\\\\1}\\right]$$\n", "\n", "Supongamos una realimentación de estados\n", "\n", "$$u=-K\\,x = - \\left[\\array{k_1&k_2}\\right]x $$\n", "\n", "¿Cómo seleccionamos la ganancia de los controladores?\n", "\n", "**Idea:** Seleccionarlas para ubicar los polos del sistema en los valores deseados (_posicionamiento de polos_)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Calculando los valores propios (polos)\n", "\n", "Dada una matriz $M$, sus valores propios satisfacen la ecuación característica:\n", "\n", "$$\\chi M (\\lambda) = \\text{det}(\\lambda\\,I- M) = 0$$\n", "\n", "Para una matriz $M$ (2x2):\n", "\n", "$$M=\\left[\\array{ m_1 & m_2 \\\\ m_3 & m_4 }\\right]$$\n", "\n", "tendremos:\n", "\n", "$$\\lambda\\,I- M = \\lambda\\left[\\array{ 1 & 0 \\\\ 0 & 1 }\\right]-M = \\left[\\array{ \\lambda - m_1 & -m_2 \\\\ -m_3 & \\lambda-m_4 }\\right]$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Calculando los valores propios (polos) #2\n", "\n", "Dada una matriz $M$, sus valores propios satisfacen la ecuación característica:\n", "\n", "$$\\chi M (\\lambda) = \\text{det}(\\lambda\\,I- M) = 0$$\n", "\n", "continuando:\n", "\n", "$$\\text{det}(\\lambda\\,I- M) = \\left|\\array{ \\lambda - m_1 & -m_2 \\\\ -m_3 & \\lambda-m_4 }\\right| $$\n", "$$ = (\\lambda - m_1)(\\lambda-m_4)-m_2m_3$$\n", "$$ = \\lambda^2-(m_1+m_4)\\lambda+m_1m_4-m_2m_3 = 0$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Calculando los valores propios (polos) #3\n", "\n", "Dada una matriz $M$, sus valores propios satisfacen la ecuación característica:\n", "\n", "$$\\chi M (\\lambda) = \\text{det}(\\lambda\\,I- M) = 0$$\n", "\n", "continuando:\n", "\n", "$$\\chi M (\\lambda) = \\lambda^2-(m_1+m_4)\\lambda+m_1m_4-m_2m_3 = 0$$\n", "\n", "de aquí tenemos:\n", "\n", "$$\\lambda = \\frac{m1+m4}{2}\\pm \\sqrt{\\frac{(m1+m4)^2}{4}-m_1m_4+m_2m_3}$$\n", "\n", "¿Hay una forma más sencilla de hacer esto?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# # Calculando los valores propios (polos) #4\n", "\n", "El teorema fundamental del algebra dice:\n", "\n", "\"_Las raices de un polinomio estan completamente determinadas por sus coeficientes_\"\n", "\n", "$$\\chi M (\\lambda) = \\lambda^2-(m_1+m_4)\\lambda+m_1m_4-m_2m_3 = 0$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Retomando la masa puntual #2\n", "\n", "De $\\dot{x}=A\\,x+B\\,u$ y $u=-K\\,x$ tenemos que $\\dot{x}=(A-BK)x$\n", "\n", "entonces:\n", "\n", "$$A-BK = \\left[\\array{0&1\\\\0&0}\\right] - \\left[\\array{0\\\\1}\\right]\\left[\\array{k_1&k_2}\\right] = \\left[\\array{0&1\\\\-k_1&-k_2}\\right]$$\n", "\n", "luego,\n", "\n", "$$\\chi A-BK (\\lambda) = \\left|\\array{\\lambda&-1\\\\k_1&\\lambda+k_2}\\right| = \\lambda^2+\\lambda k_2+k_1$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Valores propios deseados\n", "\n", "Seleccionemos los valores propios que queramos que el sistema en lazo cerrado tenga.\n", "\n", "$$\\lambda_1,\\ldots,\\lambda_n$$\n", "\n", "Si estos son los valores propios del sistema entonces, el polinomio característico sería\n", "\n", "$$\\varphi(\\lambda) = (\\lambda-\\lambda_1)(\\lambda-\\lambda_2)\\cdots(\\lambda-\\lambda_n)=\\prod_{i=1}^n(\\lambda-\\lambda_i)$$\n", "\n", "Para el robot tomemos ambos valores propios como $-1$\n", "\n", "$$\\varphi(\\lambda) = (\\lambda+1)(\\lambda+1) = \\lambda^2+2\\lambda+1$$\n", "\n", "Ahora solo alineamos los coeficientes" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Alineando los coeficientes\n", "\n", "De anteriores diapositivas:\n", "\n", "$$\\chi A-BK (\\lambda) = \\lambda^2+\\lambda k_2+k_1$$\n", "\n", "$$\\varphi(\\lambda) = (\\lambda+1)(\\lambda+1) = \\lambda^2+2\\lambda+1$$\n", "\n", "alineando:\n", "\n", "$$\\array{\n", "\\lambda^1: & k_2 = 2\\\\\n", "\\lambda^2: & k_1 = 1} \\qquad \\text{entonces} \\qquad K=\\left[\\array{1&2}\\right]$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Posicionamiento de polos\n", "\n", "Es seleccionar las ganancias del controlador de tal manera que los polos del sistema en lazo cerrado concuerden con los polos deseados. \n", "\n", "$$\\array{ \n", "& \\chi A-BK (\\lambda) =& \\lambda^n + a_{n-1}\\lambda^{n-1}+\\ldots+a_1\\lambda+a_0\\\\ \n", "\\varphi(\\lambda) =& \\prod_{i=1}^n(\\lambda-\\lambda_i) =& \\lambda^n + b_{n-1}\\lambda^{n-1}+\\ldots+b_1\\lambda+b_0}$$\n", "\n", "Las ganacias del controlador saldrán del sistema de ecuaciones generado:\n", "\n", "$$\\array{\n", "\\lambda^n_1: & a_{n-1}(K) = b_{n-1}\\\\\n", "&\\vdots \\\\\n", "\\lambda^0: & a_0(K) = b_0}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Preguntas sobre el posicionamiento de polos\n", "\n", "- ¿Es siempre posible? no\n", "- ¿Cómo seleccionamos el valor de los polos? es un arte\n", "- ¿Tenemos que computar grandes determinantes? no\n", "\n", "en MATLAB:\n", "\n", "```\n", ">> P = [lambda1,lambda2,lambda3,...];\n", ">> K = place(A,B,P);\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Ejemplo\n", "\n", "Dado el siguiente sistema ubicar los polos en $-1$,\n", "$$\\dot{x}=A\\,x+B\\,u \\qquad A=\\left[\\array{2&0\\\\1&1}\\right] \\qquad B=\\left[\\array{1\\\\1}\\right] \\qquad u=-K\\,x = - \\left[\\array{k_1&k_2}\\right]x$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "El sistema en lazo cerrado:\n", "\n", "$$A-BK = \\left[\\array{2-k_1&-k_2\\\\1-k_1&1-k_2}\\right]$$\n", "\n", "$$\\chi A-BK(\\lambda) = \\left|\\array{\\lambda-2+k_1&k_2\\\\-1+k_1&\\lambda-1+k_2}\\right| = \\lambda^2+\\lambda\\, (-3+k_1+k_2)+2-k_1-k_2$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Ejemplo\n", "\n", "de la ecuación caracteristica y el polinomio. \n", "\n", "$$\\array{ \n", "\\chi A-BK (\\lambda) =& \\lambda^2+\\lambda\\, (-3+k_1+k_2)+2-k_1-k_2\\\\ \n", "\\varphi(\\lambda) =& (\\lambda+1)^2 \\lambda^2 + 2\\lambda+1}$$\n", "\n", "asociando:\n", "\n", "$$\\array{\n", "\\lambda^1: & -3 + k_1 + k_2 = 2\\\\\n", "\\lambda^2: & 2 - k_1 - k_2 = 1} \\qquad \\to \\qquad \n", "\\array{\n", "k_1 + k_2 = 5\\\\\n", "k_1 + k_2 = 1}$$\n", "\n", "Lo que ocurre con este ejemplo es una falta de controlabilidad, es decir, el efecto de las entradas no es lo suficientemente rico para influenciar el sistema. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Cómo elegir los polos\n", "\n", "Asumiendo que tenemos suficiente autoridad en el control para hacer el posicionamiento de los polos. \n", "\n", "**no existe una única respuesta**\n", "\n", "Algunas observaciones para tener en cuenta:\n", "\n", "- Pares de polos complejos conjugados\n", " $$\\text{Im}(\\lambda_i)\\neq 0 \\to \\exists \\lambda_j : \\text{Im}(\\lambda_j)=-\\text{Im}(\\lambda_i), \\text{Re}(\\lambda_j)=\\text{Re}(\\lambda_i) $$\n", "- Estabilidad \n", " $$\\text{Re}(\\lambda_i) < 0, \\forall \\lambda_i $$\n", "- Habrán oscilaciones\n", " $$\\text{Im}(\\lambda_i)\\neq 0$$\n", "- Tasa de convergencia" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Tasa de convergencia ~ tiempo de respuesta\n", "\n", "Teniendo,\n", "\n", "$$\\dot{x} = (A-BK)\\, x,\\qquad \\text{Re}(\\lambda)<0, \\qquad \\forall\\lambda \\in \\text{eig}(A-BK)$$\n", "\n", "el valor propio más pequeño dominará la tasa de convergencia ~ tiempo de respuesta:\n", "\n", "$$\\lambda{min} = \\text{argmin}_\\lambda|\\text{Re}(\\lambda)|$$\n", "\n", "entre más grandes los valores de los polos, más grandes las ganancias del controlador y las señales de control. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Del ejemplo anterior en MATLAB\n", "\n", "```matlab\n", "% Matrices del sistema\n", " A = [2,0;1,-1]; \n", " B = [1;1];\n", "\n", "% Selecionemos los polos\n", " P = [-0.5+1i,-0.5-1i];\n", "\n", "% Realicemos el posicionamiento de polos\n", " K = place(A,B,P);\n", "\n", "% Calculemos la solución\n", " x=[1;1]; t=0; tf=30; dt=0.01;\n", " X=[]; T=[];\n", " \n", "while (t> G = ctrb(A,B);\n", ">> rank(G); \n", " ans: 2\n", "```" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD4CAYAAADiry33AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAARPElEQVR4nO3cf4xlZX3H8fcHlwWJUn7sBFcWWEixSlujdMRfUdAaBf5glVoFMQK12fqr/zQmhewfNhhqqzY2RAKlZktRAlqq7RoxiPwIMXGtQ5RfEmDAKLuu7ChCQjaiwrd/3DN6GWfmzsyemWEf3q/k5p7zPM855zvPvfu5Z865s6kqJEnt2m+1C5AkLS+DXpIaZ9BLUuMMeklqnEEvSY1bs9oFzLRu3brauHHjapchSfuU22+//WdVNTZb37Mu6Ddu3MjExMRqlyFJ+5QkP5qrz0s3ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktS4kUGfZGuS3UnunqM/SS5JMpnkziQnzug/OMmOJJ/tq2hJ0sIt5Iz+SuDUefpPA47vHpuBy2b0fxy4bSnFSZL23sigr6rbgEfnGbIJuKoGtgOHJFkPkOTPgCOAb/RRrCRp8fq4Rn8k8PDQ+g7gyCT7Af8CfHTUDpJsTjKRZGJqaqqHkiRJ05bzZuyHgOuraseogVV1RVWNV9X42NjYMpYkSc89a3rYx07gqKH1DV3ba4E3JPkQ8AJgbZInquqCHo4pSVqgPoJ+G/CRJNcCrwYer6pdwDnTA5KcB4wb8pK08kYGfZJrgFOAdUl2AB8D9geoqsuB64HTgUlgD3D+chUrSVq8kUFfVWeP6C/gwyPGXMnga5qSpBXmX8ZKUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxo0M+iRbk+xOcvcc/UlySZLJJHcmObFrf0WSbye5p2t/d9/FS5JGW8gZ/ZXAqfP0nwYc3z02A5d17XuA91XVH3fb/2uSQ5ZcqSRpSdaMGlBVtyXZOM+QTcBVVVXA9iSHJFlfVfcP7eMnSXYDY8Bje1mzJGkR+rhGfyTw8ND6jq7tt5KcBKwFHuzheJKkRVj2m7FJ1gOfB86vqqfnGLM5yUSSiampqeUuSZKeU/oI+p3AUUPrG7o2khwMfA3YUlXb59pBVV1RVeNVNT42NtZDSZKkaX0E/Tbgfd23b14DPF5Vu5KsBb7C4Pr9dT0cR5K0BCNvxia5BjgFWJdkB/AxYH+AqrocuB44HZhk8E2b87tN3wW8ETg8yXld23lV9f3+ypckjbKQb92cPaK/gA/P0v4F4AtLL02S1Af/MlaSGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMaNDPokW5PsTnL3HP1JckmSySR3JjlxqO/cJA90j3P7LHw2u3bBySfDT3+63EeSpB5dfTVs3Aj77Td4vvrqXne/kDP6K4FT5+k/DTi+e2wGLgNIchjwMeDVwEnAx5IcujfFjvLxj8O3vgUXXbScR5GkHl19NWzeDD/6EVQNnjdv7jXsRwZ9Vd0GPDrPkE3AVTWwHTgkyXrgbcCNVfVoVf0CuJH5PzCW7PnPhwQuuwyefnrwnAzaJelZbcsW2LPnmW179gzae9LHNfojgYeH1nd0bXO1/54km5NMJJmYmppadAEPPQTveQ8cdNBg/aCD4Jxz4Ic/XPSuJGll/fjHi2tfgmfFzdiquqKqxqtqfGxsbNHbr18PBx8Mv/wlHHjg4Pngg+FFL1qGYiWpT0cfvbj2Jegj6HcCRw2tb+ja5mpfFo88Ah/4AGzfPnj2hqykfcLFF//ucsS0gw4atPdkTQ/72AZ8JMm1DG68Pl5Vu5LcAPzj0A3YtwIX9nC8WX35y79bvvTS5TqKJPXsnHMGz1u2DC7XHH30IOSn23swMuiTXAOcAqxLsoPBN2n2B6iqy4HrgdOBSWAPcH7X92iSjwPf7XZ1UVXNd1NXkp6bzjmn12CfaWTQV9XZI/oL+PAcfVuBrUsrTZLUh2fFzVhJ0vIx6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGregoE9yapL7kkwmuWCW/mOS3JTkziS3Jtkw1PfJJPckuTfJJUnS5w8gSZrfyKBP8jzgUuA04ATg7CQnzBj2aeCqqno5cBHwiW7b1wGvB14O/AnwKuDk3qqXJI20kDP6k4DJqnqoqn4FXAtsmjHmBODmbvmWof4CDgTWAgcA+wOP7G3RkqSFW0jQHwk8PLS+o2sbdgdwZrf8DuCFSQ6vqm8zCP5d3eOGqrp370qWJC1GXzdjPwqcnOR7DC7N7ASeSvKHwMuADQw+HN6c5A0zN06yOclEkompqameSpIkwcKCfidw1ND6hq7tt6rqJ1V1ZlW9EtjStT3G4Ox+e1U9UVVPAF8HXjvzAFV1RVWNV9X42NjY0n4SSdKsFhL03wWOT3JskrXAWcC24QFJ1iWZ3teFwNZu+ccMzvTXJNmfwdm+l24kaQWNDPqq+g3wEeAGBiH9paq6J8lFSc7ohp0C3JfkfuAI4OKu/TrgQeAuBtfx76iqr/b7I0iS5pOqWu0anmF8fLwmJiZWuwxJ2qckub2qxmfr8y9jJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklq3IKCPsmpSe5LMpnkgln6j0lyU5I7k9yaZMNQ39FJvpHk3iQ/SLKxx/olSSOMDPokzwMuBU4DTgDOTnLCjGGfBq6qqpcDFwGfGOq7CvhUVb0MOAnY3UfhkqSFWcgZ/UnAZFU9VFW/Aq4FNs0YcwJwc7d8y3R/94GwpqpuBKiqJ6pqTy+VS5IWZCFBfyTw8ND6jq5t2B3Amd3yO4AXJjkceAnwWJIvJ/lekk91vyE8Q5LNSSaSTExNTS3+p5Akzamvm7EfBU5O8j3gZGAn8BSwBnhD1/8q4DjgvJkbV9UVVTVeVeNjY2M9lSRJgoUF/U7gqKH1DV3bb1XVT6rqzKp6JbCla3uMwdn/97vLPr8B/gc4sYe6JUkLtJCg/y5wfJJjk6wFzgK2DQ9Isi7J9L4uBLYObXtIkunT9DcDP9j7siVJCzUy6Lsz8Y8ANwD3Al+qqnuSXJTkjG7YKcB9Se4HjgAu7rZ9isFlm5uS3AUE+PfefwpJ0pxSVatdwzOMj4/XxMTEapchSfuUJLdX1fhsff5lrCQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXGpqtWu4RmSTAE/2otdrAN+1lM5fbKuxbGuxbGuxWmxrmOqamy2jmdd0O+tJBNVNb7adcxkXYtjXYtjXYvzXKvLSzeS1DiDXpIa12LQX7HaBczBuhbHuhbHuhbnOVVXc9foJUnP1OIZvSRpiEEvSY3bJ4M+yV8muSfJ00nm/CpSklOT3JdkMskFQ+3HJvlO1/7FJGt7quuwJDcmeaB7PnSWMW9K8v2hxy+TvL3ruzLJD4f6XrFSdXXjnho69rah9tWcr1ck+Xb3et+Z5N1Dfb3N11zvlaH+A7qffbKbi41DfRd27fcledtSa1hiXX+X5Afd3NyU5JihvllfzxWs7bwkU0M1/PVQ37nd6/5AknNXsKbPDNVzf5LHhvqWbb6SbE2yO8ndc/QnySVd3XcmOXGob+/nqqr2uQfwMuCPgFuB8TnGPA94EDgOWAvcAZzQ9X0JOKtbvhz4YE91fRK4oFu+APjnEeMPAx4FDurWrwTeuQzztaC6gCfmaF+1+QJeAhzfLb8Y2AUc0ud8zfdeGRrzIeDybvks4Ivd8gnd+AOAY7v9PK+n+VlIXW8aev98cLqu+V7PFaztPOCzs2x7GPBQ93xot3zoStQ0Y/zfAltXaL7eCJwI3D1H/+nA14EArwG+0+dc7ZNn9FV1b1XdN2LYScBkVT1UVb8CrgU2JQnwZuC6btx/Am/vqbRN3f4Wut93Al+vqj09HX8ui63rt1Z7vqrq/qp6oFv+CbAbmPWv//bCrO+VeWq9Dvjzbm42AddW1ZNV9UNgstvfitRVVbcMvX+2Axt6OvZe1zaPtwE3VtWjVfUL4Ebg1FWo6Wzgmh6OO1JV3cbgpG4um4CramA7cEiS9fQ0V/tk0C/QkcDDQ+s7urbDgceq6jcz2vtwRFXt6pZ/ChwxYvxZ/P4b7eLuV7fPJDlghes6MMlEku3Tl5N4Fs1XkpMYnKk9ONTcx3zN9V6ZdUw3F48zmJuFbLtUi933+xmcFU6b7fXsy0Jr+4vu9bkuyVGL3Ha5aqK7xHUscPNQ83LO1yhz1d7LXK3Zq9KWUZJvAi+apWtLVf3vStczbb66hleqqpLM+d3V7tP6T4EbhpovZBB4axl8n/bvgYtWsK5jqmpnkuOAm5PcxSDQlqzn+fo8cG5VPd01L3m+WpPkvcA4cPJQ8++9nlX14Ox7WBZfBa6pqieT/A2D34jevILHn89ZwHVV9dRQ22rP17J51gZ9Vb1lL3exEzhqaH1D1/ZzBr8WrenOzKbb97quJI8kWV9Vu7pg2j3Prt4FfKWqfj207+mz2yeT/Afw0ZWsq6p2ds8PJbkVeCXw36zyfCU5GPgagw/57UP7XvJ8zTDXe2W2MTuSrAH+gMF7aSHbLtWC9p3kLQw+OE+uqien2+d4PfsKrpG1VdXPh1Y/x+CezPS2p8zY9taVqGnIWcCHhxuWeb5Gmav2Xuaq5Us33wWOz+AbI2sZvLDbanCH4xYG18cBzgX6+g1hW7e/hez3964PdmE3fV387cCsd+iXo64kh05f+kiyDng98IPVnq/utfsKg+uX183o62u+Zn2vzFPrO4Gbu7nZBpyVwbdyjgWOB/5viXUsuq4krwT+DTijqnYPtc/6evZU10JrWz+0egZwb7d8A/DWrsZDgbfyzN9sl62mrq6XMrix+e2htuWer1G2Ae/rvn3zGuDx7kSmn7larrvMy/kA3sHgWtWTwCPADV37i4Hrh8adDtzP4FN5y1D7cQz+MU4C/wUc0FNdhwM3AQ8A3wQO69rHgc8NjdvI4JN6vxnb3wzcxSCwvgC8YKXqAl7XHfuO7vn9z4b5At4L/Br4/tDjFX3P12zvFQaXgc7olg/sfvbJbi6OG9p2S7fdfcBpPb/XR9X1ze7fwPTcbBv1eq5gbZ8A7ulquAV46dC2f9XN5SRw/krV1K3/A/BPM7Zb1vlicFK3q3sv72BwP+UDwAe6/gCXdnXfxdC3CfuYK/8LBElqXMuXbiRJGPSS1DyDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcf8P9cxJH3vgk3cAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(-1,1,'*b');\n", "plt.plot(1,1,'or');" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Observadores\n", "\n", "Sabemos diseñar controladores efectivamente usando la realimentación del estado. Pero como hacemos con $y$ ? \n", "\n", "A partir de la medida $y$ debemos encontrar los estados del sistema $x$ a traves de una predición $\\hat{x}$." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Predictor-Corrector\n", "\n", "Supongamos un sistema:\n", "\n", "$$\\dot{x}=A\\,x \\qquad y=C\\, x$$\n", "\n", "1. **Primer idea** hagamos una copia del sistema (predictor):\n", " $$\\dot{\\hat{x}}= A\\, \\hat{x}$$\n", "2. **Segunda idea** agreguemos la noción de cuan mal estimamos el modelo (correcto). \n", " $$\\dot{\\hat{x}}= A\\, \\hat{x} + L(y-C\\, \\hat{x})$$\n", " \n", "Esto se conoce como el observador de **Luenberger**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Elegiendo la ganancia del observador\n", "\n", "Lo que queremos estabilizar (llevar a cero) es la estimación del error, es decir, la diferencia del estado actual y la estimación del estado $e=x-\\hat{x}$\n", "\n", "$$\\dot{e} = \\dot{x} - \\dot{\\hat{x}} = Ax - A\\hat{x} - L(y-C\\hat{x}) \\qquad \\text{con} \\qquad y=Cx$$\n", "\n", "luego,\n", "\n", "$$\\dot{e} = A(x-\\hat{x}) - LC(x-\\hat{x}) = (A-LC)e$$\n", "\n", "por lo que debemos elegir L de tal forma que los valores propios de $A-LC$ tenga parte real negativa. \n", "\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Nuevamente posicionamiento de polos\n", "\n", "\n", "$$\\dot{e} = (A-LC)e$$\n", "\n", "queremos \n", "\n", "$$\\text{Re}\\left(\\text{eig}(A-LC)\\right)<0$$\n", "\n", "ya sabemos hacer posicionamiento de polos. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Ejemplo\n", "\n", "Partimos de: \n", "\n", "$$\\dot{x} = \\left[\\array{-1&2\\\\0&-2}\\right]x \\qquad y = \\left[\\array{1&-1}\\right]x$$\n", "\n", "el error será:\n", "\n", "$$\\dot{e} = (A-LC)e = \\left(\\left[\\array{-1&2\\\\0&-2}\\right]-\\left[\\array{L_1\\\\L_2}\\right]\\left[\\array{1&-1}\\right]\\right)e$$\n", "$$\\dot{e}= \\left[\\array{-1-L_1&2+L_1\\\\-L_2&-2+L_2}\\right]e$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Ejemplo \n", "\n", "$$\\dot{e}= \\left[\\array{-1-L_1&2+L_1\\\\-L_2&-2+L_2}\\right]e$$\n", "\n", "Ecuación característica:\n", "\n", "$$\\chi A-LC (\\lambda) = \\left|\\array{\\lambda+1+L_1&-2-L_1\\\\L_2&\\lambda+2-L_2}\\right|$$\n", "$$\\chi A-LC (\\lambda) = \\lambda^2 + \\lambda (3+L_1-L_2) + 2 + 2L_1+L_2$$\n", "\n", "$$\\varphi(\\lambda) = (\\lambda+1)^2 = \\lambda^2 + 2\\lambda+1$$\n", "\n", "de aquí:\n", "\n", "$$L_1 = -2/3 \\qquad \\text{y} \\qquad L_2=1/3$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Ejemplo\n", "\n", "$$\\dot{\\hat{x}} = A\\hat{x} + \\frac{1}{3}\\left[\\array{-2\\\\1}\\right](y-C\\,\\hat{x})$$\n", "\n", "$$\\dot{x} = \\left[\\array{-1&2\\\\0&-2}\\right]x \\qquad y = \\left[\\array{1&-1}\\right]x$$\n", "\n", "Podemos diseñar observadores todo el tiempo? " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Observabilidad\n", "\n", "Necesitamos hacer lo que hicimos para el diseño del controlador para entender cuando podemos recuperar la información del estado de la salidad. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Un ejemplo modesto\n", "\n", "- Dado un sistema en tiempo discreto:\n", " $$x_{k+1}= A\\, x_k \\qquad y_k = C x_k$$\n", " \n", "- ¿Podemos recuperar la condición inicial recolectando n valores de salida? \n", "\n", "$$\n", "\\array{\n", "y_0 &=& Cx_0 \\\\\n", "y_1 &=& Cx_1 &=& CAx_0 \\\\\n", "&\\vdots\\\\\n", "y_{n-1} &=& Cx_{n-1} &=& CA^{n-1}x_0\n", "}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# La matriz de observabilidad\n", "\n", "$$\\left[\\array{y_0\\\\y_1\\\\y_2\\\\\\vdots\\\\y_{n-1}}\\right] = \\left[\\array{C\\\\CA\\\\CA^2\\\\\\vdots\\\\CA^{n-1}}\\right]\\,x_0 = \\Omega x_0$$\n", "\n", "donde $\\Omega$ es la matriz de observabilidad. La condición inicial del sistema puede ser recuperadad de las medidas/salidas del sistema cuando la matriz de observabilidad tiene rango completo. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Observabilidad : Teorema 1\n", "\n", "Dado un sistema: \n", "\n", " $$x_{k+1}= A\\, x_k \\qquad y_k = C x_k \\qquad x \\in \\mathscr{R}^n$$\n", " \n", "**Definición** el sistema es completamente observable (CO) si es posible recuperar la condicion inicial a partir de su salida.\n", "\n", "$$\\Omega = \\left[\\array{C\\\\CA\\\\CA^2\\\\\\vdots\\\\CA^{n-1}}\\right]$$\n", "\n", "**Teorema 1** el sistema es CO si y solo si \n", "\n", "$$\\text{rank}\\left(\\Omega\\right) = n$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Observabilidad : Teorema 2\n", "\n", "Dado un estimador:\n", "\n", "$$\\dot{\\hat{x}}= A\\, \\hat{x} + L(y-C\\, \\hat{x}) \\qquad \\dot{e} = (A-LC)e$$ \n", "\n", "**Teorema 2** se puede hacer un posicionamiento de polos arbitrariamente si y solo if el sistema es CO." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# El principio de separación \n", "\n", "Estamos muy cerca de poder diseñar controladores como si tuvieramos el estado $x$ aunque solo conozcamos $y$, ya que podemos estimar $x$.\n", "\n", "En este momento tenemos muchos buenos bloques para construir un controlador: \n", "\n", "- Controlabilidad\n", "- Observabilidad\n", "- Realimentación del estado\n", "- Observadores\n", "- Posicionamiento de polos\n", "\n", "¿Cómo ponemos todo esto juntos? \n", "\n", "El principio de separación " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Lista de pasos para diseñar un controlador\n", "\n", "Tenemos un sistema:\n", "\n", "$$\\dot{x}=Ax+Bu \\qquad y=Cx$$\n", "\n", "asumiendo CC y CO.\n", "\n", "**Paso 1** Diseñamos un control en realimentación de estado como si conocieramos $x$.\n", "\n", "$$u=-Kx \\quad\\to\\quad \\dot{x} = (A-BK)x$$\n", "\n", "aunque solo conozcamos $\\hat{x}$\n", "\n", "$$u=-K\\hat{x}$$\n", "\n", "**Paso 2** Estimar $x$ usando un observador (en este caso también contiene $u$).\n", "\n", "$$\\dot{\\hat{x}}=A\\hat{x}+Bu+L(y-C\\hat{x})$$\n", "\n", "encontrando $L$ para:\n", "\n", "$$\\dot{e}=(A-LC)e$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Esto funciona? \n", "\n", "Queremos estabilizar ambos $x$ y $e$. Analizemos la dinámica conjunta. \n", "\n", "$$\\dot{x} = Ax - BK \\hat{x} = Ax - BK(x-e)= (A-BK)x + BK e$$\n", "$$\\dot{e} = (A-LC)e \\qquad e= x-\\hat{x}$$\n", "\n", "Podemos verlo en conjunto:\n", "\n", "$$\\left[\\array{\\dot{x}\\\\\\dot{e}}\\right]=\\left[\\array{A-BK&BK\\\\0&A-LC}\\right]\\left[\\array{x\\\\e}\\right]$$\n", "\n", "Esta estrategia funciona si y solo si la matriz anterior genera un sistema asintóticamente estable. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# El principio de separación\n", "\n", "$$\\left[\\array{\\dot{x}\\\\\\dot{e}}\\right]=\\left[\\array{A-BK&BK\\\\0&A-LC}\\right]\\left[\\array{x\\\\e}\\right]=M\\left[\\array{x\\\\e}\\right]$$\n", "\n", "Para esta matriz triangular superior. Sus valores propios estan dados por los valores propios de los bloques diagonales. \n", "\n", "$$\\chi M(\\lambda) = \\chi A-BK (\\lambda) \\, \\chi A-LC (\\lambda)$$\n", "\n", "Si no nos equivocamos en el diseño, tendremos qué: \n", "\n", "$$\\text{Re}\\left(\\text{eig}(A-BK)\\right)<0$$\n", "$$\\text{Re}\\left(\\text{eig}(A-LC)\\right)<0$$\n", "\n", "Es decir que todo funciona." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# El principio de separación\n", "\n", "- Este impresionante hecho se conoce como el principio de separación. \n", "- Significa que podemos diseñar controladores si conocemos $x$.\n", "- Podemos diseñar observadores independientemente de las acciones del control.\n", "- El diseño de los observadores y controladores puede realizarse separadamente. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Consideraciones prácticas\n", "\n", "El principio de separación significa que podemos desacoplar el diseño del controlador del diseño del observador (en teoría).\n", "\n", "```\n", "“In theory, theory and practice are the\n", "same. In practice they are not.” -Yogi Berra\n", "```\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Selección de los polos / valores propios\n", "\n", "Típicamente el observador debe ser más rápido que el controlador, ya que el controlador no hará nada útil mientras que la estimación del estado no esté cerca del estado. \n", "\n", "**Nota** Grandes valores de los valores propios del observador generan grandes ganancias en el observador, lo que no es un problema ya que el observador es una construcción computacional. \n", "\n", "![](observador-controlador.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Seguimiento del objetivo " ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.8" } }, "nbformat": 4, "nbformat_minor": 2 }