{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Chapter 7" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "using ControlSystems\n", "using Plots; gr()\n", "using LinearAlgebra" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## オブザーバ" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "StateSpace{Continuous, Int64}\n", "A = \n", " 0 1\n", " -4 5\n", "B = \n", " 0\n", " 1\n", "C = \n", " 1 0\n", "D = \n", " 0\n", "\n", "Continuous-time state-space model\n", "StateSpace{Continuous, Int64}\n", "A = \n", " 0 1\n", " -4 5\n", "B = \n", " 0\n", " 1\n", "C = \n", " 1 0\n", " 0 1\n", "D = \n", " 0\n", " 0\n", "\n", "Continuous-time state-space model\n" ] } ], "source": [ "A = [0 1; -4 5]\n", "B = [0; 1]\n", "C = [1 0]\n", "D = 0\n", "P = ss(A, B, C, D)\n", "println(P)\n", "\n", "A = [0 1; -4 5]\n", "B = [0; 1]\n", "C = [1 0; 0 1]\n", "D = [0; 0]\n", "Ps = ss(A, B, C, D)\n", "println(Ps)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### オブザーバゲインの設計(極配置)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ComplexF64[-35.0 + 0.0im; -421.0 + 0.0im;;]\n" ] } ], "source": [ "# オブザーバ極\n", "observer_poles=[-15+5im,-15-5im]\n", "\n", "# オブザーバゲインの設計(状態フィードバックの双対) \n", "L = -place(P.A', P.C', observer_poles)'\n", "println(L)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{Float64}:\n", " -35.0\n", " -421.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = [ convert(Float64, L[i]) for i in 1:length(L) ]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{ComplexF64}:\n", " -15.000000000000002 - 4.9999999999999964im\n", " -15.000000000000002 + 4.9999999999999964im" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eigvals(P.A + L * P.C)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ComplexF64[-46.0 - 0.0im -15.0 - 0.0im]\n" ] } ], "source": [ "# レギュレータ極\n", "regulator_poles = [-5+5im, -5-5im]\n", "# 極配置\n", "F = -place(P.A, P.B, regulator_poles)\n", "println(F)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1×2 adjoint(::Vector{Float64}) with eltype Float64:\n", " -46.0 -15.0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F = [ convert(Float64, F[i]) for i in 1:length(F) ]'" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "Gsf = ss(P.A + P.B*F, P.B, [1 0; 0 1], [0; 0]);\n", "Obs = ss(P.A + L*P.C, [P.B -L], [1 0; 0 1], [0 0; 0 0]);" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Td = 0:0.01:3;\n", "X0 = [-1, 0.5];\n", "u(x,t) = 0;\n", "y, t, x, uout = lsim(Gsf, u, Td, x0=X0);\n", "\n", "Ud = F*x;\n", "y, t, xhat, uout = lsim(Obs, [Ud' y[1,:]]', Td, [0, 0]);\n", "\n", "p = [ plot(), plot()]\n", "\n", "for i=1:2\n", "plot!(p[i], t, x[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "plot!(p[i], t, xhat[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x̂\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "end\n", "\n", "plot( p[1], p[2], layout=(1,2), size=(600,230) )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 出力フィードバック" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "K:\n", "StateSpace{Continuous, Float64}\n", "A = \n", " -35.0 1.0\n", " -471.0 -10.0\n", "B = \n", " 35.0\n", " 421.0\n", "C = \n", " -46.0 -15.0\n", "D = \n", " 0.0\n", "\n", "Continuous-time state-space model\n", "----------------\n", "K(s)=\n", "TransferFunction{Continuous, ControlSystems.SisoRational{Float64}}\n", "-7925.000000000001s - 9215.999999997051\n", "---------------------------------------\n", " 1.0s^2 + 45.0s + 821.0\n", "\n", "Continuous-time transfer function model\n" ] } ], "source": [ "# 出力フィードバック(オブザーバ+状態フィードバック)\n", "K = ss(P.A+P.B*F+L*P.C, -L, F, 0)\n", "println(\"K:\\n\", K)\n", "println(\"----------------\")\n", "println(\"K(s)=\\n\", tf(K))\n", " \n", "# フィードバック系\n", "Gfb = feedback(P, K);" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# Td = 0:0.01:3;\n", "\n", "# u(x,t) = 0;\n", "# y, t, x, uout = lsim(Gfb, Td, u, [-1, 0.5, 0, 0])\n", "\n", "# plot(t, x',\n", "# xlabel=\"t\", #X軸のラベル\n", "# ylabel=\"x\", #Y軸のラベル\n", "# lw=2, #線幅\n", "# ls=:solid, #線種\n", "# legend=false,\n", "# size=(300,230) #プロットのサイズ \n", "# )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 外乱オブザーバ" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "using ControlSystems\n", "using Plots; gr()\n", "using LinearAlgebra" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "StateSpace{Continuous, Int64}\n", "A = \n", " 0 1\n", " -4 5\n", "B = \n", " 0\n", " 1\n", "C = \n", " 1 0\n", "D = \n", " 0\n", "\n", "Continuous-time state-space model\n", "StateSpace{Continuous, Int64}\n", "A = \n", " 0 1\n", " -4 5\n", "B = \n", " 0\n", " 1\n", "C = \n", " 1 0\n", " 0 1\n", "D = \n", " 0\n", " 0\n", "\n", "Continuous-time state-space model\n" ] } ], "source": [ "A = [0 1; -4 5]\n", "B = [0; 1]\n", "C = [1 0]\n", "D = 0\n", "P = ss(A, B, C, D)\n", "println(P)\n", "\n", "A = [0 1; -4 5]\n", "B = [0; 1]\n", "C = [1 0; 0 1]\n", "D = [0; 0]\n", "Ps = ss(A, B, C, D)\n", "println(Ps)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "出力に0.5の定値外乱が加わるとする" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# オブザーバ極\n", "observer_poles=[-15+5im,-15-5im]\n", "# オブザーバゲインの設計(状態フィードバックの双対) \n", "L = -place(P.A', P.C', observer_poles)'\n", "L = [ convert(Float64, L[i]) for i in 1:length(L) ]\n", "\n", "# レギュレータ極\n", "regulator_poles = [-5+5im, -5-5im]\n", "# 極配置\n", "F = -place(P.A, P.B, regulator_poles)\n", "F = [ convert(Float64, F[i]) for i in 1:length(F) ]'\n", "\n", "\n", "Gsf = ss(P.A + P.B*F, P.B, [1 0; 0 1], [0; 0]);\n", "Obs = ss(P.A + L*P.C, [P.B -L], [1 0; 0 1], [0 0; 0 0]);" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Td = 0:0.01:3;\n", "d = 0.5\n", "X0 = [-1, 0.5];\n", "u(x,t) = 0;\n", "y, t, x, uout = lsim(Gsf, u, Td, x0=X0);\n", "\n", "Ud = F*x;\n", "y, t, xhat, uout = lsim(Obs, [Ud' y[1,:].+d]', Td, [0, 0]);\n", "\n", "p = [ plot(), plot()]\n", "\n", "for i=1:2\n", "plot!(p[i], t, x[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "plot!(p[i], t, xhat[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x̂\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "end\n", "\n", "plot( p[1], p[2], layout=(1,2), size=(600,230) )" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[149.5, -526.0, -187.5]\n" ] } ], "source": [ "# オブザーバ極\n", "observer_poles=[-15+5im,-15-5im, -3] \n", "\n", "# オブザーバゲインの設計(状態フィードバックの双対)\n", "Abar = [ P.A zeros(2,1) ; 0 0 0 ] \n", "Bbar = [ P.B; 0 ]\n", "Cbar = [ P.C 1 ]\n", "\n", "Lbar = -place(Abar', Cbar', observer_poles)'\n", "Lbar = [ convert(Float64, Lbar[i]) for i in 1:length(Lbar) ]\n", "\n", "println(Lbar)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "Fbar = [ F 0 ]\n", "\n", "Aob = Abar + Lbar*Cbar\n", "Bob = [Bbar -Lbar]\n", "Obs = ss(Aob, Bob, [1 0 0; 0 1 0; 0 0 1], [0 0; 0 0; 0 0] );" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3-element Vector{ComplexF64}:\n", " -15.000000000000306 + 4.999999999999643im\n", " -15.000000000000306 - 4.999999999999643im\n", " -2.9999999999994746 + 0.0im" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pole(Obs)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Td = 0:0.01:3;\n", "d = 0.5\n", "X0 = [-1, 0.5];\n", "u(x,t) = 0;\n", "y, t, x, uout = lsim(Gsf, u, Td, x0=X0);\n", "\n", "Ud = F*x;\n", "y, t, xhat, uout = lsim(Obs, [Ud' y[1,:].+d]', Td, [0, 0, 0]);\n", "\n", "p = [ plot(), plot()]\n", "\n", "for i=1:2\n", "plot!(p[i], t, x[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "plot!(p[i], t, xhat[i,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"x\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"x̂\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "end\n", "\n", "plot( p[1], p[2], layout=(1,2), size=(600,230) )" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot(t, xhat[3,:],\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"d̂\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " legend=false,\n", " size=(300,230) #プロットのサイズ \n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "外乱 0.5 が推定できている" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ロバスト制御" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "using ControlSystems\n", "using Plots; gr()\n", "using LinearAlgebra" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = 9.81 # 重力加速度[m/s^2]\n", "l = 0.2 # アームの長さ[m]\n", "M = 0.5 # アームの質量[kg]\n", "mu = 1.5e-2 # 粘性摩擦係数\n", "J = 1.0e-2 # 慣性モーメント\n", "\n", "P = tf( [0,1], [J, mu, M*g*l] )\n", "\n", "ref = 30 # 目標角度 [deg]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 乗法的不確かさ" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 垂直駆動アームのノミナルモデル\n", "Pn = tf( [0,1], [J, mu, M*g*l] )\n", "\n", "# 不確かさ\n", "delta = LinRange(-1, 1, 100)\n", "WT = tf( [10, 0], [1, 150])\n", "\n", "P = TransferFunction[ (1 + WT*delta[i])*Pn for i in 1:length(delta) ];\n", "DT = TransferFunction[ WT*delta[i] for i in 1:length(delta) ];\n", "\n", "setPlotScale(\"dB\")\n", "w = exp10.(LinRange(-2, 3, 1000))\n", "bodeplot(P, w; lc=:black, lw=0.5, size=(450,400), legend=false, title=\"\" )" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bodeplot(DT, w; lc=:black, lw=0.5, size=(450,400), legend=false, title=\"\" )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 混合感度問題" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "確認中" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# from control import mixsyn\n", "\n", "# WS = tf( [0, 1], [1, 1, 0.25]) # 感度関数に対する重み関数 \n", "# WU = tf(1, 1)\n", "# WT = tf( [10, 0], [1, 150]) # 相補感度関数に対する重み関数\n", "\n", "# # 混合感度問題\n", "# K, _, gamma = mixsyn(Pn, w1=WS , w2=WU, w3=WT) \n", "\n", "# print('K=', ss2tf(K))\n", "# print('gamma =', gamma[0])\n", "\n", "# fig, ax = plt.subplots(1, 2, figsize=(6,2.3))\n", "\n", "# # 感度関数\n", "# Ssys = feedback(1, Pn*K)\n", "# gain, _, w = bode(Ssys, logspace(-3,3), plot=False)\n", "# ax[0].semilogx(w, 20*np.log10(gain), ls= '-', lw =2, label='$S$', color='k')\n", "\n", "# gain, _, w = bode(1/WS, logspace(-3,3), plot=False)\n", "# ax[0].semilogx(w, 20*np.log10(gain), ls= '-.', lw =1, label='$1/W_S$', color='k')\n", "\n", "# # 相補感度関数\n", "# Tsys = feedback(Pn*K, 1)\n", "# gain, _, w = bode(Tsys, logspace(-3,3), plot=False)\n", "# ax[1].semilogx(w, 20*np.log10(gain), ls = '-', lw =2, label='$T$', color='k')\n", "\n", "# gain, _, w = bode(1/WT, logspace(-3,3), plot=False)\n", "# ax[1].semilogx(w, 20*np.log10(gain), ls= '--', lw =1, label='$1/W_T$', color='k')\n", "\n", "# for i in range(2):\n", "# ax[i].set_ylim(-40, 40)\n", "# ax[i].legend()\n", "# ax[i].grid(which=\"both\", ls=':')\n", "# ax[i].set_ylabel('Gain [dB]')\n", "# ax[i].set_xlabel('$\\omega$ [rad/s]')\n", "\n", "# fig.tight_layout()\n", "# # fig.savefig(\"robust_design.pdf\", transparent=True, bbox_inches=\"tight\", pad_inches=0.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# fig, ax = plt.subplots(figsize=(3, 2.3))\n", "\n", "# for i in range(len(delta)):\n", "# P = (1 + WT*delta[i])*Pn\n", "# Gyr = feedback(P*K, 1)\n", " \n", "# y, t = step(Gyr, np.arange(0,5,0.01))\n", "\n", "# ax.plot(t, y*ref, color ='k', lw =0.3)\n", "\n", "# Gyr = feedback(Pn*K, 1)\n", "# y, t = step(Gyr, np.arange(0,5,0.01))\n", "# ax.plot(t, y*ref, lw =2, color='k')\n", "\n", "# plot_set(ax, 't', 'y')\n", "# ax.set_xlim(0, 2)\n", "# ax.set_ylim(0, 60)\n", "\n", "# # fig.savefig(\"robust_step.pdf\", transparent=True, bbox_inches=\"tight\", pad_inches=0.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### PID制御との比較" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "kp = 2\n", "kd = 0.1\n", "ki = 10\n", "\n", "plt = plot()\n", "for i in 1:1:length(delta)\n", " Kpid = tf([kd, kp, ki], [1, 0])\n", " \n", " P = (1 + WT*delta[i])*Pn\n", " Gyr = feedback(P*Kpid, 1)\n", " y, t = step(Gyr, 0:0.01:5 )\n", " plot!(plt, t, y', lc=:black, lw =0.3)\n", "end\n", "\n", "plot!(plt,\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " ylim = (0,2),\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " legend=false,\n", " size=(300,230) #プロットのサイズ \n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ナイキスト線図で不確かさの影響を確認する" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Kpid = tf([kd, kp, ki], [1, 0])\n", "H = TransferFunction[ Kpid*(1 + WT*delta[i])*Pn for i in 1:length(delta) ];\n", "nyquistplot(H, gaincircle=true, lc = :black, lw = 1, xlim=(-1.5,0.5), ylim=(-1.5,0.5), size=(300,300), legend=false)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ディジタル実装" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "using ControlSystems\n", "using Plots; gr()\n", "using LinearAlgebra" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "連続時間システムTransferFunction{Continuous, ControlSystems.SisoRational{Float64}}\n", " 1.0\n", "----------\n", "0.5s + 1.0\n", "\n", "Continuous-time transfer function model\n" ] } ], "source": [ "P = tf([0, 1], [0.5, 1])\n", "println(\"連続時間システム\",P)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "離散時間システム(zoh)TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}\n", " 0.3296799539643608\n", "-------------------------\n", "1.0z - 0.6703200460356393\n", "\n", "Sample Time: 0.2 (seconds)\n", "Discrete-time transfer function model\n" ] } ], "source": [ "ts = 0.2\n", "\n", "Pd1 = c2d(P, ts, :zoh)\n", "println(\"離散時間システム(zoh)\", Pd1)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "離散時間システム(tustin)TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}\n", "0.16666666666666669z + 0.1666666666666667\n", "-----------------------------------------\n", " 1.0z - 0.6666666666666667\n", "\n", "Sample Time: 0.2 (seconds)\n", "Discrete-time transfer function model" ] } ], "source": [ "Pd2 = c2d(P, ts, :tustin)\n", "print(\"離散時間システム(tustin)\",Pd2)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tc = 0:0.01:3\n", "y, t = step(P, Tc)\n", "\n", "Td = 0:ts:3;\n", "\n", "p = [ plot(), plot()]\n", "\n", "plot!(p[1], t, y',\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"continuous\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "\n", "y, t = step(Pd1, Td)\n", "\n", "plot!(p[1], t, y',\n", " seriestype = :scatter,\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " label=\"zoh\",\n", " legend=:bottomright,\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "plot!(p[2], t, y',\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"continuous\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "\n", "y, t = step(Pd2, Td)\n", "\n", "plot!(p[2], t, y',\n", " seriestype = :scatter,\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " label=\"tustin\",\n", " legend=:bottomright,\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "\n", "plot( p[1], p[2], layout=(1,2), size=(600,230) )" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tc = 0:0.01:3\n", "\n", "u(x,t) = 0.5 * sin.(6*t) + 0.5 * cos.(8*t)\n", "yc, tc, x, uout = lsim(P, u, Tc);\n", "\n", "Td = 0:ts:3;\n", "\n", "p = [ plot(), plot()]\n", "\n", "plot!(p[1], tc, yc',\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"continuous\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "\n", "y, t, x, uout = lsim(Pd1, u, Td);\n", "\n", "plot!(p[1], t, y',\n", " seriestype = :scatter,\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " label=\"zoh\",\n", " legend=:bottomleft,\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "plot!(p[2], tc, yc',\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " lw=2, #線幅\n", " ls=:solid, #線種\n", " label=\"continuous\",\n", " size=(300,230) #プロットのサイズ \n", ")\n", "\n", "y, t, x, uout = lsim(Pd2, u, Td);\n", "\n", "plot!(p[2], t, y',\n", " seriestype = :scatter,\n", " xlabel=\"t\", #X軸のラベル\n", " ylabel=\"y\", #Y軸のラベル\n", " label=\"tustin\",\n", " legend=:bottomleft,\n", " size=(300,230) #プロットのサイズ \n", ")\n", " \n", "\n", "plot( p[1], p[2], layout=(1,2), size=(600,230) )" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "setPlotScale(\"dB\")\n", "bodeplot(P, lw=2, size=(450,400), legend=false, title=\"\" )" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "setPlotScale(\"dB\")\n", "bodeplot([Pd1, Pd2], lw=2, size=(450,400), legend=false, title=\"\" )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.7.0", "language": "julia", "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.7.0" } }, "nbformat": 4, "nbformat_minor": 4 }