diff --git a/examples/bdalg-matlab.py b/examples/bdalg-matlab.py index c3b11b109..8911d6579 100644 --- a/examples/bdalg-matlab.py +++ b/examples/bdalg-matlab.py @@ -10,8 +10,8 @@ sys1ss = ss(A1, B1, C1, 0) sys1tf = ss2tf(sys1ss) -sys2tf = tf([1, 0.5], [1, 5]); -sys2ss = tf2ss(sys2tf); +sys2tf = tf([1, 0.5], [1, 5]) +sys2ss = tf2ss(sys2tf) # Series composition -series1 = sys1ss + sys2ss; +series1 = sys1ss + sys2ss diff --git a/examples/bode-and-nyquist-plots.ipynb b/examples/bode-and-nyquist-plots.ipynb index 5a2e94ad0..8aa0df822 100644 --- a/examples/bode-and-nyquist-plots.ipynb +++ b/examples/bode-and-nyquist-plots.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -14,13 +14,13 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%matplotlib nbagg\n", "# only needed when developing python-control\n", - "%load_ext autoreload \n", + "%load_ext autoreload\n", "%autoreload 2" ] }, @@ -33,11 +33,14 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { + "text/latex": [ + "$$\\frac{1}{s + 1}$$" + ], "text/plain": [ "\n", " 1\n", @@ -50,6 +53,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{1}{0.1592 s + 1}$$" + ], "text/plain": [ "\n", " 1\n", @@ -62,6 +68,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{1}{0.02533 s^2 + 0.1592 s + 1}$$" + ], "text/plain": [ "\n", " 1\n", @@ -74,6 +83,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{s}{0.1592 s + 1}$$" + ], "text/plain": [ "\n", " s\n", @@ -86,6 +98,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{1}{1.021e-10 s^5 + 7.122e-08 s^4 + 4.519e-05 s^3 + 0.003067 s^2 + 0.1767 s + 1}$$" + ], "text/plain": [ "\n", " 1\n", @@ -131,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -151,11 +166,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { + "text/latex": [ + "$$\\frac{0.0004998 z + 0.0004998}{z - 0.999}\\quad dt = 0.001$$" + ], "text/plain": [ "\n", "0.0004998 z + 0.0004998\n", @@ -170,6 +188,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{0.003132 z + 0.003132}{z - 0.9937}\\quad dt = 0.001$$" + ], "text/plain": [ "\n", "0.003132 z + 0.003132\n", @@ -184,6 +205,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{6.264 z - 6.264}{z - 0.9937}\\quad dt = 0.001$$" + ], "text/plain": [ "\n", "6.264 z - 6.264\n", @@ -198,6 +222,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{9.839e-06 z^2 + 1.968e-05 z + 9.839e-06}{z^2 - 1.994 z + 0.9937}\\quad dt = 0.001$$" + ], "text/plain": [ "\n", "9.839e-06 z^2 + 1.968e-05 z + 9.839e-06\n", @@ -212,6 +239,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{2.091e-07 z^5 + 1.046e-06 z^4 + 2.091e-06 z^3 + 2.091e-06 z^2 + 1.046e-06 z + 2.091e-07}{z^5 - 4.205 z^4 + 7.155 z^3 - 6.212 z^2 + 2.78 z - 0.5182}\\quad dt = 0.001$$" + ], "text/plain": [ "\n", "2.091e-07 z^5 + 1.046e-06 z^4 + 2.091e-06 z^3 + 2.091e-06 z^2 + 1.046e-06 z + 2.091e-07\n", @@ -226,6 +256,9 @@ }, { "data": { + "text/latex": [ + "$$\\frac{2.731e-10 z^5 + 1.366e-09 z^4 + 2.731e-09 z^3 + 2.731e-09 z^2 + 1.366e-09 z + 2.731e-10}{z^5 - 4.815 z^4 + 9.286 z^3 - 8.968 z^2 + 4.337 z - 0.8405}\\quad dt = 0.00025$$" + ], "text/plain": [ "\n", "2.731e-10 z^5 + 1.366e-09 z^4 + 2.731e-09 z^3 + 2.731e-09 z^2 + 1.366e-09 z + 2.731e-10\n", @@ -270,7 +303,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -830,7 +863,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -1056,7 +1089,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -1080,7 +1113,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -1640,7 +1673,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -1866,7 +1899,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -1890,7 +1923,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -2450,7 +2483,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -2676,7 +2709,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -2700,7 +2733,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -3260,7 +3293,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -3486,7 +3519,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -3510,7 +3543,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -4070,7 +4103,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -4296,7 +4329,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -4321,7 +4354,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -4881,7 +4914,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -5107,7 +5140,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -5131,7 +5164,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -5691,7 +5724,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -5917,7 +5950,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -5943,7 +5976,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -6503,7 +6536,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -6729,7 +6762,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -6754,7 +6787,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -7314,7 +7347,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -7540,7 +7573,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -7564,7 +7597,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -8124,7 +8157,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -8350,7 +8383,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -8370,7 +8403,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -8930,7 +8963,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -9156,7 +9189,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -9181,7 +9214,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -9741,7 +9774,7 @@ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", "\n", @@ -9967,7 +10000,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -9992,9 +10025,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python (pctest)", "language": "python", - "name": "python3" + "name": "pctest" }, "language_info": { "codemirror_mode": { @@ -10006,7 +10039,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.9" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/examples/check-controllability-and-observability.py b/examples/check-controllability-and-observability.py index d20416f1f..399693781 100644 --- a/examples/check-controllability-and-observability.py +++ b/examples/check-controllability-and-observability.py @@ -6,25 +6,25 @@ from __future__ import print_function -from scipy import * # Load the scipy functions +import numpy as np # Load the scipy functions from control.matlab import * # Load the controls systems library # Parameters defining the system m = 250.0 # system mass -k = 40.0 # spring constant -b = 60.0 # damping constant +k = 40.0 # spring constant +b = 60.0 # damping constant # System matrices -A = matrix([[1, -1, 1.], - [1, -k / m, -b / m], - [1, 1, 1]]) +A = np.array([[1, -1, 1.], + [1, -k/m, -b/m], + [1, 1, 1]]) -B = matrix([[0], - [1 / m], - [1]]) +B = np.array([[0], + [1/m], + [1]]) -C = matrix([[1., 0, 1.]]) +C = np.array([[1., 0, 1.]]) sys = ss(A, B, C, 0) diff --git a/examples/genswitch.py b/examples/genswitch.py index 11f79a36c..e65e40110 100644 --- a/examples/genswitch.py +++ b/examples/genswitch.py @@ -8,75 +8,76 @@ import os import numpy as np -import matplotlib.pyplot as mpl +import matplotlib.pyplot as plt from scipy.integrate import odeint from control import phase_plot, box_grid # Simple model of a genetic switch -# + # This function implements the basic model of the genetic switch # Parameters taken from Gardner, Cantor and Collins, Nature, 2000 def genswitch(y, t, mu=4, n=2): - return (mu / (1 + y[1]**n) - y[0], mu / (1 + y[0]**n) - y[1]) + return mu/(1 + y[1]**n) - y[0], mu/(1 + y[0]**n) - y[1] # Run a simulation from an initial condition tim1 = np.linspace(0, 10, 100) sol1 = odeint(genswitch, [1, 5], tim1) -# Extract the equlibirum points -mu = 4; n = 2; # switch parameters -eqpt = np.empty(3); -eqpt[0] = sol1[0,-1] -eqpt[1] = sol1[1,-1] -eqpt[2] = 0; # fzero(@(x) mu/(1+x^2) - x, 2); +# Extract the equilibrium points +mu = 4; n = 2 # switch parameters +eqpt = np.empty(3) +eqpt[0] = sol1[0, -1] +eqpt[1] = sol1[1, -1] +eqpt[2] = 0 # fzero(@(x) mu/(1+x^2) - x, 2) # Run another simulation showing switching behavior -tim2 = np.linspace(11, 25, 100); -sol2 = odeint(genswitch, sol1[-1,:] + [2, -2], tim2) +tim2 = np.linspace(11, 25, 100) +sol2 = odeint(genswitch, sol1[-1, :] + [2, -2], tim2) # First plot out the curves that define the equilibria u = np.linspace(0, 4.5, 46) -f = np.divide(mu, (1 + u**n)) # mu / (1 + u^n), elementwise +f = np.divide(mu, (1 + u**n)) # mu/(1 + u^n), element-wise -mpl.figure(1); mpl.clf(); -mpl.axis([0, 5, 0, 5]); # box on; -mpl.plot(u, f, '-', f, u, '--') # 'LineWidth', AM_data_linewidth); -mpl.legend(('z1, f(z1)', 'z2, f(z2)')) # legend(lgh, 'boxoff'); -mpl.plot([0, 3], [0, 3], 'k-') # 'LineWidth', AM_ref_linewidth); -mpl.plot(eqpt[0], eqpt[1], 'k.', eqpt[1], eqpt[0], 'k.', - eqpt[2], eqpt[2], 'k.') # 'MarkerSize', AM_data_markersize*3); -mpl.xlabel('z1, f(z2)'); -mpl.ylabel('z2, f(z1)'); +plt.figure(1); plt.clf() +plt.axis([0, 5, 0, 5]) # box on; +plt.plot(u, f, '-', f, u, '--') # 'LineWidth', AM_data_linewidth) +plt.legend(('z1, f(z1)', 'z2, f(z2)')) # legend(lgh, 'boxoff') +plt.plot([0, 3], [0, 3], 'k-') # 'LineWidth', AM_ref_linewidth) +plt.plot(eqpt[0], eqpt[1], 'k.', eqpt[1], eqpt[0], 'k.', + eqpt[2], eqpt[2], 'k.') # 'MarkerSize', AM_data_markersize*3) +plt.xlabel('z1, f(z2)') +plt.ylabel('z2, f(z1)') # Time traces -mpl.figure(3); mpl.clf(); # subplot(221); -mpl.plot(tim1, sol1[:,0], 'b-', tim1, sol1[:,1], 'g--'); -# set(pl, 'LineWidth', AM_data_linewidth); -mpl.plot([tim1[-1], tim1[-1]+1], - [sol1[-1,0], sol2[0,1]], 'ko:', - [tim1[-1], tim1[-1]+1], [sol1[-1,1], sol2[0,0]], 'ko:'); -# set(pl, 'LineWidth', AM_data_linewidth, 'MarkerSize', AM_data_markersize); -mpl.plot(tim2, sol2[:,0], 'b-', tim2, sol2[:,1], 'g--'); -# set(pl, 'LineWidth', AM_data_linewidth); -mpl.axis([0, 25, 0, 5]); +plt.figure(3); plt.clf() # subplot(221) +plt.plot(tim1, sol1[:, 0], 'b-', tim1, sol1[:, 1], 'g--') +# set(pl, 'LineWidth', AM_data_linewidth) +plt.plot([tim1[-1], tim1[-1] + 1], + [sol1[-1, 0], sol2[0, 1]], 'ko:', + [tim1[-1], tim1[-1] + 1], [sol1[-1, 1], sol2[0, 0]], 'ko:') +# set(pl, 'LineWidth', AM_data_linewidth, 'MarkerSize', AM_data_markersize) +plt.plot(tim2, sol2[:, 0], 'b-', tim2, sol2[:, 1], 'g--') +# set(pl, 'LineWidth', AM_data_linewidth) +plt.axis([0, 25, 0, 5]) -mpl.xlabel('Time {\itt} [scaled]'); -mpl.ylabel('Protein concentrations [scaled]'); -mpl.legend(('z1 (A)', 'z2 (B)')) # 'Orientation', 'horizontal'); -# legend(legh, 'boxoff'); +plt.xlabel('Time {\itt} [scaled]') +plt.ylabel('Protein concentrations [scaled]') +plt.legend(('z1 (A)', 'z2 (B)')) # 'Orientation', 'horizontal') +# legend(legh, 'boxoff') # Phase portrait -mpl.figure(2); mpl.clf(); # subplot(221); -mpl.axis([0, 5, 0, 5]); # set(gca, 'DataAspectRatio', [1, 1, 1]); -phase_plot(genswitch, X0 = box_grid([0, 5, 6], [0, 5, 6]), T = 10, - timepts = [0.2, 0.6, 1.2]) +plt.figure(2) +plt.clf() # subplot(221) +plt.axis([0, 5, 0, 5]) # set(gca, 'DataAspectRatio', [1, 1, 1]) +phase_plot(genswitch, X0=box_grid([0, 5, 6], [0, 5, 6]), T=10, + timepts=[0.2, 0.6, 1.2]) # Add the stable equilibrium points -mpl.plot(eqpt[0], eqpt[1], 'k.', eqpt[1], eqpt[0], 'k.', - eqpt[2], eqpt[2], 'k.') # 'MarkerSize', AM_data_markersize*3); +plt.plot(eqpt[0], eqpt[1], 'k.', eqpt[1], eqpt[0], 'k.', + eqpt[2], eqpt[2], 'k.') # 'MarkerSize', AM_data_markersize*3) -mpl.xlabel('Protein A [scaled]'); -mpl.ylabel('Protein B [scaled]'); # 'Rotation', 90); +plt.xlabel('Protein A [scaled]') +plt.ylabel('Protein B [scaled]') # 'Rotation', 90) if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: - mpl.show() + plt.show() diff --git a/examples/phaseplots.py b/examples/phaseplots.py index 0c86522de..cf05c384a 100644 --- a/examples/phaseplots.py +++ b/examples/phaseplots.py @@ -7,12 +7,12 @@ import os import numpy as np -import matplotlib.pyplot as mpl +import matplotlib.pyplot as plt from control.phaseplot import phase_plot -from numpy import pi +from numpy import pi # Clear out any figures that are present -mpl.close('all') +plt.close('all') # # Inverted pendulum @@ -20,52 +20,65 @@ # Define the ODEs for a damped (inverted) pendulum def invpend_ode(x, t, m=1., l=1., b=0.2, g=1): - return (x[1], -b/m*x[1] + (g*l/m) * np.sin(x[0])) + return x[1], -b/m*x[1] + (g*l/m)*np.sin(x[0]) + # Set up the figure the way we want it to look -mpl.figure(); mpl.clf(); -mpl.axis([-2*pi, 2*pi, -2.1, 2.1]); -mpl.title('Inverted pendulum') +plt.figure() +plt.clf() +plt.axis([-2*pi, 2*pi, -2.1, 2.1]) +plt.title('Inverted pendulum') # Outer trajectories -phase_plot(invpend_ode, - X0 = [ [-2*pi, 1.6], [-2*pi, 0.5], [-1.8, 2.1], - [-1, 2.1], [4.2, 2.1], [5, 2.1], - [2*pi, -1.6], [2*pi, -0.5], [1.8, -2.1], - [1, -2.1], [-4.2, -2.1], [-5, -2.1] ], - T = np.linspace(0, 40, 200), - logtime = (3, 0.7) ) +phase_plot( + invpend_ode, + X0=[[-2*pi, 1.6], [-2*pi, 0.5], [-1.8, 2.1], + [-1, 2.1], [4.2, 2.1], [5, 2.1], + [2*pi, -1.6], [2*pi, -0.5], [1.8, -2.1], + [1, -2.1], [-4.2, -2.1], [-5, -2.1]], + T=np.linspace(0, 40, 200), + logtime=(3, 0.7) +) # Separatrices -phase_plot(invpend_ode, X0 = [[-2.3056, 2.1], [2.3056, -2.1]], T=6, lingrid=0) +phase_plot(invpend_ode, X0=[[-2.3056, 2.1], [2.3056, -2.1]], T=6, lingrid=0) # # Systems of ODEs: damped oscillator example (simulation + phase portrait) # def oscillator_ode(x, t, m=1., b=1, k=1): - return (x[1], -k/m*x[0] - b/m*x[1]) + return x[1], -k/m*x[0] - b/m*x[1] + # Generate a vector plot for the damped oscillator -mpl.figure(); mpl.clf(); -phase_plot(oscillator_ode, [-1, 1, 10], [-1, 1, 10], 0.15); -#mpl.plot([0], [0], '.'); -# a=gca; set(a,'FontSize',20); set(a,'DataAspectRatio',[1,1,1]); -mpl.xlabel('$x_1$'); mpl.ylabel('$x_2$'); -mpl.title('Damped oscillator, vector field') +plt.figure() +plt.clf() +phase_plot(oscillator_ode, [-1, 1, 10], [-1, 1, 10], 0.15) +#plt.plot([0], [0], '.') +# a=gca; set(a,'FontSize',20); set(a,'DataAspectRatio',[1,1,1]) +plt.xlabel('$x_1$') +plt.ylabel('$x_2$') +plt.title('Damped oscillator, vector field') # Generate a phase plot for the damped oscillator -mpl.figure(); mpl.clf(); -mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1, 1, 1]); -phase_plot(oscillator_ode, - X0 = [ - [-1, 1], [-0.3, 1], [0, 1], [0.25, 1], [0.5, 1], [0.75, 1], [1, 1], - [1, -1], [0.3, -1], [0, -1], [-0.25, -1], [-0.5, -1], [-0.75, -1], [-1, -1] - ], T = np.linspace(0, 8, 80), timepts = [0.25, 0.8, 2, 3]) -mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); -# set(gca,'DataAspectRatio',[1,1,1]); -mpl.xlabel('$x_1$'); mpl.ylabel('$x_2$'); -mpl.title('Damped oscillator, vector field and stream lines') +plt.figure() +plt.clf() +plt.axis([-1, 1, -1, 1]) # set(gca, 'DataAspectRatio', [1, 1, 1]); +phase_plot( + oscillator_ode, + X0=[ + [-1, 1], [-0.3, 1], [0, 1], [0.25, 1], [0.5, 1], [0.75, 1], [1, 1], + [1, -1], [0.3, -1], [0, -1], [-0.25, -1], [-0.5, -1], [-0.75, -1], [-1, -1] + ], + T=np.linspace(0, 8, 80), + timepts=[0.25, 0.8, 2, 3] +) +plt.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3) +# set(gca, 'DataAspectRatio', [1,1,1]) +plt.xlabel('$x_1$') +plt.ylabel('$x_2$') +plt.title('Damped oscillator, vector field and stream lines') # # Stability definitions @@ -73,54 +86,81 @@ def oscillator_ode(x, t, m=1., b=1, k=1): # This set of plots illustrates the various types of equilibrium points. # -# Saddle point vector field + def saddle_ode(x, t): - return (x[0] - 3*x[1], -3*x[0] + x[1]); + """Saddle point vector field""" + return x[0] - 3*x[1], -3*x[0] + x[1] + # Asy stable -m = 1; b = 1; k = 1; # default values -mpl.figure(); mpl.clf(); -mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); -phase_plot(oscillator_ode, - X0 = [ - [-1,1], [-0.3,1], [0,1], [0.25,1], [0.5,1], [0.7,1], [1,1], [1.3,1], - [1,-1], [0.3,-1], [0,-1], [-0.25,-1], [-0.5,-1], [-0.7,-1], [-1,-1], - [-1.3,-1] - ], T = np.linspace(0, 10, 100), - timepts = [0.3, 1, 2, 3], parms = (m, b, k)); -mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); -# set(gca,'FontSize', 16); -mpl.xlabel('$x_1$'); mpl.ylabel('$x_2$'); -mpl.title('Asymptotically stable point') +m = 1 +b = 1 +k = 1 # default values +plt.figure() +plt.clf() +plt.axis([-1, 1, -1, 1]) # set(gca, 'DataAspectRatio', [1 1 1]); +phase_plot( + oscillator_ode, + X0=[ + [-1, 1], [-0.3, 1], [0, 1], [0.25, 1], [0.5, 1], [0.7, 1], [1, 1], [1.3, 1], + [1, -1], [0.3, -1], [0, -1], [-0.25, -1], [-0.5, -1], [-0.7, -1], [-1, -1], + [-1.3, -1] + ], + T=np.linspace(0, 10, 100), + timepts=[0.3, 1, 2, 3], + parms=(m, b, k) +) +plt.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3) +# plt.set(gca,'FontSize', 16) +plt.xlabel('$x_1$') +plt.ylabel('$x_2$') +plt.title('Asymptotically stable point') # Saddle -mpl.figure(); mpl.clf(); -mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); -phase_plot(saddle_ode, scale = 2, timepts = [0.2, 0.5, 0.8], X0 = - [ [-1, -1], [1, 1], - [-1, -0.95], [-1, -0.9], [-1, -0.8], [-1, -0.6], [-1, -0.4], [-1, -0.2], - [-0.95, -1], [-0.9, -1], [-0.8, -1], [-0.6, -1], [-0.4, -1], [-0.2, -1], - [1, 0.95], [1, 0.9], [1, 0.8], [1, 0.6], [1, 0.4], [1, 0.2], - [0.95, 1], [0.9, 1], [0.8, 1], [0.6, 1], [0.4, 1], [0.2, 1], - [-0.5, -0.45], [-0.45, -0.5], [0.5, 0.45], [0.45, 0.5], - [-0.04, 0.04], [0.04, -0.04] ], T = np.linspace(0, 2, 20)); -mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); -# set(gca,'FontSize', 16); -mpl.xlabel('$x_1$'); mpl.ylabel('$x_2$'); -mpl.title('Saddle point') +plt.figure() +plt.clf() +plt.axis([-1, 1, -1, 1]) # set(gca, 'DataAspectRatio', [1 1 1]) +phase_plot( + saddle_ode, + scale=2, + timepts=[0.2, 0.5, 0.8], + X0=[ + [-1, -1], [1, 1], + [-1, -0.95], [-1, -0.9], [-1, -0.8], [-1, -0.6], [-1, -0.4], [-1, -0.2], + [-0.95, -1], [-0.9, -1], [-0.8, -1], [-0.6, -1], [-0.4, -1], [-0.2, -1], + [1, 0.95], [1, 0.9], [1, 0.8], [1, 0.6], [1, 0.4], [1, 0.2], + [0.95, 1], [0.9, 1], [0.8, 1], [0.6, 1], [0.4, 1], [0.2, 1], + [-0.5, -0.45], [-0.45, -0.5], [0.5, 0.45], [0.45, 0.5], + [-0.04, 0.04], [0.04, -0.04] + ], + T=np.linspace(0, 2, 20) +) +plt.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3) +# set(gca,'FontSize', 16) +plt.xlabel('$x_1$') +plt.ylabel('$x_2$') +plt.title('Saddle point') # Stable isL -m = 1; b = 0; k = 1; # zero damping -mpl.figure(); mpl.clf(); -mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); -phase_plot(oscillator_ode, timepts = - [pi/6, pi/3, pi/2, 2*pi/3, 5*pi/6, pi, 7*pi/6, 4*pi/3, 9*pi/6, 5*pi/3, 11*pi/6, 2*pi], - X0 = [ [0.2,0], [0.4,0], [0.6,0], [0.8,0], [1,0], [1.2,0], [1.4,0] ], - T = np.linspace(0, 20, 200), parms = (m, b, k)); -mpl.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3); -# set(gca,'FontSize', 16); -mpl.xlabel('$x_1$'); mpl.ylabel('$x_2$'); -mpl.title('Undamped system\nLyapunov stable, not asympt. stable') +m = 1 +b = 0 +k = 1 # zero damping +plt.figure() +plt.clf() +plt.axis([-1, 1, -1, 1]) # set(gca, 'DataAspectRatio', [1 1 1]); +phase_plot( + oscillator_ode, + timepts=[pi/6, pi/3, pi/2, 2*pi/3, 5*pi/6, pi, 7*pi/6, + 4*pi/3, 9*pi/6, 5*pi/3, 11*pi/6, 2*pi], + X0=[[0.2, 0], [0.4, 0], [0.6, 0], [0.8, 0], [1, 0], [1.2, 0], [1.4, 0]], + T=np.linspace(0, 20, 200), + parms=(m, b, k) +) +plt.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3) +# plt.set(gca,'FontSize', 16) +plt.xlabel('$x_1$') +plt.ylabel('$x_2$') +plt.title('Undamped system\nLyapunov stable, not asympt. stable') if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: - mpl.show() + plt.show() diff --git a/examples/pvtol-lqr-nested.ipynb b/examples/pvtol-lqr-nested.ipynb index bb9a51b07..8b0f01676 100644 --- a/examples/pvtol-lqr-nested.ipynb +++ b/examples/pvtol-lqr-nested.ipynb @@ -1 +1,587 @@ -{"nbformat_minor": 0, "cells": [{"source": "#`python-control` Example: Vertical takeoff and landing aircraft\n\nhttp://www.cds.caltech.edu/~murray/wiki/index.php/Python-control/Example:_Vertical_takeoff_and_landing_aircraft\n\nThis page demonstrates the use of the python-control package for analysis and design of a controller for a vectored thrust aircraft model that is used as a running example through the text *Feedback Systems* by Astrom and Murray. This example makes use of MATLAB compatible commands. ", "cell_type": "markdown", "metadata": {}}, {"source": "##System Description\nThis example uses a simplified model for a (planar) vertical takeoff and landing aircraft (PVTOL), as shown below:\n \n\nThe position and orientation of the center of mass of the aircraft is denoted by $(x,y,\\theta)$, $m$ is the mass of the vehicle, $J$ the moment of inertia, $g$ the gravitational constant and $c$ the damping coefficient. The forces generated by the main downward thruster and the maneuvering thrusters are modeled as a pair of forces $F_1$ and $F_2$ acting at a distance $r$ below the aircraft (determined by the geometry of the thrusters).\n\nIt is convenient to redefine the inputs so that the origin is an equilibrium point of the system with zero input. Letting $u_1 =\nF_1$ and $u_2 = F_2 - mg$, the equations can be written in state space form as:\n\n\n##LQR state feedback controller\nThis section demonstrates the design of an LQR state feedback controller for the vectored thrust aircraft example. This example is pulled from Chapter 6 (State Feedback) of [http:www.cds.caltech.edu/~murray/amwiki Astrom and Murray]. The python code listed here are contained the the file pvtol-lqr.py.\n\nTo execute this example, we first import the libraries for SciPy, MATLAB plotting and the python-control package:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 1, "cell_type": "code", "source": "from numpy import * # Grab all of the NumPy functions\nfrom matplotlib.pyplot import * # Grab MATLAB plotting functions\nfrom control.matlab import * # MATLAB-like functions\n%matplotlib inline", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "The parameters for the system are given by", "cell_type": "markdown", "metadata": {}}, {"execution_count": 2, "cell_type": "code", "source": "m = 4; # mass of aircraft\nJ = 0.0475; # inertia around pitch axis\nr = 0.25; # distance to center of force\ng = 9.8; # gravitational constant\nc = 0.05; # damping factor (estimated)\nprint \"m = %f\" % m\nprint \"J = %f\" % J\nprint \"r = %f\" % r\nprint \"g = %f\" % g\nprint \"c = %f\" % c", "outputs": [{"output_type": "stream", "name": "stdout", "text": "m = 4.000000\nJ = 0.047500\nr = 0.250000\ng = 9.800000\nc = 0.050000\n"}], "metadata": {"collapsed": false, "trusted": true}}, {"source": "The linearization of the dynamics near the equilibrium point $x_e = (0, 0, 0, 0, 0, 0)$, $u_e = (0, mg)$ are given by", "cell_type": "markdown", "metadata": {}}, {"execution_count": 3, "cell_type": "code", "source": "# State space dynamics\nxe = [0, 0, 0, 0, 0, 0]; # equilibrium point of interest\nue = [0, m*g]; # (note these are lists, not matrices)", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 4, "cell_type": "code", "source": "# Dynamics matrix (use matrix type so that * works for multiplication)\nA = matrix(\n [[ 0, 0, 0, 1, 0, 0],\n [ 0, 0, 0, 0, 1, 0],\n [ 0, 0, 0, 0, 0, 1],\n [ 0, 0, (-ue[0]*sin(xe[2]) - ue[1]*cos(xe[2]))/m, -c/m, 0, 0],\n [ 0, 0, (ue[0]*cos(xe[2]) - ue[1]*sin(xe[2]))/m, 0, -c/m, 0],\n [ 0, 0, 0, 0, 0, 0 ]])\n\n# Input matrix\nB = matrix(\n [[0, 0], [0, 0], [0, 0],\n [cos(xe[2])/m, -sin(xe[2])/m],\n [sin(xe[2])/m, cos(xe[2])/m],\n [r/J, 0]])\n\n# Output matrix \nC = matrix([[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0]])\nD = matrix([[0, 0], [0, 0]])", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "To compute a linear quadratic regulator for the system, we write the cost function as\n\n\nwhere $z = z - z_e$ and $v = u - u_e$ represent the local coordinates around the desired equilibrium point $(z_e, u_e)$. We begin with diagonal matrices for the state and input costs:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 5, "cell_type": "code", "source": "Qx1 = diag([1, 1, 1, 1, 1, 1]);\nQu1a = diag([1, 1]);\n(K, X, E) = lqr(A, B, Qx1, Qu1a); K1a = matrix(K);", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "This gives a control law of the form $v = -K z$, which can then be used to derive the control law in terms of the original variables:\n\n\n $$u = v + u_d = - K(z - z_d) + u_d.$$\nwhere $u_d = (0, mg)$ and $z_d = (x_d, y_d, 0, 0, 0, 0)$\n\nSince the `python-control` package only supports SISO systems, in order to compute the closed loop dynamics, we must extract the dynamics for the lateral and altitude dynamics as individual systems. In addition, we simulate the closed loop dynamics using the step command with $K x_d$ as the input vector (assumes that the \"input\" is unit size, with $xd$ corresponding to the desired steady state. The following code performs these operations:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 6, "cell_type": "code", "source": "xd = matrix([[1], [0], [0], [0], [0], [0]]); \nyd = matrix([[0], [1], [0], [0], [0], [0]]); ", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 7, "cell_type": "code", "source": "# Indices for the parts of the state that we want\nlat = (0,2,3,5);\nalt = (1,4);\n\n# Decoupled dynamics\nAx = (A[lat, :])[:, lat]; #! not sure why I have to do it this way\nBx = B[lat, 0]; Cx = C[0, lat]; Dx = D[0, 0];\n \nAy = (A[alt, :])[:, alt]; #! not sure why I have to do it this way\nBy = B[alt, 1]; Cy = C[1, alt]; Dy = D[1, 1];\n\n# Step response for the first input\nH1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx);\n(Tx, Yx) = step(H1ax, T=linspace(0,10,100));\n\n# Step response for the second input\nH1ay = ss(Ay - By*K1a[1,alt], By*K1a[1,alt]*yd[alt,:], Cy, Dy);\n(Ty, Yy) = step(H1ay, T=linspace(0,10,100));", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 8, "cell_type": "code", "source": "plot(Yx.T, Tx, '-', Yy.T, Ty, '--'); hold(True);\nplot([0, 10], [1, 1], 'k-'); hold(True);\nylabel('Position');\nxlabel('Time (s)');\ntitle('Step Response for Inputs');\nlegend(('Yx', 'Yy'), loc='lower right');", "outputs": [{"output_type": "display_data", "data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAEZCAYAAABmTgnDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XmcW2XZ//HPl7IvpYUCSimLCgpIkb0KQlHEAgqCIqus\nIgIFXFBExTQ+Px7BHUTZHuChIpuKiMgiIH0ABRTZoVUQCrSVfWnZC71+f9xnaDqdmWRmktzJ5Pt+\nvc5rJjkn51zJtOfKvSsiMDMz68siuQMwM7PW52RhZmZVOVmYmVlVThZmZlaVk4WZmVXlZGFmZlU5\nWZi1CUm7Snpc0hxJG+aOxzqLk4UNiKStJP1V0guSnpV0s6RNi30HSLqpgdeeIunV4qb5jKTfS1qt\nUddrIT8EDo+I5SLi7sGerPgcD65DXNWu09B/D9YcThbWb5KGA1cAJwMjgdFAGXi9SSEEcERELAe8\nG1gS+HGTrp2FJAGrAw8M8PU9/V+PYjOrysnCBmIdICLi4khei4hrI+JeSesCpwEfLL75PwcgaQlJ\nP5T0qKQnJJ0macli33hJMyQdJ+lpSY9I2ruWQCLiReD3wPpdz0l6n6RrixLPNEm7V+zbUdL9kmYX\n1/xqLTFIWl7SZElPSZou6VvFDbzrm/PNkn4g6TlJD0uaUPHaAyT9u7jmw93Oe5CkB4rXXS1p9e7v\nUdISwBxgGHC3pAeL59ctSgfPS7pP0icrXvO/xWd8paSXgPF9fY4V7/8rkp6UNEvSAd3Od7qkPxXv\nY0pXrJLWlDSvMiF1lVokvQ84nYX/PfT4d7DW5WRhA/FP4K3iBjJB0siuHRExFfgicEtRXbJCsetE\n4D3AhsXP0cB3Ks65CrAisCqwP3CmpHX6iKHrRr0isBtwW/F4GeBa4HxgJWBP4BfFTQvgbOALETGc\nlGD+XGMMPwOWA9YCtgH2Aw6seO3mwLTi9d8vrtMVz8nAhOKaHwTuKvbtAhwH7AqMAm4CLuz+RiPi\n9YhYtng4NiLWlrQY8Afg6uJ9Hgn8qttnthfwX8Vr/9LHZ1n5/ocX7/9g4OeSlq/Yvzfw3SLWu4Bf\n9XGuSKHHNOBQFv730NffwVqQk4X1W0TMAbYi3RDOAp4q2g1WLg5R5fHFN/BDgK9ExAsR8RLwPdKN\nvNLxETE3Im4E/gh8tpcQBJwi6QXgaWBZ4Ihi3yeARyLivIiYFxF3AZdWnOsNYH1JwyPixYi4s1oM\nkoYBewDHRcTLEfEo8CPgcxWvezQizo402dpk4J0Vn8c8YANJS0XEkxHRVZX0ReB7EfHPiJhXfCYf\nkDSml/ddaRywTEScGBFvRsQNpKrBvSqOuSwiboGUcGo451zguxHxVkRcBbwEvLdi/xURcXNEvAF8\ni1RaGF3DedXDc9X+DtZinCxsQCJiWkQcGBFjgPeTvo3+tJfDVwKWBv5RVJk8D1xF+oba5fmIeLXi\n8aPFOXu8PHBkRIwAxgJrADsW+9YAtui6TnGtvUnfmgE+XRw7vagqGVclhneSSguLFY+7PEYqHXV5\n4u3gIl4pfl02Il4mJZovArMkXSGp6wa8BnByRZzPFs/XcgNeFXi823OVn1n0sL+aZ4uk1eUVUiLu\nOt+Mrh3F+3qO3v9G1fT1d7AW5GRhgxYR/wTOIyUNWLjR9BngVWC9iBhZbCOKKoguIyUtXfF4DWBm\nH5dVce37gOOBE4s688eA/6u4zsii+uOI4vjbI+JTpAR2GXBJlRhmFfHPBdas2Lc6FTfPvkTEnyJi\ne+AdpKqqs4pdj5GqYipjXSYibq3htLOAMV3tJhXx9vWZDYaAt0s8kpYFVijieLl4uvKze0fF7ws1\nolf5O1gLcrKwfpP03qIhdHTxeAyp+uOW4pAngdWKenWKb6tnAT+VtFLxmtGStu926rKkxSR9GNgJ\n+HWNIZ1HulHtTqqKWUfSvsW5FpO0mVKj92KS9pG0fES8RWo0fqtaDEX8lwAnSFpW0hrAl0ntItU+\nq5Ul7VK0Xcwl3Vi7rnk68E1J6xXHLq+KxvgqbiV98/96Ee94UhXcRV2XrvE8/bGjpC0lLQ78F6kd\nYmZEPE1KUp+TNEzSQaReal0W+PdQ49/BWoyThQ3EHGAL4Laip80twD1AV4+W64H7gSckPVU8dyzw\nEHCrpBdJjdCVjbFPAM+Tvqn+Ejg0Iv7VRwxvf1uNiLmkRuSvF+0h25PaQ2YC/yG1BSxeHL4v8EgR\nwxeAfWqM4UjSjf5hUkP0r4BzK2Lp/u256/EipMQyk1TN9GHgsCLuy4CTgIuKeO4FPt6P9/xJYAdS\nu82pwOcq4h1It9i+jg/gAqBUvI+NSJ9ll0OAr5FKYeuxYIN6T/8e+vo7WAtSzsWPJJ1D+vb2VERs\n0MP+fYCvk74lzQEOi4h7mhulNVrxrfiXRftHx8bQyiSdC8yIiONzx2J55C5ZnAtM6GP/w8DWETGW\nVOw9sylRmVl3jajWsjaSNVlExE2kYn9v+28pBl1B6kffCVM6dKpWGEncCjG0Ko/27nBZq6Egjf4E\n/tBTNVS3444B1omILzQjLjMzm2/R3AHUQtK2wEHAlrljMTPrRC2fLCSNJXW7nBARC1VZSXLR2Mxs\nACKi5raolk4WxURllwL7RsRDvR3Xnzc8lEmaFBGTcsfRCvxZzOfPYj5/FvP194t21mQh6ULSpGyj\nJD1O6sPdNZDrDNJEcyOB04qBqnMjYvNM4ZqZdaysySIi9qqy//PA55sUjpmZ9SL3OAurrym5A2gh\nU3IH0EKm5A6ghUzJHUC7yt51drAkhdsszMz6p7/3TpcszMysKicLMzOrysnCzMyqcrIwM7OqnCzM\nzKwqJwszM6vKycLMzKpysjAzs6qcLMzMrConCzMzq8rJwszMqnKyMDOzqpwszMysKicLMzOrysnC\nzMyqcrIwM7OqnCzMzKwqJwszM6vKycLMzKpysjAzs6oWzR2AmdlQo7LWA4YDSxTb4sXPa6IUL/Vw\n/OeBUcCwYluk2E6OUjzbw/FfA1aseCqK7Ue9HH8osDzwVrG92d/3lC1ZSDoH2Al4KiI26OWYU4Ad\ngFeAAyLiziaGaGZDmMoSsAzpprsCMBK4LUrxcg/H/gJYB1gOWLZi2yJK8VAPpz8RWAV4vdjeKH7e\nAiyULEiJYgQwj/k39LdICaAns0lJBUAVW2/HjwBWIiWgroTUL4ro7dyNJenDpA9tck/JQtKOwMSI\n2FHSFsDJETGuh+MiItT4iM2s1RUJYCTwTmBV4G9Rihd7OO56YEvSzflZ4LliOyhK8UgPx3+UdKOd\nU2wvAS8Dz0cp3mrMu2ms/t47s5UsIuImSWv2ccjOwHnFsbdJGiFplYh4shnxmVn7UFmnAx8FViN9\ng59VbEcACyULYE/g5SjFK7WcP0pxfZ1CbVut3GYxGni84vEM0j8EJwuzIU5lvRf4APCeiu1dpG/+\n1/Twkl8APwFm9tQm0F2U4uk6htsRWjlZQKqDq9RjnZmkPHVpZtZsV2tS3zUn1fbbwLRyspgJjKl4\nvFrx3ELcZmGtRmIRUgPo8qReMcNJjaPDi+crG0qXqdiWLralKn4uBSxZbEuRetV0NZi+xoKNqG9U\n/D63h5/dtzcrtq7Hb1U891YPP7u27o2x8yp+Vv4erHvpSDa4YD1W/Ne7WebJtVnyxXexyNzleGTb\nk/jldX9kfm+eeW+/Zv7jnn7va+s6jm7Pd39c+Vz3n73t6+247vu6/97Xvv6co7fjFtwRfb4O6P+X\n7FZOFpcDE4GLJI0DXnB7heUgsSSwcrGtVGyjiq2rJ01Xb5oRxTacdCN/sdhmF1tlA2nX9gypsfSV\nip+vAK/2sL0GvBHBvMa+6/pS+dOHABsBdwG/A+4Bpsfk6+YxOWtoVqOcvaEuBLYh/Yd7EigBiwFE\nxBnFMacCE0j/gQ6MiDt6OI97Q9mAFN/+VwFWJ5ViR5NKsKsW2zuBd5C+4T9F+nf6dLE9Q+pFU9mT\n5jngBeB5YHZE//uytxuVtTSwGaln0QeBf0Upvpo3KqtFf++d2ZJFvThZWF8kliY1jq4NvJvUSNq1\nrUb61v8YqTPFDFJV50zgP8X2BPB8LcX6TqKy1gfOBjYA7gP+AvwVuCVK0WN1sbWWtuk6a1ZPEssD\n7yfdvNat2EYBDwMPAg+Rqj8uAx4BHovg1SwBtwmVtViUYm4Pu2YA3yCNY6ip+6m1N5csrO1IjAY2\nIdWBb0zqYrki8ADpW+4DxTaVlBDactBUDsWgtvWBjxfbRsDoKMUbWQOzunM1lA0pReNyV534FsDm\npHl2bgfuKLa7gYfbrdG31aisE4G9Sb2YrgauAf4cpZidNTBrCFdDWVsr2hi2BD4CbE0qNdxPqg+/\nGPgKMN1tCA1xCzAZmBqlNv8WaXXnkoVlJSFSQtiBVO2xCXAncAMwBbgtgoUmdrP+U1mrALsC/45S\nXJs7HsvLJQtreRJLkebx+RRp5uE5wFWkmTpviuhxVk4bAJW1ArAbsBcpEV8J3Js1KGtLLllYUxTV\nSzsBewAfI5UeLgP+EMG/c8Y2VKmszYFrgT8BFwJXRSnc+8sAlyyshUgMIyWGz5ESxd9I7Q5fjOCZ\nnLF1iDuA1aIUc3IHYu3PJQurO4m1gYOA/UgD3CYDl0TwVNbAhiCVtTLpcz63pxXSzHrjkoVlUZQi\ndiKtH7ARKUF8PIL7sgY2BKmsRYBtgUOB7UlzLS2VNSgb8pwsbFAklgE+D3yZNDXGz4FdIngta2BD\nlMraHvgZaRbZM4AvRCleyBuVdQInCxsQiVHAUcBhpC6un43gb1mD6gyPAwcDf/FYCGsmt1lYv0iM\nAL4KHA78FvhBBA/mjcrM+sttFtYQxdiILxfb5cAmEUzPGtQQpLIWBXYnJeTPRCmm543ILHGysD4V\nI6x3B75Pmo/pQy5J1J/KWorUg+wY0pTpJeDRrEGZVXCysF5JrA+cRloCdP8I/i9zSEOSytoO+CVp\nHMpeUYpbM4dkthAnC1uIxBLAN0ntEscDZ3ma74aaCkyIUtydOxCz3riB2xYgsQVwLvAv4IgIvOqZ\n2RDkBm4bkGJQ3bHA0cCRwK89DXj9qKzFgS+Qlh39R+54zPrLycK6Vp77JTAM2DSCxzOHNGSorGGk\nBYW+S6puuj5vRGYD42TR4SS2AS4ijbz+ntsm6kdlfQz4AfAKsF+U4qbMIZkNmNssOpjEoaRvvPtE\ncF3ueIYSlTUcuA44CbjUo62t1XgNbqtKYjHgp6SlS3f2uAmzztPfe+cijQymGkkTJE2T9KCkY3vY\nP0rS1ZLuknSfpAMyhDmkFCOxfwe8CxjnRGFmtchWspA0DPgnsB1pzYO/A3tFxNSKYyYBS0TEcZJG\nFcevEhFvVhzjkkWNJJYnTdUxAzgggrmZQ2p7Kmtb0sjr/aMU83LHY1arduo6uznwUESa+0bSRcAu\npB4jXf4DjC1+Hw48W5korHYSKwFXA7cCR0bgG9sgqKzRwI+AcaT5stq7PtesipzJYjQs0EVzBrBF\nt2POAv4saRZpyonPNim2IaWYTvwG0prXx3v8xMAVXWGPAL4DnA4cFKV4JW9UZo2XM1nUcsP6JnBX\nRIyX9G7gWkkbRiy4pnBRXdVlSkRMqV+Y7U1iOKlEcQVOFPWwO7Ab8OEoxdRqB5u1CknjgfEDfX3O\nZDETGFPxeAypdFHpQ8AJABHxb0mPAO8lzX76toiY1Lgw25fE0sAfSBPUHedEUReXABe7K6y1m+JL\n9JSux5JK/Xl9zgbuRUkN1h8FZtE14+aCDdw/Bl6MiLKkVYB/AGMj4rmKY9zA3YOie+zvgWdJM8a6\njcLM3tY2XWeLhuqJwDXAA8DFETFV0qGSDi0O+29gU0l3kwY4fb0yUVjPijUoTikeHuhE0X8qa7jK\n2ip3HGatwoPyhiCJI0jTi38wgtm542k3Kmt7UueKX0cpjskdj1kjtFPXWWsAiY+R1qD4kBNF/6is\nZYEfAjsAh0Qp/pQ5JLOWkXUEt9WXxDrA+cAeETycO552orI2A+4ClgDGOlGYLcgliyFCYklST51J\nXv50QN4AjolSXJY7ELNW5DaLIULiFGBVYHd3kTWzatxm0YEkdgZ2BjZyojCzRnCbRZuTWI3Uc2fv\nCJ7PHU+rU1kjVNYXcsdh1m6cLNqYxCLAZOCUCP6aO55Wp7LGAXcCG6gs/9s36wdXQ7W3Q4ClgRNz\nB9LKVJaArwJfAw51I7ZZ/zlZtCmJ0cD/A7b1utm9U1kjSKWvlYHNoxSPZg7JrC25KN6Giuk8TgN+\nHsF9ueNpcW8BtwFbO1GYDZy7zrYhiT1I6ylsHMHrueMxs/bT33unk0WbkVgBuB/YNYJbc8djZu3J\nyWKIKwbfLRrB4bljaTUqaw3gqSjFq7ljMWt1bTNFufWfxHrAXqQqKKugsj5K0TaROxazoci9odpE\n0aj9Y+CECJ7JHU+rKLrFfgn4OrBnlLykrlkjOFm0jx2ANYGfZ46jZaisJYEzgfcD49zbyaxxnCza\nQLFE6o+Br0YwN3c8LeQbpCnFt4pSvJI7GLOhzMmiPRwGTAeuzBxHq/ke8EaU2ryXhlkbcG+oFiex\nLPAQsH0E9+SOx8yGBveGGnomAv/nRGFmOblk0cIkhpNKFdtEMDV3PLmorMWB44AfRynm5I7HbCjw\n4kdDy5eAqzs8UYwALgXmAPMyh2PWsVyyaFESI4EHgXERPJQ7nhyKEdlXAtcBX4lSeHZdszppqzYL\nSRMkTZP0oKRjezlmvKQ7Jd0naUqTQ8zpq8BlHZwoNgH+CpwZpTjaicIsr2zVUJKGAacC2wEzgb9L\nujwiplYcM4I0CO3jETFD0qg80TZXUao4DNgkdywZ7QlMjFL8LncgZpa3zWJz4KGImA4g6SJgF1ig\nfn5v4LcRMQMgIjplmovDgD9EMD13ILlEKb6WOwYzm69qNZSkTxfVRLMlzSm22XW49mjg8YrHM4rn\nKq0NrCDpBkm3S/pcHa7b0iSWBI4EfpA7FjOzLrWULL4PfKKyeqhOamlZXwzYGPgoaa3pWyTdGhEP\nVh4kaVLFwykRbT2Z3P7A7RHcnzsQMxs6JI0Hxg/09bUkiycakCggtVOMqXg8hlS6qPQ48ExEvAq8\nKulGYENSL6G3RcSkBsTXdBLDgGOAg3LH0iwqawnSWuInRimezR2P2VBVfIme0vVYUqk/r68lWdwu\n6WLgMuCN+deNS/tzoZ7OC6wtaU1gFrAHaa2GSr8HTi0aw5cAtiBNqDdU7Qo8DdycO5BmUFnLAb8D\nXgBezhyOmfWhlmSxPPAqsH235weVLCLiTUkTgWuAYcDZETFV0qHF/jMiYpqkq4F7SAOyzoqIBwZz\n3VZVrFfxdeC/I2qqomtrKmsl4CrSl4Yj3DXWrLV5UF6LkNgGOANYL2Joj1RWWWOAP5G+cHzbs8aa\nNV/dp/uQNAY4BdiqeOpG4Oiu7qxWN0cBJw/1RFHYHzg7SvHD3IGYWW2qliwkXQf8Cji/eGofYJ+I\n+FiDY6vJUChZSKwO3AmsEcFLueNpNJUllybM8urvvbOWZHF3RGxY7blchkiyOAFYJoIv5Y7FzDpD\nI+aGelbS5yQNk7SopH2BThlJ3XDFILzPA7/IHYuZWW9qSRYHAZ8FngD+A+wOHNjIoDrMZ4E7I/hX\n7kAaQWVtp7JWzR2HmQ1O1QbuYu6mTzY+lI41Efhu7iAaQWXtCpwOfII0lsbM2lSvyULSsRFxkqSf\n9bA7IuKoBsbVESQ2B0aRxhsMKSprT+CnwA5Rijtyx2Nmg9NXyaJr8Ns/WHAeJ1HbvE5W3UTgtAiG\n1IA0lXUA8N/AdlGK+zKHY2Z1UEtvqM9GxCXVnsulXXtDFWtWPAK8J2LodBhQWZuRpvDYLkoxLXc8\nZtazRvSGOq7G56x/9iGtrz1kEkXhdmBjJwqzoaWvNosdgB2B0ZJOIVU/ASwHzG1CbENWMQ/UIaSl\nU4eUYrDdU7njMLP66qvNYhapvWKX4mdXspgNfLnBcQ11m5CS7p9zB2JmVota2iwWi4iWLUm0Y5uF\nxBnAYxGckDuWwVJZy0QpPL24WZup20SCkn4dEbsDd0gLnS8iYuwAY+xoEsuSBuK9P3csg6Wyvkyq\nqmyJecLMrHH6qoY6uvjpAXn1tTtwcwQzcwcyGEWimAhsmzsWM2u8XntDRUTXiNungceLkdxLAGOh\nvW90mX0eOCt3EIOhso4GjgS2jVI8ljseM2u8Wtos7iCtZTES+Avwd+CNiNin8eFV105tFhLvA24A\nxkTwZu54BkJlTST14hofpXg0dzxmNjCNGGehiHgF2A34RdGO0fb17ZnsD5zfromisDipROFEYdZB\nalmDG0kfJA0iO7h4qpYkYxUkhgH7khqE21aU4se5YzCz5qvlpv8l0ojt30XE/ZLeTapKsf7ZFng6\ngntzB2Jm1l9V2yzePlBajtRltqWW/WyXNguJycA/Ijg5dyxmZnVvs5C0gaQ7gfuBByT9Q5LbLPpB\nYjlgZ+DC3LH0h8r6lMp6V+44zCy/WqqhzgS+EhGrR8TqpJ4wZzY2rCFnN+DGiPaZM6li4aJlc8di\nZvnVkiyWjoi32ygiYgqwTD0uLmmCpGmSHpR0bB/HbSbpTUm71eO6GewPnJc7iFqprJ1IiWLHKMU9\nueMxs/xqSRaPSDpe0pqS1pL0beDhwV5Y0jDgVGACsB6wl6R1eznuJOBq5k9m2DYk1iANZLwidyy1\nUFnbAecCO3uFOzPrUkuyOBBYGbgU+C2wEnBQHa69OfBQREwvJiq8iDTDbXdHAr8hjSRvR/sCl0Tw\neu5AqlFZqwMXALtFKW7LHY+ZtY6+JhJcCvgi8B7gHlK7RT1nnx0NPF7xeAawRbcYRpMSyEeAzWiz\n5VyLdSv2IU3x0fKiFI+prM084M7MuutrUN55wBvAzcAOpKqio/s4vr9qufH/FPhGRITS1Lc9VkNJ\nmlTxcErRrtIKPgAsCdySO5BaOVGYDU2SxgPjB/z63sZZSLo3IjYofl8U+HtEbDTQC/Vw/nHApIiY\nUDw+DpgXESdVHPMw8xPEKOAV4JCIuLzimJYdZyHxQ+C1CL6dOxYzs0r1HGfx9vxFEdGIuYxuB9Yu\nGs4XB/YALq88ICLeFRFrRcRapHaLwyoTRSsrpvfYC/hV7lh6o/LCC5WYmfWkr2QxVtKcrg3YoOLx\n7MFeuEhAE4FrgAeAiyNiqqRDJR062PO3gPHAExFMzR1IT1TWGsDNKmt47ljMrPXVPN1Hq2rVaiiJ\nc4D7Imi5ifdU1qrAjcApUYpTcsdjZs3X33unk0UDSCwJzALeH8Gsasc3k8paCZgCnB+l+F7mcMws\nk0asZ2H99wngjhZMFCNI1X6XOVGYWX84WTTGPrRmw/ZOpOon984ys35xNVSdSYwEpgOrR/Bi5nAW\norIUpTb/o5vZoLnNIjOJg4EdIvhM7ljMzHrjNov89ibNr2RmNmQ4WdSRxKrARsCV2WMpaxGVNSZ3\nHGY2NPQ1N5T13x7AZRG8ljOIYmT2z0mzBX86ZyxmNjS4ZFFf2augikTxA2AT0vTyZmaD5pJFnUis\nA6wG3FDt2Ab7DrA9MD5KMehpWczMwMminvYCLo7grVwBqKxjiji2iVI8lysOMxt6XA1VB8UiR9mr\noICngO2iFE9mjsPMhhiPs6hLDGwCXAysHdFeq/mZWWfyOIs89gEucKIws6HKJYtBX59hpPXDx0fw\nz1xxmJn1h0sWzfcRYEazE4XKmqCyPtDMa5pZ53KyGLx9gfObeUGVtR0wGViimdc1s87laqhBXZul\ngZnAuhE80ZRrlrU1aT3yT0cpbmrGNc1s6OnvvdPjLAZnZ+C2JiaKLYHfAns6UZhZM7kaanCatsiR\nylqRlCj2jVJc34xrmpl1cTXUgK/LKOAhYEwEc5pyzbJWjVK01FKtZtaevPhR067L4cBWEezd7Gub\nmQ2Wu842z340uReUmVkuWZOFpAmSpkl6UNKxPezfR9Ldku6R9BdJY3PE2Z3EusDqwJ8ado2y3PnA\nzFpGtmQhaRhwKjABWA/YS9K63Q57GNg6IsYC/wWc2dwoe3UA8MsI3mzEyVXWWOAelTW8Eec3M+uv\nnN9eNwceiojpAJIuAnYBpnYdEBG3VBx/G2m9iKwkFgU+B3y0IedPo7KvBo72ehRm1ipyVkONBh6v\neDyjeK43B9MCa1uTFhZ6LGJ+UqsXlbURKVEcGaW4uN7nNzMbqJwli5q7YUnaFjgI2LKX/ZMqHk6J\niCmDiqxvBwD/W++TqqxNgD8Ch0cpLq33+c2ss0kaD4wf6OtzJouZwJiKx2NIpYsFFI3aZwETIuL5\nnk4UEZMaEeDCsbACqWTxhQacfh3gi1GKyxpwbjPrcMWX6CldjyWV+vP6bOMsJC0K/JNU9z8L+Buw\nV0RMrThmdeDPwL4RcWsv52naOAuJI0hjK/ZqxvXMzBqlbeaGiog3JU0ErgGGAWdHxFRJhxb7zwC+\nA4wETpMEMDciNs8VM6kK6lsZr29mloVHcNd8HTYGLgPWiuCtRl/PzKyRPIK7cQ4DTq9HolBZ+6is\nD9YhJjOzpvAo4RpIjAQ+A7xv0Ocq63Dgm6SGcjOztuBkUZv9gSsjeHKgJ1BZAo4vzrV1lOLhegVn\nZtZoThZVSCwCHA4cOOBzlDUMOBnYCtgyStGUxZLMzOrFyaK6jwCvAn8dxDk2JVVhbROleLEuUZmZ\nNZF7Q1U9P5cC10RwxqDOU5ai1OYftpkNGV78qK7nZgxwF7BGBC814hpmZjm462x9HUWaityJwsw6\nmksWvZ6XUcC/gLERC89Z1evrytoNeDFKcX29YzIzq5e2me6jDRwN/LrWRFF0jf0WcCjwqUYGZmbW\nbE4WPZAYQRqxXdM8VCprKeBs4D3AFlGKWQ0Mz8ys6ZwsejYR+GMEVQfOqax3Ab8F7id1jX210cGZ\nWX1Iau96+BrVo6reyaIbiWVJDdtb1/iS1YFzgZ+5a6xZ+2nWEge51CshuoF7ofPxNWDTCPao1znN\nrDU1cz2cXHp7j27gHoSiB9QxwHa5YzEzayUeZ7Gg7wMXRnBvTztV1qBnnTUza0euhnr7PGwFXASs\nF8HsBfa71dNeAAAKbUlEQVSVtTzwE1I7xoZRipcHez0zy8/VUB7B3S8SiwGnAV/pIVF8HLgXeB3Y\nyInCzDqR2yySo4FZwK+7nlBZKwI/AsYDB0UprssTmpl1GknnA29ExEEVz21D6qa/fkQMeG2dger4\nZCGxDvANYFwE3evkZgIbRCnmND8yM+tgRwH3S9ouIq6TtCRwFvCVHIkCOrzNQmIl4BbgxAj+p76R\nmVmra+U2C0mfIXW6eT9plc2xEbGTpCuBByLimOK4i4CXI+LgXs7jrrODIbEU8HvgYibpAhYqVJiZ\n5RMRv5G0J6njzYeADYtdBwL3SPojsCppcbUNez5L/XRkskhLpc6bzNhfvcau+21K+mPsnDsuM2st\nUn2+RUYw0NLL4cC/gW9GxMx0rnhS0mHAZGBJYJeIxne8ydobStIESdMkPSjp2F6OOaXYf7ekjQZ9\nzY98ezTblG9m4ro7sOv+qyAuBHYf7HnNbOiJQPXYBn79eAp4hjT3XKUrgGHAtIgYzJLPNctWspA0\nDDiVNFp6JvB3SZdHxNSKY3YE3hMRa0vagtS9ddyAr7nIm9ty2KXX8PryM1nslf1Q/M7zOZlZGzoB\neABYU9KeEXFRoy+Ysxpqc+ChiJgObzfS7AJMrThmZ+A8gIi4TdIISatU6w2gskYBb0UpnpdYlJRg\n9oVFP8E5f9ktXh15RQPej5lZw0naGjgAGAu8G/idpBsjGrs0Qs5kMRp4vOLxDGCLGo5ZDVggWejg\nLaexxOxFWfylxVj6mRVYZMnFuPkb12sSrwEfAR4BrgTGxqsjn6v3GzEzawZJw0lfoI+IiP8A/5F0\nNnAOMKGR186ZLGqt/ule37fw666Z/QZzl3yNN0fCWwf+jdnfuosY9jrwBHBEBE8MMlYzsywiYq2K\n32cDa3Xb/41aziNpPGmQ8YDkTBYzgTEVj8fAQkuYdj9mteK5BcSMe8fWPTozsyEkIqYAU7oeSyr1\n5/U5e0PdDqwtaU1JiwN7AJd3O+ZyYD8ASeOAF3KNXjQz62TZShYR8aakicA1pC5gZ0fEVEmHFvvP\niIgrJe0o6SHgZdJgFDMza7KOnu7DzDpbJ9w/PEW5mZk1jZOFmZlV5WRhZmZVOVmYmVlVThZmZlaV\nk4WZWYuRdL6kc7o9t42kZyStkiMmJwszs9ZzFLCDpO0AWmFZVScLM7MWExHPAUcCZ0paGigBDwLX\nSHpF0gpdx0raWNJTxbIPDeNBeWbWsVr9/iHpN8DiFMuqRsTMYjnVP0TE6cUxPwEWiYijezlHXQbl\nOVmYWceqdv9QWZNI3+q7K0cpJtV4fI/H1hjfysxfVvVnxXN7AEdGxFZFaWIG8MmIuL2XczhZgJOF\nmQ1cO9w/JD0CHBwRfy4eLwnMAjYG3gf8NCLe18fr65Isck5RbmZm/RQRr0n6NbAvKVlMbsZ1nSzM\nzNrP5GJbCTiuGRd0bygzszYTEX8B5gH/iIjHqx1fDy5ZmJm1sMplVbt5FLigWXE4WZiZtRlJm5Ea\nuHdp1jVdDWVm1kYknQdcC3wpIl5u2nXdddbMOlUn3D+8Up6ZmTWNk4WZmVXlZGFmZlW5N5SZdTRJ\n7d1w2yRZkkUxve7FwBrAdOCzEfFCt2PGkEYorgwEcGZEnNLkUM1sCBvqjdv1lKsa6hvAtRGxDnB9\n8bi7ucCXI2J9YBxwhKR1mxhj25E0PncMrcKfxXz+LObzZzFwuZLFzsB5xe/nAZ/qfkBEPBERdxW/\nvwRMBVZtWoTtaXzuAFrI+NwBtJDxuQNoIeNzB9CuciWLVSqWBnwS6HNNWUlrAhsBtzU2LDMz60nD\n2iwkXQu8o4dd36p8EBHRVwOTpGWB3wBHFyUMMzNrsiwjuCVNA8ZHxBOS3gnc0NPiHZIWA64AroqI\nn/ZyLvdkMDMbgHZY/OhyYH/gpOLnZd0PkCTgbOCB3hIFuDeDmVkz5CpZrABcAqxORddZSasCZ0XE\nTpK2Am4E7iF1nQU4LiKubnrAZmYdru0nEjQzs8Zr6+k+JE2QNE3Sg5KOzR1PLpLGSLpB0v2S7pN0\nVO6YcpM0TNKdkv6QO5acJI2Q9BtJUyU9IGlc7phykXRc8X/kXkkXSFoid0zNIukcSU9KurfiuRUk\nXSvpX5L+JGlEX+do22QhaRhwKjABWA/Yq4MH7XkA48KOBh5gfhVmpzoZuDIi1gXGksYrdZyi+/0h\nwMYRsQEwDNgzZ0xNdi7pXlmplsHRb2vbZAFsDjwUEdMjYi5wEU1cNaqVeADjgiStBuwI/A/QsR0g\nJC0PfDgizgGIiDcj4sXMYeUym/SlamlJiwJLAzPzhtQ8EXET8Hy3p6sOjq7UzsliNFC5UPmM4rmO\n5gGMAPwE+BppQftOthbwtKRzJd0h6SxJS+cOKoeIeA74EfAYMAt4ISKuyxtVdv0aHN3OyaLTqxcW\n4gGMIOkTwFMRcScdXKooLEpap/kXEbEx8DJVqhqGKknvBr4ErEkqdS8raZ+sQbWQSD2d+ryntnOy\nmAmMqXg8hlS66EjFAMbfAudHxELjVjrIh4CdJT0CXAh8RNLkzDHlMgOYERF/Lx7/hpQ8OtGmwF8j\n4tmIeBO4lPRvpZM9KekdAMXg6Kf6Oridk8XtwNqS1pS0OLAHabBfx6l1AGMniIhvRsSYiFiL1ID5\n54jYL3dcOUTEE8DjktYpntoOuD9jSDlNA8ZJWqr4/7IdqQNEJ+saHA29DI6u1LaLH0XEm5ImAteQ\nejacHREd2dMD2BLYF7hH0p3Fcx7AmHR6deWRwK+KL1T/Bg7MHE8WEXF3UcK8ndSWdQdwZt6omkfS\nhcA2wChJjwPfAU4ELpF0MMXg6D7P4UF5ZmZWTTtXQ5mZWZM4WZiZWVVOFmZmVpWThZmZVeVkYWZm\nVTlZmJlZVU4WZhUkrVhMbX6npP9ImlH8PkfSqQ265kRJB/Sxf2dJxzfi2ma18jgLs15IKgFzIuLH\nDbyGSAPENiumoejtmDuLY+Y2KhazvrhkYdY3AUga37WQkqRJks6TdKOk6ZJ2k/RDSfdIuqqYAhtJ\nm0iaIul2SVd3zcPTzZbAtK5EIemoYoGeu4tRt12TvN0CbN+MN2zWEycLs4FZC9iWtCbA+aRFZMYC\nrwI7FRM7/gz4dERsSlp85oQezrMVaQqKLscCH4iIDYFDK57/G7B13d+FWY3adm4os4wCuCoi3pJ0\nH7BIRFxT7LuXNA32OsD6wHWpFolhpHUUulsduLni8T3ABZIuY8GJ3Wax8EpnZk3jZGE2MG8ARMQ8\nSZXtCPNI/68E3B8RtUyDXbnuxk6kEsQngW9Jen9EzCPVAriB0bJxNZRZ/9WyqNI/gZUkjYO03oik\n9Xo47lGga00BAatHxBTSIkXLA8sWx72zONYsCycLs75Fxc+efoeFv/FH0WvpM8BJku4i9Wb6YA/n\nv5m0MA+kEskvJd1D6iF1ckTMLvZtDtw4mDdiNhjuOmuWUUXX2S0i4o1ejlmkOGbT3rrXmjWaSxZm\nGRXdYs8C+loP+hPAb5woLCeXLMzMrCqXLMzMrConCzMzq8rJwszMqnKyMDOzqpwszMysKicLMzOr\n6v8DfENdKxw8Sq0AAAAASUVORK5CYII=\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}, {"source": "The plot above shows the $x$ and $y$ positions of the aircraft when it is commanded to move 1 m in each direction. The following shows the $x$ motion for control weights $\\rho = 1, 10^2, 10^4$. A higher weight of the input term in the cost function causes a more sluggish response. It is created using the code:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 9, "cell_type": "code", "source": "# Look at different input weightings\nQu1a = diag([1, 1]); (K1a, X, E) = lqr(A, B, Qx1, Qu1a);\nH1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx);\n\nQu1b = (40**2)*diag([1, 1]); (K1b, X, E) = lqr(A, B, Qx1, Qu1b);\nH1bx = ss(Ax - Bx*K1b[0,lat], Bx*K1b[0,lat]*xd[lat,:],Cx, Dx);\n\nQu1c = (200**2)*diag([1, 1]); (K1c, X, E) = lqr(A, B, Qx1, Qu1c);\nH1cx = ss(Ax - Bx*K1c[0,lat], Bx*K1c[0,lat]*xd[lat,:],Cx, Dx);\n\n[T1, Y1] = step(H1ax, T=linspace(0,10,100));\n[T2, Y2] = step(H1bx, T=linspace(0,10,100));\n[T3, Y3] = step(H1cx, T=linspace(0,10,100));", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 10, "cell_type": "code", "source": "plot(Y1.T, T1, 'b-'); hold(True);\nplot(Y2.T, T2, 'r-'); hold(True);\nplot(Y3.T, T3, 'g-'); hold(True);\nplot([0 ,10], [1, 1], 'k-'); hold(True);\ntitle('Step Response for Inputs');\nylabel('Position');\nxlabel('Time (s)');\nlegend(('Y1','Y2','Y3'),loc='lower right');\naxis([0, 10, -0.1, 1.4]); ", "outputs": [{"output_type": "display_data", "data": {"image/png": "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\ni76yKeGdswAAAABJRU5ErkJggg==\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}, {"source": "##Lateral control using inner/outer loop design\nThis section demonstrates the design of loop shaping controller for the vectored thrust aircraft example. This example is pulled from Chapter 11 [Frequency Domain Design](http:www.cds.caltech.edu/~murray/amwiki) of Astrom and Murray. \n\nTo design a controller for the lateral dynamics of the vectored thrust aircraft, we make use of a \"inner/outer\" loop design methodology. We begin by representing the dynamics using the block diagram\n\n\nwhere\n \nThe controller is constructed by splitting the process dynamics and controller into two components: an inner loop consisting of the roll dynamics $P_i$ and control $C_i$ and an outer loop consisting of the lateral position dynamics $P_o$ and controller $C_o$.\n\nThe closed inner loop dynamics $H_i$ control the roll angle of the aircraft using the vectored thrust while the outer loop controller $C_o$ commands the roll angle to regulate the lateral position.\n\nThe following code imports the libraries that are required and defines the dynamics:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 11, "cell_type": "code", "source": "from matplotlib.pyplot import * # Grab MATLAB plotting functions\nfrom control.matlab import * # MATLAB-like functions", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 12, "cell_type": "code", "source": "# System parameters\nm = 4; # mass of aircraft\nJ = 0.0475; # inertia around pitch axis\nr = 0.25; # distance to center of force\ng = 9.8; # gravitational constant\nc = 0.05; # damping factor (estimated)\nprint \"m = %f\" % m\nprint \"J = %f\" % J\nprint \"r = %f\" % r\nprint \"g = %f\" % g\nprint \"c = %f\" % c", "outputs": [{"output_type": "stream", "name": "stdout", "text": "m = 4.000000\nJ = 0.047500\nr = 0.250000\ng = 9.800000\nc = 0.050000\n"}], "metadata": {"collapsed": false, "trusted": true}}, {"execution_count": 13, "cell_type": "code", "source": "# Transfer functions for dynamics\nPi = tf([r], [J, 0, 0]); # inner loop (roll)\nPo = tf([1], [m, c, 0]); # outer loop (position)", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "For the inner loop, use a lead compensator", "cell_type": "markdown", "metadata": {}}, {"execution_count": 14, "cell_type": "code", "source": "k = 200; a = 2; b = 50\nCi = k*tf([1, a], [1, b]) # lead compensator\nLi = Pi*Ci", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "The closed loop dynamics of the inner loop, $H_i$, are given by", "cell_type": "markdown", "metadata": {}}, {"execution_count": 15, "cell_type": "code", "source": "Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1));", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "Finally, we design the lateral compensator using another lead compenstor", "cell_type": "markdown", "metadata": {}}, {"execution_count": 16, "cell_type": "code", "source": "# Now design the lateral control system\na = 0.02; b = 5; K = 2;\nCo = -K*tf([1, 0.3], [1, 10]); # another lead compensator\nLo = -m*g*Po*Co;", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"source": "The performance of the system can be characterized using the sensitivity function and the complementary sensitivity function:", "cell_type": "markdown", "metadata": {}}, {"execution_count": 17, "cell_type": "code", "source": "L = Co*Hi*Po;\nS = feedback(1, L);\nT = feedback(L, 1);", "outputs": [], "metadata": {"collapsed": true, "trusted": true}}, {"execution_count": 18, "cell_type": "code", "source": "t, y = step(T,T=linspace(0,10,100))\nplot(y, t)\ntitle(\"Step Response\")\ngrid()\nxlabel(\"time (s)\")\nylabel(\"y(t)\")", "outputs": [{"execution_count": 18, "output_type": "execute_result", "data": {"text/plain": ""}, "metadata": {}}, {"output_type": "display_data", "data": {"image/png": "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\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}, {"source": "The frequency response and Nyquist plot for the loop transfer function are computed using the commands", "cell_type": "markdown", "metadata": {}}, {"execution_count": 19, "cell_type": "code", "source": "bode(L);", "outputs": [{"output_type": "display_data", "data": {"image/png": "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\nGZxzH3gVd6cS60xK0lf0tb1b+prkH3p91ekVdHIdxq3S1A1h6kzb30npS24MG78Tjh8DvB8u3A/m\nezOc+ReJC2HfZ2HazfbdF7Sir0l4VKwzyc6nqEPuVNp9M7lN0i8lrS9poqQjgNslzQ9tv5J2atHj\nCNOd3L7MbKNs0zIVX27u8tVlGoWr0mbWOW+HXOXL0Nfkmnnpir5a+UeTvgZaZ9bL0yZVtj36Epxw\nV/YmsyN8/Iuw17bwqW8Dr8C6n4Ffny5xlcS+sP27Yd6bG2nJEa55v/Xw+2uUp/C9x+t/jwfmtKkp\n7b6ZTAZ2A/bKwtcA/4/UkHyszToLr3wPgmA0cOsz2cyyi6Qtr4S3zw8PjQEmwXZfhe3fIHEucBEs\n/zT89d/l2jtKcMF50+0e/KdPrnmAe7L4+Uit5Ypt1OsO2DaxSJ56adXxjcJ5zrulrSx9RbV1U1+e\nuGHWV09rJ3+bndO3ybbgXcHngZ9Of390IHixdr+7Xuor8dniItraejORtDzwQ2AlYIEs2raXy1m+\nKyvfK+o/jvDNVTOct3xZ+gZ1TGHY9VWnV9CPvrneZnMI8Cvp3R+HHd4PK6wPzJbO/Cvc8wd479UN\n6hsVYyYV9ZXqm+sa4ADgIOCTpG6vsc4GzbqFpC1I61MWITU2l9bIY8fU4CAIqpBYCNiU5Jl8U5Lf\nv1OAM22eKtO2fqDos7PdxuRG22tJmuW560RutF1rMWPHkbQo8DPbu9RIi8YkCIKGSCwIfIK0lu1j\nwBWkhuU8m+fKtK0sij472x2Af0FpkeHdWdfUw8BCeQur4Ap4YH/S1r716j+Ogt1ctg9plH8krpXy\n9crWClfFVda3F23sHFkRzlW+DH3V+ftJX638o0lfA82v2TNI+rLwaZL+DiscDTt8GKbsApcfI11w\nJ/x8f+Ay0O4l6Gv0/KlZvo6+euHq5wmU6OhxHdLWvUsDxwFnAO9vofx6wJq8fgB+LHA3aQB+XrIB\neGB74GDg7YCAHwMbNKjb7WiqqmNikTz10qrjG4XznHdLW1n6imrrpr48ccOsr57WTv42e6mvvh6/\nFQ7+Bfg68KNw3Ong94HVK30lPltcRFtb3VydQP+5j8kHSL5hJmXhKZm6AyvK7AF8keRqZaazbYSr\n6rWjmysIgoJITAA+T9rt9VXgJOAkm3tKNaxL9LSbS9K5gElvCNXY9ifbNYR8K+APBQ7NYedxFFsB\n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\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}, {"execution_count": 20, "cell_type": "code", "source": "nyquist(L, (0.0001, 1000));", "outputs": [{"output_type": "display_data", "data": {"image/png": "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\nLKv/D2ULb19b6nZgAAAAAElFTkSuQmCC\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}, {"execution_count": 21, "cell_type": "code", "source": "gangof4(Hi*Po, Co);", "outputs": [{"output_type": "display_data", "data": {"image/png": "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\nAAAASUVORK5CYII=\n", "text/plain": ""}, "metadata": {}}], "metadata": {"collapsed": false, "trusted": true}}], "nbformat": 4, "metadata": {"kernelspec": {"display_name": "Python 2", "name": "python2", "language": "python"}, "language_info": {"mimetype": "text/x-python", "nbconvert_exporter": "python", "version": "2.7.6", "name": "python", "file_extension": ".py", "pygments_lexer": "ipython2", "codemirror_mode": {"version": 2, "name": "ipython"}}}} \ No newline at end of file +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# `python-control` Example: Vertical takeoff and landing aircraft\n", + "\n", + "http://www.cds.caltech.edu/~murray/wiki/index.php/Python-control/Example:_Vertical_takeoff_and_landing_aircraft\n", + "\n", + "This page demonstrates the use of the python-control package for analysis and design of a controller for a vectored thrust aircraft model that is used as a running example through the text *Feedback Systems* by Astrom and Murray. This example makes use of MATLAB compatible commands. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## System Description\n", + "This example uses a simplified model for a (planar) vertical takeoff and landing aircraft (PVTOL), as shown below:\n", + " \n", + "\n", + "The position and orientation of the center of mass of the aircraft is denoted by $(x,y,\\theta)$, $m$ is the mass of the vehicle, $J$ the moment of inertia, $g$ the gravitational constant and $c$ the damping coefficient. The forces generated by the main downward thruster and the maneuvering thrusters are modeled as a pair of forces $F_1$ and $F_2$ acting at a distance $r$ below the aircraft (determined by the geometry of the thrusters).\n", + "\n", + "It is convenient to redefine the inputs so that the origin is an equilibrium point of the system with zero input. Letting $u_1 =\n", + "F_1$ and $u_2 = F_2 - mg$, the equations can be written in state space form as:\n", + "\n", + "\n", + "## LQR state feedback controller\n", + "This section demonstrates the design of an LQR state feedback controller for the vectored thrust aircraft example. This example is pulled from Chapter 6 (State Feedback) of [http:www.cds.caltech.edu/~murray/amwiki Astrom and Murray]. The python code listed here are contained the the file pvtol-lqr.py.\n", + "\n", + "To execute this example, we first import the libraries for SciPy, MATLAB plotting and the python-control package:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from numpy import * # Grab all of the NumPy functions\n", + "from matplotlib.pyplot import * # Grab MATLAB plotting functions\n", + "from control.matlab import * # MATLAB-like functions\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The parameters for the system are given by" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "m = 4.000000\n", + "J = 0.047500\n", + "r = 0.250000\n", + "g = 9.800000\n", + "c = 0.050000\n" + ] + } + ], + "source": [ + "m = 4 # mass of aircraft\n", + "J = 0.0475 # inertia around pitch axis\n", + "r = 0.25 # distance to center of force\n", + "g = 9.8 # gravitational constant\n", + "c = 0.05 # damping factor (estimated)\n", + "print(\"m = %f\" % m)\n", + "print(\"J = %f\" % J)\n", + "print(\"r = %f\" % r)\n", + "print(\"g = %f\" % g)\n", + "print(\"c = %f\" % c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The linearization of the dynamics near the equilibrium point $x_e = (0, 0, 0, 0, 0, 0)$, $u_e = (0, mg)$ are given by" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# State space dynamics\n", + "xe = [0, 0, 0, 0, 0, 0] # equilibrium point of interest\n", + "ue = [0, m*g] # (note these are lists, not matrices)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# Dynamics matrix (use matrix type so that * works for multiplication)\n", + "A = matrix(\n", + " [[ 0, 0, 0, 1, 0, 0],\n", + " [ 0, 0, 0, 0, 1, 0],\n", + " [ 0, 0, 0, 0, 0, 1],\n", + " [ 0, 0, (-ue[0]*sin(xe[2]) - ue[1]*cos(xe[2]))/m, -c/m, 0, 0],\n", + " [ 0, 0, (ue[0]*cos(xe[2]) - ue[1]*sin(xe[2]))/m, 0, -c/m, 0],\n", + " [ 0, 0, 0, 0, 0, 0 ]])\n", + "\n", + "# Input matrix\n", + "B = matrix(\n", + " [[0, 0], [0, 0], [0, 0],\n", + " [cos(xe[2])/m, -sin(xe[2])/m],\n", + " [sin(xe[2])/m, cos(xe[2])/m],\n", + " [r/J, 0]])\n", + "\n", + "# Output matrix \n", + "C = matrix([[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0]])\n", + "D = matrix([[0, 0], [0, 0]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To compute a linear quadratic regulator for the system, we write the cost function as\n", + "\n", + "\n", + "where $z = z - z_e$ and $v = u - u_e$ represent the local coordinates around the desired equilibrium point $(z_e, u_e)$. We begin with diagonal matrices for the state and input costs:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "Qx1 = diag([1, 1, 1, 1, 1, 1])\n", + "Qu1a = diag([1, 1])\n", + "(K, X, E) = lqr(A, B, Qx1, Qu1a); K1a = matrix(K)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This gives a control law of the form $v = -K z$, which can then be used to derive the control law in terms of the original variables:\n", + "\n", + "\n", + " $$u = v + u_d = - K(z - z_d) + u_d.$$\n", + "where $u_d = (0, mg)$ and $z_d = (x_d, y_d, 0, 0, 0, 0)$\n", + "\n", + "Since the `python-control` package only supports SISO systems, in order to compute the closed loop dynamics, we must extract the dynamics for the lateral and altitude dynamics as individual systems. In addition, we simulate the closed loop dynamics using the step command with $K x_d$ as the input vector (assumes that the \"input\" is unit size, with $xd$ corresponding to the desired steady state. The following code performs these operations:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "xd = matrix([[1], [0], [0], [0], [0], [0]]) \n", + "yd = matrix([[0], [1], [0], [0], [0], [0]]) " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# Indices for the parts of the state that we want\n", + "lat = (0,2,3,5)\n", + "alt = (1,4)\n", + "\n", + "# Decoupled dynamics\n", + "Ax = (A[lat, :])[:, lat] #! not sure why I have to do it this way\n", + "Bx, Cx, Dx = B[lat, 0], C[0, lat], D[0, 0]\n", + " \n", + "Ay = (A[alt, :])[:, alt] #! not sure why I have to do it this way\n", + "By, Cy, Dy = B[alt, 1], C[1, alt], D[1, 1]\n", + "\n", + "# Step response for the first input\n", + "H1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx)\n", + "(Tx, Yx) = step(H1ax, T=linspace(0,10,100))\n", + "\n", + "# Step response for the second input\n", + "H1ay = ss(Ay - By*K1a[1,alt], By*K1a[1,alt]*yd[alt,:], Cy, Dy)\n", + "(Ty, Yy) = step(H1ay, T=linspace(0,10,100))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot(Yx.T, Tx, '-', Yy.T, Ty, '--')\n", + "plot([0, 10], [1, 1], 'k-')\n", + "ylabel('Position')\n", + "xlabel('Time (s)')\n", + "title('Step Response for Inputs')\n", + "legend(('Yx', 'Yy'), loc='lower right')\n", + "show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The plot above shows the $x$ and $y$ positions of the aircraft when it is commanded to move 1 m in each direction. The following shows the $x$ motion for control weights $\\rho = 1, 10^2, 10^4$. A higher weight of the input term in the cost function causes a more sluggish response. It is created using the code:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Look at different input weightings\n", + "Qu1a = diag([1, 1])\n", + "K1a, X, E = lqr(A, B, Qx1, Qu1a)\n", + "H1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx)\n", + "\n", + "Qu1b = (40**2)*diag([1, 1])\n", + "K1b, X, E = lqr(A, B, Qx1, Qu1b)\n", + "H1bx = ss(Ax - Bx*K1b[0,lat], Bx*K1b[0,lat]*xd[lat,:],Cx, Dx)\n", + "\n", + "Qu1c = (200**2)*diag([1, 1])\n", + "K1c, X, E = lqr(A, B, Qx1, Qu1c)\n", + "H1cx = ss(Ax - Bx*K1c[0,lat], Bx*K1c[0,lat]*xd[lat,:],Cx, Dx)\n", + "\n", + "[T1, Y1] = step(H1ax, T=linspace(0,10,100))\n", + "[T2, Y2] = step(H1bx, T=linspace(0,10,100))\n", + "[T3, Y3] = step(H1cx, T=linspace(0,10,100))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot(Y1.T, T1, 'b-')\n", + "plot(Y2.T, T2, 'r-')\n", + "plot(Y3.T, T3, 'g-')\n", + "plot([0 ,10], [1, 1], 'k-')\n", + "title('Step Response for Inputs')\n", + "ylabel('Position')\n", + "xlabel('Time (s)')\n", + "legend(('Y1','Y2','Y3'),loc='lower right')\n", + "axis([0, 10, -0.1, 1.4])\n", + "show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lateral control using inner/outer loop design\n", + "This section demonstrates the design of loop shaping controller for the vectored thrust aircraft example. This example is pulled from Chapter 11 [Frequency Domain Design](http:www.cds.caltech.edu/~murray/amwiki) of Astrom and Murray. \n", + "\n", + "To design a controller for the lateral dynamics of the vectored thrust aircraft, we make use of a \"inner/outer\" loop design methodology. We begin by representing the dynamics using the block diagram\n", + "\n", + "\n", + "where\n", + " \n", + "The controller is constructed by splitting the process dynamics and controller into two components: an inner loop consisting of the roll dynamics $P_i$ and control $C_i$ and an outer loop consisting of the lateral position dynamics $P_o$ and controller $C_o$.\n", + "\n", + "The closed inner loop dynamics $H_i$ control the roll angle of the aircraft using the vectored thrust while the outer loop controller $C_o$ commands the roll angle to regulate the lateral position.\n", + "\n", + "The following code imports the libraries that are required and defines the dynamics:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib.pyplot import * # Grab MATLAB plotting functions\n", + "from control.matlab import * # MATLAB-like functions" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "m = 4.000000\n", + "J = 0.047500\n", + "r = 0.250000\n", + "g = 9.800000\n", + "c = 0.050000\n" + ] + } + ], + "source": [ + "# System parameters\n", + "m = 4 # mass of aircraft\n", + "J = 0.0475 # inertia around pitch axis\n", + "r = 0.25 # distance to center of force\n", + "g = 9.8 # gravitational constant\n", + "c = 0.05 # damping factor (estimated)\n", + "print(\"m = %f\" % m)\n", + "print(\"J = %f\" % J)\n", + "print(\"r = %f\" % r)\n", + "print(\"g = %f\" % g)\n", + "print(\"c = %f\" % c)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# Transfer functions for dynamics\n", + "Pi = tf([r], [J, 0, 0]) # inner loop (roll)\n", + "Po = tf([1], [m, c, 0]) # outer loop (position)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the inner loop, use a lead compensator" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "k = 200\n", + "a = 2\n", + "b = 50\n", + "Ci = k*tf([1, a], [1, b]) # lead compensator\n", + "Li = Pi*Ci" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The closed loop dynamics of the inner loop, $H_i$, are given by" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we design the lateral compensator using another lead compenstor" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# Now design the lateral control system\n", + "a = 0.02\n", + "b = 5\n", + "K = 2\n", + "Co = -K*tf([1, 0.3], [1, 10]) # another lead compensator\n", + "Lo = -m*g*Po*Co" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The performance of the system can be characterized using the sensitivity function and the complementary sensitivity function:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "L = Co*Hi*Po\n", + "S = feedback(1, L)\n", + "T = feedback(L, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "t, y = step(T, T=linspace(0,10,100))\n", + "plot(y, t)\n", + "title(\"Step Response\")\n", + "grid()\n", + "xlabel(\"time (s)\")\n", + "ylabel(\"y(t)\")\n", + "show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The frequency response and Nyquist plot for the loop transfer function are computed using the commands" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "bode(L)\n", + "show()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "nyquist(L, (0.0001, 1000))\n", + "show()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "gangof4(Hi*Po, Co)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (pctest)", + "language": "python", + "name": "pctest" + }, + "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.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/examples/pvtol-lqr.py b/examples/pvtol-lqr.py index 8412dc2ff..611931a9a 100644 --- a/examples/pvtol-lqr.py +++ b/examples/pvtol-lqr.py @@ -8,10 +8,9 @@ # import os - -from numpy import * # Grab all of the NumPy functions -from matplotlib.pyplot import * # Grab MATLAB plotting functions -from control.matlab import * # MATLAB-like functions +import numpy as np +import matplotlib.pyplot as plt # MATLAB plotting functions +from control.matlab import * # MATLAB-like functions # # System dynamics @@ -21,35 +20,41 @@ # # System parameters -m = 4; # mass of aircraft -J = 0.0475; # inertia around pitch axis -r = 0.25; # distance to center of force -g = 9.8; # gravitational constant -c = 0.05; # damping factor (estimated) +m = 4 # mass of aircraft +J = 0.0475 # inertia around pitch axis +r = 0.25 # distance to center of force +g = 9.8 # gravitational constant +c = 0.05 # damping factor (estimated) # State space dynamics -xe = [0, 0, 0, 0, 0, 0]; # equilibrium point of interest -ue = [0, m*g]; # (note these are lists, not matrices) +xe = [0, 0, 0, 0, 0, 0] # equilibrium point of interest +ue = [0, m*g] # (note these are lists, not matrices) + +# TODO: The following objects need converting from np.matrix to np.array +# This will involve re-working the subsequent equations as the shapes +# See below. # Dynamics matrix (use matrix type so that * works for multiplication) -A = matrix( - [[ 0, 0, 0, 1, 0, 0], - [ 0, 0, 0, 0, 1, 0], - [ 0, 0, 0, 0, 0, 1], - [ 0, 0, (-ue[0]*sin(xe[2]) - ue[1]*cos(xe[2]))/m, -c/m, 0, 0], - [ 0, 0, (ue[0]*cos(xe[2]) - ue[1]*sin(xe[2]))/m, 0, -c/m, 0], - [ 0, 0, 0, 0, 0, 0 ]]) +A = np.matrix( + [[0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, (-ue[0]*np.sin(xe[2]) - ue[1]*np.cos(xe[2]))/m, -c/m, 0, 0], + [0, 0, (ue[0]*np.cos(xe[2]) - ue[1]*np.sin(xe[2]))/m, 0, -c/m, 0], + [0, 0, 0, 0, 0, 0]] +) # Input matrix -B = matrix( +B = np.matrix( [[0, 0], [0, 0], [0, 0], - [cos(xe[2])/m, -sin(xe[2])/m], - [sin(xe[2])/m, cos(xe[2])/m], - [r/J, 0]]) + [np.cos(xe[2])/m, -np.sin(xe[2])/m], + [np.sin(xe[2])/m, np.cos(xe[2])/m], + [r/J, 0]] +) # Output matrix -C = matrix([[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0]]) -D = matrix([[0, 0], [0, 0]]) +C = np.matrix([[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0]]) +D = np.matrix([[0, 0], [0, 0]]) # # Construct inputs and outputs corresponding to steps in xy position @@ -61,16 +66,16 @@ # The way these vectors are used is to compute the closed loop system # dynamics as # -# xdot = Ax + B u => xdot = (A-BK)x + K xd -# u = -K(x - xd) y = Cx +# xdot = Ax + B u => xdot = (A-BK)x + K xd +# u = -K(x - xd) y = Cx # # The closed loop dynamics can be simulated using the "step" command, # with K*xd as the input vector (assumes that the "input" is unit size, # so that xd corresponds to the desired steady state. # -xd = matrix([[1], [0], [0], [0], [0], [0]]); -yd = matrix([[0], [1], [0], [0], [0], [0]]); +xd = np.matrix([[1], [0], [0], [0], [0], [0]]) +yd = np.matrix([[0], [1], [0], [0], [0], [0]]) # # Extract the relevant dynamics for use with SISO library @@ -83,91 +88,127 @@ # # Indices for the parts of the state that we want -lat = (0,2,3,5); -alt = (1,4); +lat = (0, 2, 3, 5) +alt = (1, 4) # Decoupled dynamics -Ax = (A[lat, :])[:, lat]; #! not sure why I have to do it this way -Bx = B[lat, 0]; Cx = C[0, lat]; Dx = D[0, 0]; +Ax = (A[lat, :])[:, lat] # ! not sure why I have to do it this way +Bx = B[lat, 0] +Cx = C[0, lat] +Dx = D[0, 0] -Ay = (A[alt, :])[:, alt]; #! not sure why I have to do it this way -By = B[alt, 1]; Cy = C[1, alt]; Dy = D[1, 1]; +Ay = (A[alt, :])[:, alt] # ! not sure why I have to do it this way +By = B[alt, 1] +Cy = C[1, alt] +Dy = D[1, 1] # Label the plot -clf(); -suptitle("LQR controllers for vectored thrust aircraft (pvtol-lqr)") +plt.clf() +plt.suptitle("LQR controllers for vectored thrust aircraft (pvtol-lqr)") # # LQR design # # Start with a diagonal weighting -Qx1 = diag([1, 1, 1, 1, 1, 1]); -Qu1a = diag([1, 1]); -(K, X, E) = lqr(A, B, Qx1, Qu1a); K1a = matrix(K); +Qx1 = np.diag([1, 1, 1, 1, 1, 1]) +Qu1a = np.diag([1, 1]) +K, X, E = lqr(A, B, Qx1, Qu1a) +K1a = np.matrix(K) # Close the loop: xdot = Ax - B K (x-xd) # Note: python-control requires we do this 1 input at a time # H1a = ss(A-B*K1a, B*K1a*concatenate((xd, yd), axis=1), C, D); -# (T, Y) = step(H1a, T=linspace(0,10,100)); +# (T, Y) = step(H1a, T=np.linspace(0,10,100)); + +# TODO: The following equations will need modifying when converting from np.matrix to np.array +# because the results and even intermediate calculations will be different with numpy arrays +# For example: +# Bx = B[lat, 0] +# Will need to be changed to: +# Bx = B[lat, 0].reshape(-1, 1) +# (if we want it to have the same shape as before) + +# For reference, here is a list of the correct shapes of these objects: +# A: (6, 6) +# B: (6, 2) +# C: (2, 6) +# D: (2, 2) +# xd: (6, 1) +# yd: (6, 1) +# Ax: (4, 4) +# Bx: (4, 1) +# Cx: (1, 4) +# Dx: () +# Ay: (2, 2) +# By: (2, 1) +# Cy: (1, 2) # Step response for the first input -H1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx); -(Yx, Tx) = step(H1ax, T=linspace(0,10,100)); +H1ax = ss(Ax - Bx*K1a[0, lat], Bx*K1a[0, lat]*xd[lat, :], Cx, Dx) +Yx, Tx = step(H1ax, T=np.linspace(0, 10, 100)) # Step response for the second input -H1ay = ss(Ay - By*K1a[1,alt], By*K1a[1,alt]*yd[alt,:], Cy, Dy); -(Yy, Ty) = step(H1ay, T=linspace(0,10,100)); +H1ay = ss(Ay - By*K1a[1, alt], By*K1a[1, alt]*yd[alt, :], Cy, Dy) +Yy, Ty = step(H1ay, T=np.linspace(0, 10, 100)) -subplot(221); title("Identity weights") -# plot(T, Y[:,1, 1], '-', T, Y[:,2, 2], '--'); -plot(Tx.T, Yx.T, '-', Ty.T, Yy.T, '--'); -plot([0, 10], [1, 1], 'k-'); +plt.subplot(221) +plt.title("Identity weights") +# plt.plot(T, Y[:,1, 1], '-', T, Y[:,2, 2], '--') +plt.plot(Tx.T, Yx.T, '-', Ty.T, Yy.T, '--') +plt.plot([0, 10], [1, 1], 'k-') -axis([0, 10, -0.1, 1.4]); -ylabel('position'); -legend(('x', 'y'), loc='lower right'); +plt.axis([0, 10, -0.1, 1.4]) +plt.ylabel('position') +plt.legend(('x', 'y'), loc='lower right') # Look at different input weightings -Qu1a = diag([1, 1]); (K1a, X, E) = lqr(A, B, Qx1, Qu1a); -H1ax = ss(Ax - Bx*K1a[0,lat], Bx*K1a[0,lat]*xd[lat,:], Cx, Dx); +Qu1a = np.diag([1, 1]) +K1a, X, E = lqr(A, B, Qx1, Qu1a) +H1ax = ss(Ax - Bx*K1a[0, lat], Bx*K1a[0, lat]*xd[lat, :], Cx, Dx) -Qu1b = (40**2)*diag([1, 1]); (K1b, X, E) = lqr(A, B, Qx1, Qu1b); -H1bx = ss(Ax - Bx*K1b[0,lat], Bx*K1b[0,lat]*xd[lat,:],Cx, Dx); +Qu1b = (40 ** 2)*np.diag([1, 1]) +K1b, X, E = lqr(A, B, Qx1, Qu1b) +H1bx = ss(Ax - Bx*K1b[0, lat], Bx*K1b[0, lat]*xd[lat, :], Cx, Dx) -Qu1c = (200**2)*diag([1, 1]); (K1c, X, E) = lqr(A, B, Qx1, Qu1c); -H1cx = ss(Ax - Bx*K1c[0,lat], Bx*K1c[0,lat]*xd[lat,:],Cx, Dx); +Qu1c = (200 ** 2)*np.diag([1, 1]) +K1c, X, E = lqr(A, B, Qx1, Qu1c) +H1cx = ss(Ax - Bx*K1c[0, lat], Bx*K1c[0, lat]*xd[lat, :], Cx, Dx) -[Y1, T1] = step(H1ax, T=linspace(0,10,100)); -[Y2, T2] = step(H1bx, T=linspace(0,10,100)); -[Y3, T3] = step(H1cx, T=linspace(0,10,100)); +[Y1, T1] = step(H1ax, T=np.linspace(0, 10, 100)) +[Y2, T2] = step(H1bx, T=np.linspace(0, 10, 100)) +[Y3, T3] = step(H1cx, T=np.linspace(0, 10, 100)) -subplot(222); title("Effect of input weights") -plot(T1.T, Y1.T, 'b-'); -plot(T2.T, Y2.T, 'b-'); -plot(T3.T, Y3.T, 'b-'); -plot([0 ,10], [1, 1], 'k-'); +plt.subplot(222) +plt.title("Effect of input weights") +plt.plot(T1.T, Y1.T, 'b-') +plt.plot(T2.T, Y2.T, 'b-') +plt.plot(T3.T, Y3.T, 'b-') +plt.plot([0, 10], [1, 1], 'k-') -axis([0, 10, -0.1, 1.4]); +plt.axis([0, 10, -0.1, 1.4]) -# arcarrow([1.3, 0.8], [5, 0.45], -6); -text(5.3, 0.4, 'rho'); +# arcarrow([1.3, 0.8], [5, 0.45], -6) +plt.text(5.3, 0.4, 'rho') # Output weighting - change Qx to use outputs -Qx2 = C.T * C; -Qu2 = 0.1 * diag([1, 1]); -(K, X, E) = lqr(A, B, Qx2, Qu2); K2 = matrix(K) +Qx2 = C.T*C +Qu2 = 0.1*np.diag([1, 1]) +K, X, E = lqr(A, B, Qx2, Qu2) +K2 = np.matrix(K) -H2x = ss(Ax - Bx*K2[0,lat], Bx*K2[0,lat]*xd[lat,:], Cx, Dx); -H2y = ss(Ay - By*K2[1,alt], By*K2[1,alt]*yd[alt,:], Cy, Dy); +H2x = ss(Ax - Bx*K2[0, lat], Bx*K2[0, lat]*xd[lat, :], Cx, Dx) +H2y = ss(Ay - By*K2[1, alt], By*K2[1, alt]*yd[alt, :], Cy, Dy) -subplot(223); title("Output weighting") -[Y2x, T2x] = step(H2x, T=linspace(0,10,100)); -[Y2y, T2y] = step(H2y, T=linspace(0,10,100)); -plot(T2x.T, Y2x.T, T2y.T, Y2y.T) -ylabel('position'); -xlabel('time'); ylabel('position'); -legend(('x', 'y'), loc='lower right'); +plt.subplot(223) +plt.title("Output weighting") +[Y2x, T2x] = step(H2x, T=np.linspace(0, 10, 100)) +[Y2y, T2y] = step(H2y, T=np.linspace(0, 10, 100)) +plt.plot(T2x.T, Y2x.T, T2y.T, Y2y.T) +plt.ylabel('position') +plt.xlabel('time') +plt.ylabel('position') +plt.legend(('x', 'y'), loc='lower right') # # Physically motivated weighting @@ -177,21 +218,21 @@ # due to loss in efficiency. # -Qx3 = diag([100, 10, 2*pi/5, 0, 0, 0]); -Qu3 = 0.1 * diag([1, 10]); -(K, X, E) = lqr(A, B, Qx3, Qu3); K3 = matrix(K); +Qx3 = np.diag([100, 10, 2*np.pi/5, 0, 0, 0]) +Qu3 = 0.1*np.diag([1, 10]) +(K, X, E) = lqr(A, B, Qx3, Qu3) +K3 = np.matrix(K) -H3x = ss(Ax - Bx*K3[0,lat], Bx*K3[0,lat]*xd[lat,:], Cx, Dx); -H3y = ss(Ay - By*K3[1,alt], By*K3[1,alt]*yd[alt,:], Cy, Dy); -subplot(224) -# step(H3x, H3y, 10); -[Y3x, T3x] = step(H3x, T=linspace(0,10,100)); -[Y3y, T3y] = step(H3y, T=linspace(0,10,100)); -plot(T3x.T, Y3x.T, T3y.T, Y3y.T) -title("Physically motivated weights") -xlabel('time'); -legend(('x', 'y'), loc='lower right'); +H3x = ss(Ax - Bx*K3[0, lat], Bx*K3[0, lat]*xd[lat, :], Cx, Dx) +H3y = ss(Ay - By*K3[1, alt], By*K3[1, alt]*yd[alt, :], Cy, Dy) +plt.subplot(224) +# step(H3x, H3y, 10) +[Y3x, T3x] = step(H3x, T=np.linspace(0, 10, 100)) +[Y3y, T3y] = step(H3y, T=np.linspace(0, 10, 100)) +plt.plot(T3x.T, Y3x.T, T3y.T, Y3y.T) +plt.title("Physically motivated weights") +plt.xlabel('time') +plt.legend(('x', 'y'), loc='lower right') if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: - show() - + plt.show() diff --git a/examples/pvtol-nested-ss.py b/examples/pvtol-nested-ss.py index 24e173bc8..55ef56e10 100644 --- a/examples/pvtol-nested-ss.py +++ b/examples/pvtol-nested-ss.py @@ -8,24 +8,25 @@ # package. # -from matplotlib.pyplot import * # Grab MATLAB plotting functions +import os +import matplotlib.pyplot as plt # MATLAB plotting functions from control.matlab import * # MATLAB-like functions import numpy as np # System parameters -m = 4; # mass of aircraft -J = 0.0475; # inertia around pitch axis -r = 0.25; # distance to center of force -g = 9.8; # gravitational constant -c = 0.05; # damping factor (estimated) +m = 4 # mass of aircraft +J = 0.0475 # inertia around pitch axis +r = 0.25 # distance to center of force +g = 9.8 # gravitational constant +c = 0.05 # damping factor (estimated) # Transfer functions for dynamics -Pi = tf([r], [J, 0, 0]); # inner loop (roll) -Po = tf([1], [m, c, 0]); # outer loop (position) +Pi = tf([r], [J, 0, 0]) # inner loop (roll) +Po = tf([1], [m, c, 0]) # outer loop (position) # Use state space versions -Pi = tf2ss(Pi); -Po = tf2ss(Po); +Pi = tf2ss(Pi) +Po = tf2ss(Po) # # Inner loop control design @@ -36,102 +37,111 @@ # # Design a simple lead controller for the system -k = 200; a = 2; b = 50; -Ci = k*tf([1, a], [1, b]); # lead compensator +k, a, b = 200, 2, 50 +Ci = k*tf([1, a], [1, b]) # lead compensator # Convert to statespace -Ci = tf2ss(Ci); +Ci = tf2ss(Ci) # Compute the loop transfer function for the inner loop -Li = Pi*Ci; +Li = Pi*Ci # Bode plot for the open loop process -figure(1); -bode(Pi); +plt.figure(1) +bode(Pi) # Bode plot for the loop transfer function, with margins -figure(2); -bode(Li); +plt.figure(2) +bode(Li) # Compute out the gain and phase margins #! Not implemented # (gm, pm, wcg, wcp) = margin(Li); # Compute the sensitivity and complementary sensitivity functions -Si = feedback(1, Li); -Ti = Li * Si; +Si = feedback(1, Li) +Ti = Li*Si # Check to make sure that the specification is met -figure(3); gangof4(Pi, Ci); +plt.figure(3) +gangof4(Pi, Ci) # Compute out the actual transfer function from u1 to v1 (see L8.2 notes) # Hi = Ci*(1-m*g*Pi)/(1+Ci*Pi); -Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1)); +Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1)) -figure(4); clf; subplot(221); -bode(Hi); +plt.figure(4) +plt.clf() +plt.subplot(221) +bode(Hi) # Now design the lateral control system -a = 0.02; b = 5; K = 2; -Co = -K*tf([1, 0.3], [1, 10]); # another lead compensator +a, b, K = 0.02, 5, 2 +Co = -K*tf([1, 0.3], [1, 10]) # another lead compensator # Convert to statespace -Co = tf2ss(Co); +Co = tf2ss(Co) # Compute the loop transfer function for the outer loop -Lo = -m*g*Po*Co; +Lo = -m*g*Po*Co -figure(5); -bode(Lo); # margin(Lo) +plt.figure(5) +bode(Lo) # margin(Lo) # Finally compute the real outer-loop loop gain + responses -L = Co*Hi*Po; -S = feedback(1, L); -T = feedback(L, 1); +L = Co*Hi*Po +S = feedback(1, L) +T = feedback(L, 1) # Compute stability margins #! Not yet implemented # (gm, pm, wgc, wpc) = margin(L); -figure(6); clf; subplot(221); -bode(L, logspace(-4, 3)); +plt.figure(6) +plt.clf() +plt.subplot(221) +bode(L, logspace(-4, 3)) # Add crossover line -subplot(211); -loglog([1e-4, 1e3], [1, 1], 'k-') - -# Replot phase starting at -90 degrees -(mag, phase, w) = freqresp(L, logspace(-4, 3)); -phase = phase - 360; - -subplot(212); -semilogx([1e-4, 1e3], [-180, -180], 'k-') -semilogx(w, np.squeeze(phase), 'b-') -axis([1e-4, 1e3, -360, 0]); -xlabel('Frequency [deg]'); ylabel('Phase [deg]'); -# set(gca, 'YTick', [-360, -270, -180, -90, 0]); -# set(gca, 'XTick', [10^-4, 10^-2, 1, 100]); +plt.subplot(211) +plt.loglog([1e-4, 1e3], [1, 1], 'k-') + +# Re-plot phase starting at -90 degrees +mag, phase, w = freqresp(L, logspace(-4, 3)) +phase = phase - 360 + +plt.subplot(212) +plt.semilogx([1e-4, 1e3], [-180, -180], 'k-') +plt.semilogx(w, np.squeeze(phase), 'b-') +plt.axis([1e-4, 1e3, -360, 0]) +plt.xlabel('Frequency [deg]') +plt.ylabel('Phase [deg]') +# plt.set(gca, 'YTick', [-360, -270, -180, -90, 0]) +# plt.set(gca, 'XTick', [10^-4, 10^-2, 1, 100]) # # Nyquist plot for complete design # -figure(7); clf; -axis([-700, 5300, -3000, 3000]); -nyquist(L, (0.0001, 1000)); -axis([-700, 5300, -3000, 3000]); +plt.figure(7) +plt.clf() +plt.axis([-700, 5300, -3000, 3000]) +nyquist(L, (0.0001, 1000)) +plt.axis([-700, 5300, -3000, 3000]) # Add a box in the region we are going to expand -plot([-400, -400, 200, 200, -400], [-100, 100, 100, -100, -100], 'r-') +plt.plot([-400, -400, 200, 200, -400], [-100, 100, 100, -100, -100], 'r-') # Expanded region -figure(8); clf; subplot(231); -axis([-10, 5, -20, 20]); -nyquist(L); -axis([-10, 5, -20, 20]); +plt.figure(8) +plt.clf() +plt.subplot(231) +plt.axis([-10, 5, -20, 20]) +nyquist(L) +plt.axis([-10, 5, -20, 20]) # set up the color -color = 'b'; +color = 'b' # Add arrows to the plot # H1 = L.evalfr(0.4); H2 = L.evalfr(0.41); @@ -142,19 +152,23 @@ # arrow([real(H2), -imag(H2)], [real(H1), -imag(H1)], AM_normal_arrowsize, \ # 'EdgeColor', color, 'FaceColor', color); -figure(9); -(Yvec, Tvec) = step(T, linspace(1, 20)); -plot(Tvec.T, Yvec.T); +plt.figure(9) +Yvec, Tvec = step(T, linspace(1, 20)) +plt.plot(Tvec.T, Yvec.T) -(Yvec, Tvec) = step(Co*S, linspace(1, 20)); -plot(Tvec.T, Yvec.T); +Yvec, Tvec = step(Co*S, linspace(1, 20)) +plt.plot(Tvec.T, Yvec.T) #TODO: PZmap for statespace systems has not yet been implemented. -figure(10); clf(); -# (P, Z) = pzmap(T, Plot=True) -# print "Closed loop poles and zeros: ", P, Z +plt.figure(10) +plt.clf() +# P, Z = pzmap(T, Plot=True) +# print("Closed loop poles and zeros: ", P, Z) # Gang of Four -figure(11); clf(); -gangof4(Hi*Po, Co, linspace(-2, 3)); +plt.figure(11) +plt.clf() +gangof4(Hi*Po, Co, linspace(-2, 3)) +if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: + plt.show() diff --git a/examples/pvtol-nested.py b/examples/pvtol-nested.py index e02d86352..56685599b 100644 --- a/examples/pvtol-nested.py +++ b/examples/pvtol-nested.py @@ -3,30 +3,32 @@ # # This file works through a fairly complicated control design and # analysis, corresponding to the planar vertical takeoff and landing -# (PVTOL) aircraft in Astrom and Mruray, Chapter 11. It is intended +# (PVTOL) aircraft in Astrom and Murray, Chapter 11. It is intended # to demonstrate the basic functionality of the python-control # package. # from __future__ import print_function -from matplotlib.pyplot import * # Grab MATLAB plotting functions + +import os +import matplotlib.pyplot as plt # MATLAB plotting functions from control.matlab import * # MATLAB-like functions import numpy as np # System parameters -m = 4; # mass of aircraft -J = 0.0475; # inertia around pitch axis -r = 0.25; # distance to center of force -g = 9.8; # gravitational constant -c = 0.05; # damping factor (estimated) +m = 4 # mass of aircraft +J = 0.0475 # inertia around pitch axis +r = 0.25 # distance to center of force +g = 9.8 # gravitational constant +c = 0.05 # damping factor (estimated) # Transfer functions for dynamics -Pi = tf([r], [J, 0, 0]); # inner loop (roll) -Po = tf([1], [m, c, 0]); # outer loop (position) +Pi = tf([r], [J, 0, 0]) # inner loop (roll) +Po = tf([1], [m, c, 0]) # outer loop (position) # Use state space versions -Pi = tf2ss(Pi); -Po = tf2ss(Po); +Pi = tf2ss(Pi) +Po = tf2ss(Po) # # Inner loop control design @@ -37,110 +39,118 @@ # # Design a simple lead controller for the system -k = 200; a = 2; b = 50; -Ci = k*tf([1, a], [1, b]); # lead compensator -Li = Pi*Ci; +k, a, b = 200, 2, 50 +Ci = k*tf([1, a], [1, b]) # lead compensator +Li = Pi*Ci # Bode plot for the open loop process -figure(1); -bode(Pi); +plt.figure(1) +bode(Pi) # Bode plot for the loop transfer function, with margins -figure(2); -bode(Li); +plt.figure(2) +bode(Li) # Compute out the gain and phase margins #! Not implemented -# (gm, pm, wcg, wcp) = margin(Li); +# gm, pm, wcg, wcp = margin(Li) # Compute the sensitivity and complementary sensitivity functions -Si = feedback(1, Li); -Ti = Li * Si; +Si = feedback(1, Li) +Ti = Li*Si # Check to make sure that the specification is met -figure(3); gangof4(Pi, Ci); +plt.figure(3) +gangof4(Pi, Ci) # Compute out the actual transfer function from u1 to v1 (see L8.2 notes) -# Hi = Ci*(1-m*g*Pi)/(1+Ci*Pi); -Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1)); +# Hi = Ci*(1-m*g*Pi)/(1+Ci*Pi) +Hi = parallel(feedback(Ci, Pi), -m*g*feedback(Ci*Pi, 1)) -figure(4); clf; subplot(221); -bode(Hi); +plt.figure(4) +plt.clf() +plt.subplot(221) +bode(Hi) # Now design the lateral control system -a = 0.02; b = 5; K = 2; -Co = -K*tf([1, 0.3], [1, 10]); # another lead compensator -Lo = -m*g*Po*Co; +a, b, K = 0.02, 5, 2 +Co = -K*tf([1, 0.3], [1, 10]) # another lead compensator +Lo = -m*g*Po*Co -figure(5); -bode(Lo); # margin(Lo) +plt.figure(5) +bode(Lo) # margin(Lo) # Finally compute the real outer-loop loop gain + responses -L = Co*Hi*Po; -S = feedback(1, L); -T = feedback(L, 1); +L = Co*Hi*Po +S = feedback(1, L) +T = feedback(L, 1) # Compute stability margins -(gm, pm, wgc, wpc) = margin(L); +gm, pm, wgc, wpc = margin(L) print("Gain margin: %g at %g" % (gm, wgc)) print("Phase margin: %g at %g" % (pm, wpc)) -figure(6); clf; -bode(L, logspace(-4, 3)); +plt.figure(6) +plt.clf() +bode(L, np.logspace(-4, 3)) # Add crossover line to the magnitude plot # # Note: in matplotlib before v2.1, the following code worked: # -# subplot(211); hold(True); +# plt.subplot(211); hold(True); # loglog([1e-4, 1e3], [1, 1], 'k-') # -# In later versions of matplotlib the call to subplot will clear the +# In later versions of matplotlib the call to plt.subplot will clear the # axes and so we have to extract the axes that we want to use by hand. # In addition, hold() is deprecated so we no longer require it. # -for ax in gcf().axes: +for ax in plt.gcf().axes: if ax.get_label() == 'control-bode-magnitude': break -ax.semilogx([1e-4, 1e3], 20 * np.log10([1, 1]), 'k-') +ax.semilogx([1e-4, 1e3], 20*np.log10([1, 1]), 'k-') # # Replot phase starting at -90 degrees # # Get the phase plot axes -for ax in gcf().axes: +for ax in plt.gcf().axes: if ax.get_label() == 'control-bode-phase': break # Recreate the frequency response and shift the phase -(mag, phase, w) = freqresp(L, logspace(-4, 3)); -phase = phase - 360; +mag, phase, w = freqresp(L, np.logspace(-4, 3)) +phase = phase - 360 # Replot the phase by hand ax.semilogx([1e-4, 1e3], [-180, -180], 'k-') ax.semilogx(w, np.squeeze(phase), 'b-') -ax.axis([1e-4, 1e3, -360, 0]); -xlabel('Frequency [deg]'); ylabel('Phase [deg]'); -# set(gca, 'YTick', [-360, -270, -180, -90, 0]); -# set(gca, 'XTick', [10^-4, 10^-2, 1, 100]); +ax.axis([1e-4, 1e3, -360, 0]) +plt.xlabel('Frequency [deg]') +plt.ylabel('Phase [deg]') +# plt.set(gca, 'YTick', [-360, -270, -180, -90, 0]) +# plt.set(gca, 'XTick', [10^-4, 10^-2, 1, 100]) # # Nyquist plot for complete design # -figure(7); clf; -nyquist(L, (0.0001, 1000)); -axis([-700, 5300, -3000, 3000]); +plt.figure(7) +plt.clf() +nyquist(L, (0.0001, 1000)) +plt.axis([-700, 5300, -3000, 3000]) # Add a box in the region we are going to expand -plot([-400, -400, 200, 200, -400], [-100, 100, 100, -100, -100], 'r-') +plt.plot([-400, -400, 200, 200, -400], [-100, 100, 100, -100, -100], 'r-') # Expanded region -figure(8); clf; subplot(231); -nyquist(L); -axis([-10, 5, -20, 20]); +plt.figure(8) +plt.clf() +plt.subplot(231) +nyquist(L) +plt.axis([-10, 5, -20, 20]) # set up the color -color = 'b'; +color = 'b' # Add arrows to the plot # H1 = L.evalfr(0.4); H2 = L.evalfr(0.41); @@ -151,18 +161,22 @@ # arrow([real(H2), -imag(H2)], [real(H1), -imag(H1)], AM_normal_arrowsize, \ # 'EdgeColor', color, 'FaceColor', color); -figure(9); -(Yvec, Tvec) = step(T, linspace(0, 20)); -plot(Tvec.T, Yvec.T); +plt.figure(9) +Yvec, Tvec = step(T, np.linspace(0, 20)) +plt.plot(Tvec.T, Yvec.T) -(Yvec, Tvec) = step(Co*S, linspace(0, 20)); -plot(Tvec.T, Yvec.T); +Yvec, Tvec = step(Co*S, np.linspace(0, 20)) +plt.plot(Tvec.T, Yvec.T) -figure(10); clf(); -(P, Z) = pzmap(T, Plot=True) +plt.figure(10) +plt.clf() +P, Z = pzmap(T, Plot=True) print("Closed loop poles and zeros: ", P, Z) # Gang of Four -figure(11); clf(); -gangof4(Hi*Po, Co); +plt.figure(11) +plt.clf() +gangof4(Hi*Po, Co) +if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: + plt.show() diff --git a/examples/robust_mimo.py b/examples/robust_mimo.py index c7a06ea1c..402d91488 100644 --- a/examples/robust_mimo.py +++ b/examples/robust_mimo.py @@ -10,7 +10,7 @@ import numpy as np import matplotlib.pyplot as plt -from control import tf, ss, mixsyn, feedback, step_response +from control import tf, ss, mixsyn, step_response def weighting(wb, m, a): @@ -21,7 +21,7 @@ def weighting(wb, m, a): wf - SISO LTI object """ s = tf([1, 0], [1]) - return (s / m + wb) / (s + wb * a) + return (s/m + wb) / (s + wb*a) def plant(): @@ -44,7 +44,7 @@ def triv_sigma(g, w): w - frequencies, length m s - (m,n) array of singular values of g(1j*w)""" m, p, _ = g.freqresp(w) - sjw = (m * np.exp(1j * p * np.pi / 180)).transpose(2, 0, 1) + sjw = (m*np.exp(1j*p*np.pi/180)).transpose(2, 0, 1) sv = np.linalg.svd(sjw, compute_uv=False) return sv @@ -135,8 +135,8 @@ def design(): g = plant() w = np.logspace(-2, 2, 101) I = ss([], [], [], np.eye(2)) - s1 = I.feedback(g * k1) - s2 = I.feedback(g * k2) + s1 = I.feedback(g*k1) + s2 = I.feedback(g*k2) # frequency response sv1 = triv_sigma(s1, w) @@ -145,10 +145,10 @@ def design(): plt.figure(2) plt.subplot(1, 2, 1) - plt.semilogx(w, 20 * np.log10(sv1[:, 0]), label=r'$\sigma_1(S_1)$') - plt.semilogx(w, 20 * np.log10(sv1[:, 1]), label=r'$\sigma_2(S_1)$') - plt.semilogx(w, 20 * np.log10(sv2[:, 0]), label=r'$\sigma_1(S_2)$') - plt.semilogx(w, 20 * np.log10(sv2[:, 1]), label=r'$\sigma_2(S_2)$') + plt.semilogx(w, 20*np.log10(sv1[:, 0]), label=r'$\sigma_1(S_1)$') + plt.semilogx(w, 20*np.log10(sv1[:, 1]), label=r'$\sigma_2(S_1)$') + plt.semilogx(w, 20*np.log10(sv2[:, 0]), label=r'$\sigma_1(S_2)$') + plt.semilogx(w, 20*np.log10(sv2[:, 1]), label=r'$\sigma_2(S_2)$') plt.ylim([-60, 10]) plt.ylabel('magnitude [dB]') plt.xlim([1e-2, 1e2]) @@ -162,8 +162,8 @@ def design(): # design 2, output 2 does not, and is very fast, while output 1 # has a larger initial inverse response than in design 1 time = np.linspace(0, 10, 301) - t1 = (g * k1).feedback(I) - t2 = (g * k2).feedback(I) + t1 = (g*k1).feedback(I) + t2 = (g*k2).feedback(I) y1 = step_opposite(t1, time) y2 = step_opposite(t2, time) diff --git a/examples/robust_siso.py b/examples/robust_siso.py index 013ea821d..87fcdb707 100644 --- a/examples/robust_siso.py +++ b/examples/robust_siso.py @@ -11,20 +11,20 @@ import numpy as np import matplotlib.pyplot as plt -from control import tf, ss, mixsyn, feedback, step_response +from control import tf, mixsyn, feedback, step_response s = tf([1, 0], 1) # the plant -g = 200 / (10 * s + 1) / (0.05 * s + 1) ** 2 +g = 200/(10*s + 1) / (0.05*s + 1)**2 # disturbance plant -gd = 100 / (10 * s + 1) +gd = 100/(10*s + 1) # first design # sensitivity weighting M = 1.5 wb = 10 A = 1e-4 -ws1 = (s / M + wb) / (s + wb * A) +ws1 = (s/M + wb) / (s + wb*A) # KS weighting wu = tf(1, 1) @@ -32,21 +32,21 @@ # sensitivity (S) and complementary sensitivity (T) functions for # design 1 -s1 = feedback(1, g * k1) -t1 = feedback(g * k1, 1) +s1 = feedback(1, g*k1) +t1 = feedback(g*k1, 1) # second design # this weighting differs from the text, where A**0.5 is used; if you use that, # the frequency response doesn't match the figure. The time responses # are similar, though. -ws2 = (s / M ** 0.5 + wb) ** 2 / (s + wb * A) ** 2 +ws2 = (s/M ** 0.5 + wb)**2 / (s + wb*A)**2 # the KS weighting is the same as for the first design k2, cl2, info2 = mixsyn(g, ws2, wu) # S and T for design 2 -s2 = feedback(1, g * k2) -t2 = feedback(g * k2, 1) +s2 = feedback(1, g*k2) +t2 = feedback(g*k2, 1) # frequency response omega = np.logspace(-2, 2, 101) @@ -57,11 +57,11 @@ plt.figure(1) # text uses log-scaled absolute, but dB are probably more familiar to most control engineers -plt.semilogx(omega, 20 * np.log10(s1mag.flat), label='$S_1$') -plt.semilogx(omega, 20 * np.log10(s2mag.flat), label='$S_2$') +plt.semilogx(omega, 20*np.log10(s1mag.flat), label='$S_1$') +plt.semilogx(omega, 20*np.log10(s2mag.flat), label='$S_2$') # -1 in logspace is inverse -plt.semilogx(omega, -20 * np.log10(ws1mag.flat), label='$1/w_{P1}$') -plt.semilogx(omega, -20 * np.log10(ws2mag.flat), label='$1/w_{P2}$') +plt.semilogx(omega, -20*np.log10(ws1mag.flat), label='$1/w_{P1}$') +plt.semilogx(omega, -20*np.log10(ws2mag.flat), label='$1/w_{P2}$') plt.ylim([-80, 10]) plt.xlim([1e-2, 1e2]) @@ -77,8 +77,8 @@ # gd injects into the output (that is, g and gd are summed), and the # closed loop mapping from output disturbance->output is S. -_, y1d = step_response(s1 * gd, time) -_, y2d = step_response(s2 * gd, time) +_, y1d = step_response(s1*gd, time) +_, y2d = step_response(s2*gd, time) plt.figure(2) plt.subplot(1, 2, 1) diff --git a/examples/rss-balred.py b/examples/rss-balred.py index 86e499a80..f6bc58fd7 100755 --- a/examples/rss-balred.py +++ b/examples/rss-balred.py @@ -10,21 +10,29 @@ plt.close('all') -#controlable canonical realization computed in matlab for the transfer function: +# controllable canonical realization computed in Matlab for the transfer function: # num = [1 11 45 32], den = [1 15 60 200 60] -A = np.matrix('-15., -7.5, -6.25, -1.875; \ -8., 0., 0., 0.; \ -0., 4., 0., 0.; \ -0., 0., 1., 0.') -B = np.matrix('2.; 0.; 0.; 0.') -C = np.matrix('0.5, 0.6875, 0.7031, 0.5') -D = np.matrix('0.') +A = np.array([ + [-15., -7.5, -6.25, -1.875], + [8., 0., 0., 0.], + [0., 4., 0., 0.], + [0., 0., 1., 0.] +]) +B = np.array([ + [2.], + [0.], + [0.], + [0.] +]) +C = np.array([[0.5, 0.6875, 0.7031, 0.5]]) +D = np.array([[0.]]) # The full system -fsys = StateSpace(A,B,C,D) +fsys = StateSpace(A, B, C, D) + # The reduced system, truncating the order by 1 -ord = 3 -rsys = msimp.balred(fsys,ord, method = 'truncate') +n = 3 +rsys = msimp.balred(fsys, n, method='truncate') # Comparison of the step responses of the full and reduced systems plt.figure(1) @@ -35,14 +43,13 @@ # Repeat balanced reduction, now with 100-dimensional random state space sysrand = mt.rss(100, 1, 1) -rsysrand = msimp.balred(sysrand,10,method ='truncate') +rsysrand = msimp.balred(sysrand, 10, method='truncate') # Comparison of the impulse responses of the full and reduced random systems plt.figure(2) yrand, trand = mt.impulse(sysrand) yrandr, trandr = mt.impulse(rsysrand) -plt.plot(trand.T, yrand.T, trandr.T, yrandr.T) - +plt.plot(trand.T, yrand.T, trandr.T, yrandr.T) if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: plt.show() diff --git a/examples/secord-matlab.py b/examples/secord-matlab.py index c3cf08277..25bf1ff79 100644 --- a/examples/secord-matlab.py +++ b/examples/secord-matlab.py @@ -1,33 +1,39 @@ -# secord.py - demonstrate some standard MATLAB commands +# secord.py - demonstrate some standard MATLAB commands # RMM, 25 May 09 -from matplotlib.pyplot import * # Grab MATLAB plotting functions -from control.matlab import * # MATLAB-like functions +import os +import matplotlib.pyplot as plt # MATLAB plotting functions +from control.matlab import * # MATLAB-like functions # Parameters defining the system -m = 250.0 # system mass -k = 40.0 # spring constant -b = 60.0 # damping constant +m = 250.0 # system mass +k = 40.0 # spring constant +b = 60.0 # damping constant # System matrices A = [[0, 1.], [-k/m, -b/m]] B = [[0], [1/m]] C = [[1., 0]] -sys = ss(A, B, C, 0); +sys = ss(A, B, C, 0) # Step response for the system -figure(1) +plt.figure(1) yout, T = step(sys) -plot(T.T, yout.T) +plt.plot(T.T, yout.T) +plt.show(block=False) # Bode plot for the system -figure(2) -mag,phase,om = bode(sys, logspace(-2, 2),Plot=True) +plt.figure(2) +mag, phase, om = bode(sys, logspace(-2, 2), Plot=True) +plt.show(block=False) # Nyquist plot for the system -figure(3) +plt.figure(3) nyquist(sys, logspace(-2, 2)) +plt.show(block=False) -# Root lcous plut for the system -figure(4) +# Root lcous plot for the system rlocus(sys) + +if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: + plt.show() diff --git a/examples/slycot-import-test.py b/examples/slycot-import-test.py index 7e4f0d9a9..c2c78fa89 100644 --- a/examples/slycot-import-test.py +++ b/examples/slycot-import-test.py @@ -5,19 +5,18 @@ """ import numpy as np -from scipy import * from control.matlab import * from control.exception import slycot_check # Parameters defining the system m = 250.0 # system mass -k = 40.0 # spring constant -b = 60.0 # damping constant +k = 40.0 # spring constant +b = 60.0 # damping constant # System matrices -A = np.matrix([[1, -1, 1.], [1, -k / m, -b / m], [1, 1, 1]]) -B = np.matrix([[0], [1 / m], [1]]) -C = np.matrix([[1., 0, 1.]]) +A = np.array([[1, -1, 1.], [1, -k/m, -b/m], [1, 1, 1]]) +B = np.array([[0], [1/m], [1]]) +C = np.array([[1., 0, 1.]]) sys = ss(A, B, C, 0) # Python control may be used without slycot, for example for a pole placement. @@ -25,7 +24,7 @@ w = [-3, -2, -1] K = place(A, B, w) print("[python-control (from scipy)] K = ", K) -print("[python-control (from scipy)] eigs = ", np.linalg.eig(A - B * K)[0]) +print("[python-control (from scipy)] eigs = ", np.linalg.eig(A - B*K)[0]) # Before using one of its routine, check that slycot is installed. w = np.array([-3, -2, -1]) @@ -33,11 +32,11 @@ # Import routine sb01bd used for pole placement. from slycot import sb01bd - n = 3 # Number of states - m = 1 # Number of inputs - npp = 3 # Number of placed eigen values - alpha = 1 # Maximum threshold for eigen values - dico = 'D' # Discrete system + n = 3 # Number of states + m = 1 # Number of inputs + npp = 3 # Number of placed eigen values + alpha = 1 # Maximum threshold for eigen values + dico = 'D' # Discrete system _, _, _, _, _, K, _ = sb01bd(n, m, npp, alpha, A, B, w, dico, tol=0.0, ldwork=None) print("[slycot] K = ", K) print("[slycot] eigs = ", np.linalg.eig(A + np.dot(B, K))[0]) diff --git a/examples/test-response.py b/examples/test-response.py index 745a14fb6..0ccc70b6c 100644 --- a/examples/test-response.py +++ b/examples/test-response.py @@ -1,7 +1,8 @@ # test-response.py - Unit tests for system response functions # RMM, 11 Sep 2010 -from matplotlib.pyplot import * # Grab MATLAB plotting functions +import os +import matplotlib.pyplot as plt # MATLAB plotting functions from control.matlab import * # Load the controls systems library from scipy import arange # function to create range of numbers @@ -11,8 +12,11 @@ # Generate step responses (y1a, T1a) = step(sys1) -(y1b, T1b) = step(sys1, T = arange(0, 10, 0.1)) -(y1c, T1c) = step(sys1, X0 = [1, 0]) -(y2a, T2a) = step(sys2, T = arange(0, 10, 0.1)) +(y1b, T1b) = step(sys1, T=arange(0, 10, 0.1)) +(y1c, T1c) = step(sys1, X0=[1, 0]) +(y2a, T2a) = step(sys2, T=arange(0, 10, 0.1)) -plot(T1a, y1a, T1b, y1b, T1c, y1c, T2a, y2a) +plt.plot(T1a, y1a, T1b, y1b, T1c, y1c, T2a, y2a) + +if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: + plt.show() \ No newline at end of file diff --git a/examples/tfvis.py b/examples/tfvis.py index 056fd62eb..60b837d99 100644 --- a/examples/tfvis.py +++ b/examples/tfvis.py @@ -56,6 +56,7 @@ from control.matlab import logspace from numpy import conj + def make_poly(facts): """ Create polynomial from factors """ poly = [1] @@ -63,7 +64,8 @@ def make_poly(facts): poly = polymul(poly, [1, -factor]) return real(poly) - + + def coeff_string_check(text): """ Check so textfield entry is valid string of coeffs. """ try: @@ -73,6 +75,7 @@ def coeff_string_check(text): return Pmw.OK + class TFInput: """ Class for handling input of transfer function coeffs.""" def __init__(self, parent): @@ -150,6 +153,7 @@ def set_zeros(self, zeros): self.numerator_widget.setentry( ' '.join([format(i,'.3g') for i in self.numerator])) + class Analysis: """ Main class for GUI visualising transfer functions """ def __init__(self, parent): @@ -179,7 +183,7 @@ def __init__(self, parent): self.sys = self.tfi.get_tf() tkinter.Button(self.entries, text='Apply', command=self.apply, - width=9).grid(row=0, column=1, rowspan=3, padx=10, pady=5) + width=9).grid(row=0, column=1, rowspan=3, padx=10, pady=5) self.f_bode = plt.figure(figsize=(4, 4)) self.f_nyquist = plt.figure(figsize=(4, 4)) @@ -187,35 +191,35 @@ def __init__(self, parent): self.f_step = plt.figure(figsize=(4, 4)) self.canvas_pzmap = FigureCanvasTkAgg(self.f_pzmap, - master=self.figure) + master=self.figure) self.canvas_pzmap.draw() self.canvas_pzmap.get_tk_widget().grid(row=0, column=0, - padx=0, pady=0) + padx=0, pady=0) self.canvas_bode = FigureCanvasTkAgg(self.f_bode, - master=self.figure) + master=self.figure) self.canvas_bode.draw() self.canvas_bode.get_tk_widget().grid(row=0, column=1, - padx=0, pady=0) + padx=0, pady=0) self.canvas_step = FigureCanvasTkAgg(self.f_step, - master=self.figure) + master=self.figure) self.canvas_step.draw() self.canvas_step.get_tk_widget().grid(row=1, column=0, - padx=0, pady=0) + padx=0, pady=0) self.canvas_nyquist = FigureCanvasTkAgg(self.f_nyquist, master=self.figure) self.canvas_nyquist.draw() self.canvas_nyquist.get_tk_widget().grid(row=1, column=1, - padx=0, pady=0) + padx=0, pady=0) self.canvas_pzmap.mpl_connect('button_press_event', - self.button_press) + self.button_press) self.canvas_pzmap.mpl_connect('button_release_event', - self.button_release) + self.button_release) self.canvas_pzmap.mpl_connect('motion_notify_event', - self.mouse_move) + self.mouse_move) self.apply() @@ -223,7 +227,7 @@ def button_press(self, event): """ Handle button presses, detect if we are going to move any poles/zeros""" # find closest pole/zero - if (event.xdata != None and event.ydata != None): + if event.xdata != None and event.ydata != None: new = event.xdata + 1.0j*event.ydata @@ -361,6 +365,7 @@ def redraw(self): self.canvas_step.draw() self.canvas_nyquist.draw() + def create_analysis(): """ Create main object """ def handler(): @@ -376,6 +381,7 @@ def handler(): Analysis(root) root.mainloop() + if __name__ == '__main__': import os if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: diff --git a/examples/type2_type3.py b/examples/type2_type3.py index 951e5df54..250aa266c 100644 --- a/examples/type2_type3.py +++ b/examples/type2_type3.py @@ -2,10 +2,11 @@ # tracking and disturbance rejection for two proposed controllers # Gunnar Ristroph, 15 January 2010 -from matplotlib.pyplot import * # Grab MATLAB plotting functions -from control.matlab import * # MATLAB-like functions +import os +import matplotlib.pyplot as plt # Grab MATLAB plotting functions +from control.matlab import * # MATLAB-like functions from scipy import pi -integrator = tf( [0, 1], [1, 0] ) # 1/s +integrator = tf([0, 1], [1, 0]) # 1/s # Parameters defining the system J = 1.0 @@ -16,8 +17,8 @@ # Plant transfer function from torque to rate inertia = integrator*1/J -friction = b # transfer function from rate to torque -P = inertia # friction is modelled as a separate block +friction = b # transfer function from rate to torque +P = inertia # friction is modelled as a separate block # Gyro transfer function from rate to rate gyro = 1. # for now, our gyro is perfect @@ -28,16 +29,20 @@ # System Transfer Functions # tricky because the disturbance (base motion) is coupled in by friction -closed_loop_type2 = feedback(C_type2*feedback(P,friction),gyro) -disturbance_rejection_type2 = P*friction/(1.+P*friction+P*C_type2) -closed_loop_type3 = feedback(C_type3*feedback(P,friction),gyro) -disturbance_rejection_type3 = P*friction/(1.+P*friction+P*C_type3) +closed_loop_type2 = feedback(C_type2*feedback(P, friction), gyro) +disturbance_rejection_type2 = P*friction/(1. + P*friction+P*C_type2) +closed_loop_type3 = feedback(C_type3*feedback(P, friction), gyro) +disturbance_rejection_type3 = P*friction/(1. + P*friction + P*C_type3) # Bode plot for the system -figure(1) -bode(closed_loop_type2, logspace(0,2)*2*pi, dB=True, Hz=True) # blue -bode(closed_loop_type3, logspace(0,2)*2*pi, dB=True, Hz=True) # green +plt.figure(1) +bode(closed_loop_type2, logspace(0, 2)*2*pi, dB=True, Hz=True) # blue +bode(closed_loop_type3, logspace(0, 2)*2*pi, dB=True, Hz=True) # green +plt.show(block=False) -figure(2) -bode(disturbance_rejection_type2, logspace(0,2)*2*pi, Hz=True) # blue -bode(disturbance_rejection_type3, logspace(0,2)*2*pi, Hz=True) # green +plt.figure(2) +bode(disturbance_rejection_type2, logspace(0, 2)*2*pi, Hz=True) # blue +bode(disturbance_rejection_type3, logspace(0, 2)*2*pi, Hz=True) # green + +if 'PYCONTROL_TEST_EXAMPLES' not in os.environ: + plt.show()