{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains material from [cbe30338-2021](https://jckantor.github.io/cbe30338-2021);\n", "content is available [on Github](https://github.com/jckantor/cbe30338-2021.git).*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [4.7 Observer Synthesis using Linear Matrix Inequalities](https://jckantor.github.io/cbe30338-2021/04.07-Observer-Synthesis-LMI.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [5.0 Optimization](https://jckantor.github.io/cbe30338-2021/05.00-Optimization.html) >
"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 1,
"link": "[4.8 Application of Luenberger Observers to Environmental Modeling of Rivers](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8-Application-of-Luenberger-Observers-to-Environmental-Modeling-of-Rivers)",
"section": "4.8 Application of Luenberger Observers to Environmental Modeling of Rivers"
}
},
"source": [
"# 4.8 Application of Luenberger Observers to Environmental Modeling of Rivers\n",
"\n",
"Rodriguez-Mata, Abraham Efraim, et al. \"A Fractional High-Gain Nonlinear Observer Design—Application for Rivers Environmental Monitoring Model.\" Mathematical and Computational Applications 25.3 (2020): 44. [https://www.mdpi.com/2297-8747/25/3/44](https://www.mdpi.com/2297-8747/25/3/44)"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.1 Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.1-Model)",
"section": "4.8.1 Model"
}
},
"source": [
"## 4.8.1 Model\n",
"\n",
"The Streeter-Phelps model for oxygen in a river or stream is given by the pair of linear differential equations\n",
"\n",
"\\begin{align}\n",
"\\frac{dx_1}{dt} & = -\\frac{k_1}{U} x_2 + \\frac{k_2}{U}(D_s - x_1) \\\\\n",
"\\frac{dx_2}{dt} & = -\\frac{k_1}{U} x_2\n",
"\\end{align}\n",
"\n",
"where $x_1$ is dissolved oxygen (DO) and $x_2$ is biological oxygen demand (BOD). Rate constant $k_1$ is the BOD removal rate, $k_2$ is the re-areation rate, and $D_s$ is the oxygen saturation level which, for this problem, is a disturbance variable. No manipulations to this system are possible.\n",
"\n",
"For environmental monitoring, dissolved oxygen can be measured in the field with a low-cost sensor. BOD, however, cannot be measured in the field.\n",
"\n",
"Our standard model for a state-space system is given by\n",
"\n",
"\\begin{align}\n",
"\\frac{dx}{dt} & = A x + B_d d + B_u u\\\\\n",
"y & = C x\n",
"\\end{align}\n",
"\n",
"where $x$ contains the states, $d$ contains the disturbances, and $u$ contains the manipulable inputs."
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.1 Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.1-Model)",
"section": "4.8.1 Model"
}
},
"source": [
"Parameter values are $k_1 = 0.3\\ \\text{day}^{-1}$, $k_2 = 0.06\\ \\text{day}^{-1}$, and $U = 1$. A typical value of Ds = 16 mg/liter. For these values the state space model becomes\n",
"\n",
"\\begin{align}\n",
"\\frac{dx}{dt} & = A x + B_d d + B_u u\\\\\n",
"y & = C x\n",
"\\end{align}\n",
"\n",
"where \n",
"\n",
"\\begin{align}\n",
"A & = \\begin{bmatrix} -0.06 & -0.3 \\\\0 & -0.3\\end{bmatrix}\n",
"\\qquad\n",
"B_d = \\begin{bmatrix} 0.06 \\\\ 0 \\end{bmatrix} \\\\\n",
"C & = \\begin{bmatrix} 1 & 0 \\end{bmatrix}\n",
"\\end{align}\n",
"\n",
"For the state estimator, aat each time step $t_k$ there are two calculations to perform:\n",
"\n",
"* **Model Prediction:** Use the model to update the state to the next time step, i.e., $\\hat{x}_{k-1} \\rightarrow \\hat{x}_{k}^{pred}$ with the equation\n",
"\n",
"\\begin{align}\n",
"\\hat{x}_k^{pred} & = \\hat{x}_{k-1} + (t_k - t_{k-1}) ( A \\hat{x}_{k-1} + B_u u_{k-1} + B_d \\hat{d}_{k-1}) \\\\\n",
"\\hat{y}_k^{pred} & = C \\hat{x}_k^{pred}\n",
"\\end{align}\n",
"\n",
"* **Measurement Correction:** Use measurement $y_k$ to update $\\hat{x}_{k}^{pred} \\rightarrow \\hat{x}_{k}$ with the equation\n",
"\n",
"$$\\hat{x}_{k} = \\hat{x}_{k}^{pred} - (t_k - t_{k-1})L (\\hat{y}_{k}^{pred} - y_k)$$ \n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.1 Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.1-Model)",
"section": "4.8.1 Model"
}
},
"outputs": [],
"source": [
"\n",
"\n",
"therefore it is desired to implement a Luenberger observer to estimate BOD. \n",
"\n",
"\n",
"Our standard model for a state-space system is given by\n",
"\n",
"\\begin{align}\n",
"\\frac{dx}{dt} & = A x + + B_u u + B_d d \\\\\n",
"y & = C x\n",
"\\end{align}"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.2 State Space Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.2-State-Space-Model)",
"section": "4.8.2 State Space Model"
}
},
"source": [
"## 4.8.2 State Space Model"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.2 State Space Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.2-State-Space-Model)",
"section": "4.8.2 State Space Model"
}
},
"outputs": [
{
"data": {
"text/plain": [
"array([[-0.06, -0.3 ],\n",
" [ 0. , -0.3 ]])"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"\n",
"k1 = 0.3\n",
"k2 = 0.06\n",
"U = 1\n",
"Ds = 16.0\n",
"\n",
"\n",
"A = np.array([[-k2/U, -k1/U], [0, -k1/U]])\n",
"Bd = np.array([[k2/U], [0]])\n",
"C = np.array([[1, 0]])\n",
"\n",
"\n",
"sources = [\n",
" (\"DO\", lambda: x[0]),\n",
" (\"BOD\", lambda: x[1]),\n",
" (\"DS\", lambda: Ds )\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.2 State Space Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.2-State-Space-Model)",
"section": "4.8.2 State Space Model"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 0.49691879]\n",
" [-0.43544205]]\n"
]
}
],
"source": [
"import numpy as np\n",
"import cvxpy as cp\n",
"n=2\n",
"p = 1\n",
"\n",
"P = cp.Variable((n, n), PSD=True)\n",
"Y = cp.Variable((n, p))\n",
"\n",
"gamma = .75\n",
"constraints = [P >> np.eye(n)]\n",
"constraints += [A.T@P + P@A - C.T@Y.T - Y@C + gamma*P << 0]\n",
"\n",
"prob = cp.Problem(cp.Minimize(0), constraints)\n",
"prob.solve()\n",
"L = np.linalg.inv(P.value)@Y.value\n",
"print(L)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.2 State Space Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.2-State-Space-Model)",
"section": "4.8.2 State Space Model"
}
},
"outputs": [
{
"data": {
"text/plain": [
"(array([-0.4284594+0.3378325j, -0.4284594-0.3378325j]),\n",
" array([[-0.22700032+0.59698307j, -0.22700032-0.59698307j],\n",
" [ 0.76946869+0.j , 0.76946869-0.j ]]))"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.eig(A-L@C)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"nbpages": {
"level": 2,
"link": "[4.8.2 State Space Model](https://jckantor.github.io/cbe30338-2021/04.08-State-Estimation-Envrironmental-Application.html#4.8.2-State-Space-Model)",
"section": "4.8.2 State Space Model"
}
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"< [4.7 Observer Synthesis using Linear Matrix Inequalities](https://jckantor.github.io/cbe30338-2021/04.07-Observer-Synthesis-LMI.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [5.0 Optimization](https://jckantor.github.io/cbe30338-2021/05.00-Optimization.html) >
"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}