{ "nbformat": 4, "nbformat_minor": 5, "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.12.0" }, "orphan": true }, "cells": [ { "cell_type": "markdown", "id": "ukf-title", "metadata": {}, "source": [ "# Unscented Kalman Filter (UKF)\n", "\n", "\u2190 [f_h Functions](../observers.ipynb)\n", "\n", "Derivation, argument reference, and worked example for the `ukf` block." ] }, { "cell_type": "markdown", "id": "ukf-overview", "metadata": {}, "source": [ "## Overview\n", "\n", "The UKF handles **nonlinear** systems without requiring Jacobians. Instead of linearising,\n", "it propagates a small set of deterministically chosen **sigma points** through the true\n", "nonlinear functions and reconstructs the mean and covariance from the results.\n", "\n", "This makes it more accurate than the EKF for strongly nonlinear systems and eliminates\n", "the need to derive or compute Jacobians analytically." ] }, { "cell_type": "markdown", "id": "ukf-model", "metadata": {}, "source": [ "## State-Space Model\n", "\n", "Same as the EKF \u2014 arbitrary nonlinear $f$ and $h$:\n", "\n", "$$x_{k+1} = f(x_k, u_k) + w_k, \\qquad w_k \\sim \\mathcal{N}(0, Q_k)$$\n", "$$y_k = h(x_k) + v_k, \\qquad v_k \\sim \\mathcal{N}(0, R_k)$$" ] }, { "cell_type": "markdown", "id": "ukf-sigma", "metadata": {}, "source": [ "## Sigma Points\n", "\n", "Given state dimension $n$ and scaling parameter $\\lambda = \\alpha^2(n + \\kappa) - n$,\n", "construct $2n + 1$ sigma points from the current estimate $\\hat{x}_{k-1}$ and covariance $P_{k-1}$:\n", "\n", "$$\\mathcal{X}^{(0)} = \\hat{x}_{k-1}$$\n", "$$\\mathcal{X}^{(i)} = \\hat{x}_{k-1} + \\left(\\sqrt{(n+\\lambda)\\,P_{k-1}}\\right)_i, \\quad i = 1,\\ldots,n$$\n", "$$\\mathcal{X}^{(i+n)} = \\hat{x}_{k-1} - \\left(\\sqrt{(n+\\lambda)\\,P_{k-1}}\\right)_i, \\quad i = 1,\\ldots,n$$\n", "\n", "where $\\left(\\sqrt{\\cdot}\\right)_i$ denotes the $i$-th column of the Cholesky factor.\n", "\n", "**Weights** for the mean ($W_m$) and covariance ($W_c$):\n", "\n", "$$W_m^{(0)} = \\frac{\\lambda}{n+\\lambda}, \\qquad W_m^{(i)} = \\frac{1}{2(n+\\lambda)}, \\quad i > 0$$\n", "$$W_c^{(0)} = W_m^{(0)} + 1 - \\alpha^2 + \\beta, \\qquad W_c^{(i)} = W_m^{(i)}, \\quad i > 0$$" ] }, { "cell_type": "markdown", "id": "ukf-predict", "metadata": {}, "source": [ "## Predict Step\n", "\n", "Propagate each sigma point through $f$, then compute the weighted mean and covariance:\n", "\n", "$$\\mathcal{X}^{(i)}_{k|k-1} = f\\left(\\mathcal{X}^{(i)}, u_k\\right)$$\n", "$$\\hat{x}_{k|k-1} = \\sum_i W_m^{(i)}\\, \\mathcal{X}^{(i)}_{k|k-1}$$\n", "$$P_{k|k-1} = \\sum_i W_c^{(i)}\\, (\\mathcal{X}^{(i)}_{k|k-1} - \\hat{x}_{k|k-1})(\\mathcal{X}^{(i)}_{k|k-1} - \\hat{x}_{k|k-1})^\\top + Q_k$$" ] }, { "cell_type": "markdown", "id": "ukf-update", "metadata": {}, "source": [ "## Update Step\n", "\n", "Map the predicted sigma points through $h$, compute the innovation statistics, then apply the Kalman correction:\n", "\n", "$$\\mathcal{Y}^{(i)} = h\\left(\\mathcal{X}^{(i)}_{k|k-1}\\right)$$\n", "$$\\hat{y}_{k|k-1} = \\sum_i W_m^{(i)}\\, \\mathcal{Y}^{(i)}$$\n", "$$S_k = \\sum_i W_c^{(i)}\\,(\\mathcal{Y}^{(i)} - \\hat{y})(\\mathcal{Y}^{(i)} - \\hat{y})^\\top + R_k$$\n", "$$P_{xy} = \\sum_i W_c^{(i)}\\,(\\mathcal{X}^{(i)}_{k|k-1} - \\hat{x}_{k|k-1})(\\mathcal{Y}^{(i)} - \\hat{y})^\\top$$\n", "$$K_k = P_{xy}\\, S_k^{-1}$$\n", "$$\\hat{x}_k = \\hat{x}_{k|k-1} + K_k\\,(y_k - \\hat{y}_{k|k-1})$$\n", "$$P_k = P_{k|k-1} - K_k\\, S_k\\, K_k^\\top$$" ] }, { "cell_type": "markdown", "id": "ukf-args", "metadata": {}, "source": [ "## Argument Reference\n", "\n", "### `zk` \u2014 UKF state   `tuple[Float[np.ndarray, \"n\"], Float[np.ndarray, \"n n\"]]`\n", "\n", "| Field | Symbol | Shape | Description |\n", "|-------|--------|-------|-------------|\n", "| `zk[0]` | $\\hat{x}_k$ | `(n,)` | Current state estimate |\n", "| `zk[1]` | $P_k$ | `(n, n)` | Error covariance \u2014 symmetric, positive semi-definite |\n", "\n", "**Initialisation:** `zk = (x0, P0)`. Same convention as the KF and EKF.\n", "\n", "---\n", "\n", "### `uk` \u2014 control input   `float`\n", "\n", "Scalar control input at step $k$. Passed directly to `f_nl(x, uk)`. Pass `0.0` if uncontrolled.\n", "\n", "---\n", "\n", "### `yk` \u2014 measurement   `Float[np.ndarray, \"m\"]`\n", "\n", "Raw sensor reading at step $k$, shape `(m,)`. Must match the output space of `h_nl`.\n", "\n", "---\n", "\n", "### `f_nl` \u2014 nonlinear dynamics   `Callable`\n", "\n", "Signature: `f_nl(x: ndarray, u: float) -> ndarray`\n", "\n", "The true nonlinear state transition. Each sigma point is propagated through this function.\n", "No Jacobian of `f_nl` is required.\n", "\n", "---\n", "\n", "### `h_nl` \u2014 nonlinear observation   `Callable`\n", "\n", "Signature: `h_nl(x: ndarray) -> ndarray`\n", "\n", "The true nonlinear observation function. Each predicted sigma point is mapped through this\n", "to form the innovation statistics. No Jacobian of `h_nl` is required.\n", "\n", "---\n", "\n", "### `Qk` \u2014 process noise covariance   `Float[np.ndarray, \"n n\"]`\n", "\n", "Shape `(n, n)`, symmetric positive semi-definite. Added to the predicted covariance. Same role as in the KF.\n", "\n", "---\n", "\n", "### `Rk` \u2014 measurement noise covariance   `Float[np.ndarray, \"m m\"]`\n", "\n", "Shape `(m, m)`, symmetric positive definite. Added to the innovation covariance. Same role as in the KF.\n", "\n", "---\n", "\n", "### `alpha` \u2014 sigma point spread   `float` (default `1e-3`)\n", "\n", "Controls how far the sigma points spread around the mean. Typical range: $10^{-4}$ to $1$.\n", "Smaller values keep sigma points close to the mean; larger values explore more of the\n", "nonlinear region. Affects $\\lambda = \\alpha^2(n + \\kappa) - n$.\n", "\n", "---\n", "\n", "### `beta` \u2014 distribution parameter   `float` (default `2.0`)\n", "\n", "Incorporates prior knowledge of the state distribution. $\\beta = 2$ is optimal for Gaussian\n", "distributions and is the correct default in most robotics/control applications. Only the\n", "zeroth covariance weight $W_c^{(0)}$ is affected.\n", "\n", "---\n", "\n", "### `kappa` \u2014 secondary scaling   `float` (default `0.0`)\n", "\n", "Secondary scaling parameter. Common choices are $\\kappa = 0$ or $\\kappa = 3 - n$\n", "(the latter ensures the fourth-order terms of the Taylor expansion are captured exactly\n", "for Gaussian distributions). Typically left at `0.0`." ] }, { "cell_type": "markdown", "id": "ukf-impl-header", "metadata": {}, "source": [ "## Implementation\n", "\n", "`ukf_f` runs the full sigma-point predict\u2192update cycle and returns the new state and covariance.\n", "`ukf_h` extracts $\\hat{x}_k$ for downstream use.\n", "\n", "The `**kwargs` in `ukf_h` absorbs any extra arguments passed by `_smart_call` that `h` does not need." ] }, { "cell_type": "code", "id": "ukf-imports", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "import numpy as np\n", "from typing import Callable\n", "from jaxtyping import Float, jaxtyped\n", "from beartype import beartype\n", "from dynamicalnodes import DynamicalSystem" ] }, { "cell_type": "code", "id": "ukf-impl", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "@jaxtyped(typechecker=beartype)\n", "def ukf_f(\n", " zk: tuple[Float[np.ndarray, \"n\"], Float[np.ndarray, \"n n\"]],\n", " uk: float,\n", " yk: Float[np.ndarray, \"m\"],\n", " f_nl: Callable,\n", " h_nl: Callable,\n", " Qk: Float[np.ndarray, \"n n\"],\n", " Rk: Float[np.ndarray, \"m m\"],\n", " alpha: float = 1e-3,\n", " beta: float = 2.0,\n", " kappa: float = 0.0,\n", ") -> tuple[Float[np.ndarray, \"n\"], Float[np.ndarray, \"n n\"]]:\n", " \"\"\"UKF predict+update via sigma-point propagation; returns updated state and covariance.\n", "\n", " Args:\n", " zk: UKF state \u2014 2-tuple of (x\u0302_k, P_k), state estimate and error covariance.\n", " uk: Scalar control input.\n", " yk: Measurement vector (m,).\n", " f_nl: Nonlinear state transition f(x, u) \u2192 x_next.\n", " h_nl: Nonlinear observation function h(x) \u2192 y.\n", " Qk: Process noise covariance (n, n).\n", " Rk: Measurement noise covariance (m, m).\n", " alpha: Sigma point spread around the mean (default 1e-3).\n", " beta: Distribution parameter; 2.0 optimal for Gaussian (default 2.0).\n", " kappa: Secondary scaling parameter, typically 0 or 3-n (default 0.0).\n", " \"\"\"\n", " x, P = zk\n", " n = len(x)\n", " lam = alpha**2 * (n + kappa) - n\n", "\n", " sqrtP = np.linalg.cholesky((n + lam) * P)\n", " sigmas = np.column_stack(\n", " [x] + [x + sqrtP[:, i] for i in range(n)] + [x - sqrtP[:, i] for i in range(n)]\n", " )\n", " Wm = np.full(2 * n + 1, 1.0 / (2 * (n + lam)))\n", " Wm[0] = lam / (n + lam)\n", " Wc = Wm.copy()\n", " Wc[0] += 1 - alpha**2 + beta\n", "\n", " # Predict\n", " sf = np.column_stack([f_nl(sigmas[:, i], uk) for i in range(2 * n + 1)])\n", " xp = sf @ Wm\n", " Pp = (\n", " sum(Wc[i] * np.outer(sf[:, i] - xp, sf[:, i] - xp) for i in range(2 * n + 1))\n", " + Qk\n", " )\n", "\n", " # Update\n", " yk = np.atleast_1d(yk)\n", " sh = np.column_stack([np.atleast_1d(h_nl(sf[:, i])) for i in range(2 * n + 1)])\n", " yp = sh @ Wm\n", " S = (\n", " sum(Wc[i] * np.outer(sh[:, i] - yp, sh[:, i] - yp) for i in range(2 * n + 1))\n", " + Rk\n", " )\n", " Pxy = sum(Wc[i] * np.outer(sf[:, i] - xp, sh[:, i] - yp) for i in range(2 * n + 1))\n", " K = Pxy @ np.linalg.inv(S)\n", " return (xp + K @ (yk - yp), Pp - K @ S @ K.T)\n", "\n", "\n", "@jaxtyped(typechecker=beartype)\n", "def ukf_h(\n", " zk: tuple[Float[np.ndarray, \"n\"], Float[np.ndarray, \"n n\"]],\n", " **kwargs,\n", ") -> Float[np.ndarray, \"n\"]:\n", " \"\"\"Return the current state estimate from the UKF state tuple.\n", "\n", " Args:\n", " zk: UKF state \u2014 2-tuple of (x\u0302_k, P_k), state estimate and error covariance.\n", " \"\"\"\n", " return zk[0]\n", "\n", "\n", "ukf = DynamicalSystem(f=ukf_f, h=ukf_h)" ] }, { "cell_type": "markdown", "id": "ukf-usage-header", "metadata": {}, "source": [ "## Worked Example \u2014 Pendulum\n", "\n", "Same pendulum as the EKF example \u2014 no Jacobians required." ] }, { "cell_type": "code", "id": "ukf-usage", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "g, L, dt = 9.81, 1.0, 0.05\n", "\n", "\n", "def pend_f(x, u):\n", " th, w = x\n", " return np.array([th + dt * w, w + dt * (-g / L * np.sin(th) + u)])\n", "\n", "\n", "def pend_h(x):\n", " return np.array([x[0]])\n", "\n", "\n", "Qk = np.diag([1e-4, 1e-3])\n", "Rk = np.array([[0.05]])\n", "\n", "zk = (np.array([0.1, 0.0]), np.eye(2))\n", "zk_next, x_est = ukf.step(\n", " zk=zk, uk=0.0, yk=np.array([0.09]), f_nl=pend_f, h_nl=pend_h, Qk=Qk, Rk=Rk\n", ")\n", "print(\"estimate (pre-update):\", x_est)\n", "print(\"updated estimate: \", zk_next[0])\n", "print(\"updated covariance:\\n\", zk_next[1])" ] }, { "cell_type": "markdown", "id": "08ac3224", "source": [ "#", "#", " ", "`", "D", "y", "n", "a", "m", "i", "c", "a", "l", "S", "y", "s", "t", "e", "m", "`", " ", "\u2192", " ", "`", "R", "O", "S", "N", "o", "d", "e", "`" ], "metadata": {} }, { "cell_type": "code", "id": "80b82573", "source": [ "f", "r", "o", "m", " ", "d", "y", "n", "a", "m", "i", "c", "a", "l", "n", "o", "d", "e", "s", " ", "i", "m", "p", "o", "r", "t", " ", "R", "O", "S", "N", "o", "d", "e", "\n", "f", "r", "o", "m", " ", "d", "y", "n", "a", "m", "i", "c", "a", "l", "n", "o", "d", "e", "s", ".", "r", "o", "s", "2", "p", "y", "_", "p", "y", "2", "r", "o", "s", " ", "i", "m", "p", "o", "r", "t", " ", "(", "\n", " ", " ", " ", " ", "r", "o", "s", "2", "p", "y", "_", "f", "l", "o", "a", "t", "6", "4", "_", "m", "u", "l", "t", "i", "a", "r", "r", "a", "y", ",", "\n", " ", " ", " ", " ", "r", "o", "s", "2", "p", "y", "_", "f", "l", "o", "a", "t", "6", "4", ",", "\n", " ", " ", " ", " ", "p", "y", "2", "r", "o", "s", "_", "f", "l", "o", "a", "t", "6", "4", "_", "m", "u", "l", "t", "i", "a", "r", "r", "a", "y", ",", "\n", ")", "\n", "f", "r", "o", "m", " ", "s", "t", "d", "_", "m", "s", "g", "s", ".", "m", "s", "g", " ", "i", "m", "p", "o", "r", "t", " ", "F", "l", "o", "a", "t", "6", "4", "M", "u", "l", "t", "i", "A", "r", "r", "a", "y", ",", " ", "F", "l", "o", "a", "t", "6", "4", "\n", "\n", "u", "k", "f", "_", "n", "o", "d", "e", " ", "=", " ", "R", "O", "S", "N", "o", "d", "e", "(", "\n", " ", " ", " ", " ", "d", "y", "n", "a", "m", "i", "c", "a", "l", "_", "s", "y", "s", "t", "e", "m", "=", "u", "k", "f", ",", "\n", " ", " ", " ", " ", "s", "u", "b", "s", "c", "r", "i", "b", "e", "s", "_", "t", "o", "=", "[", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "{", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "t", "o", "p", "i", "c", "\"", ":", " ", "\"", "/", "m", "e", "a", "s", "u", "r", "e", "m", "e", "n", "t", "\"", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "m", "s", "g", "_", "t", "y", "p", "e", "\"", ":", " ", "F", "l", "o", "a", "t", "6", "4", "M", "u", "l", "t", "i", "A", "r", "r", "a", "y", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "a", "r", "g", "\"", ":", " ", "\"", "y", "k", "\"", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "r", "o", "s", "2", "p", "y", "\"", ":", " ", "r", "o", "s", "2", "p", "y", "_", "f", "l", "o", "a", "t", "6", "4", "_", "m", "u", "l", "t", "i", "a", "r", "r", "a", "y", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "}", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "{", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "t", "o", "p", "i", "c", "\"", ":", " ", "\"", "/", "c", "o", "n", "t", "r", "o", "l", "\"", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "m", "s", "g", "_", "t", "y", "p", "e", "\"", ":", " ", "F", "l", "o", "a", "t", "6", "4", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "a", "r", "g", "\"", ":", " ", "\"", "u", "k", "\"", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "r", "o", "s", "2", "p", "y", "\"", ":", " ", "r", "o", "s", "2", "p", "y", "_", "f", "l", "o", "a", "t", "6", "4", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "}", ",", "\n", " ", " ", " ", " ", "]", ",", "\n", " ", " ", " ", " ", "p", "u", "b", "l", "i", "s", "h", "e", "s", "_", "t", "o", "=", "[", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "{", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "t", "o", "p", "i", "c", "\"", ":", " ", "\"", "/", "s", "t", "a", "t", "e", "_", "e", "s", "t", "i", "m", "a", "t", "e", "\"", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "m", "s", "g", "_", "t", "y", "p", "e", "\"", ":", " ", "F", "l", "o", "a", "t", "6", "4", "M", "u", "l", "t", "i", "A", "r", "r", "a", "y", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "p", "y", "2", "r", "o", "s", "\"", ":", " ", "p", "y", "2", "r", "o", "s", "_", "f", "l", "o", "a", "t", "6", "4", "_", "m", "u", "l", "t", "i", "a", "r", "r", "a", "y", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "}", ",", "\n", " ", " ", " ", " ", "]", ",", "\n", ")" ], "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "6a41eebb", "source": [ "#", "#", " ", "`", "R", "O", "S", "N", "o", "d", "e", ".", "w", "r", "i", "t", "e", "_", "R", "O", "S", "N", "o", "d", "e", "_", "t", "o", "_", "r", "c", "l", "p", "y", "(", ")", "`" ], "metadata": {} }, { "cell_type": "code", "id": "551bb17b", "source": [ "g", ",", " ", "L", ",", " ", "d", "t", "_", "u", "k", "f", " ", "=", " ", "9", ".", "8", "1", ",", " ", "1", ".", "0", ",", " ", "0", ".", "1", "\n", "\n", "\n", "d", "e", "f", " ", "p", "e", "n", "d", "u", "l", "u", "m", "_", "f", "(", "x", ",", " ", "u", ")", ":", "\n", " ", " ", " ", " ", "t", "h", "e", "t", "a", ",", " ", "o", "m", "e", "g", "a", " ", "=", " ", "x", "\n", " ", " ", " ", " ", "a", "l", "p", "h", "a", " ", "=", " ", "-", "g", " ", "/", " ", "L", " ", "*", " ", "n", "p", ".", "s", "i", "n", "(", "t", "h", "e", "t", "a", ")", " ", "+", " ", "u", "\n", " ", " ", " ", " ", "r", "e", "t", "u", "r", "n", " ", "n", "p", ".", "a", "r", "r", "a", "y", "(", "[", "t", "h", "e", "t", "a", " ", "+", " ", "o", "m", "e", "g", "a", " ", "*", " ", "d", "t", "_", "u", "k", "f", ",", " ", "o", "m", "e", "g", "a", " ", "+", " ", "a", "l", "p", "h", "a", " ", "*", " ", "d", "t", "_", "u", "k", "f", "]", ")", "\n", "\n", "\n", "d", "e", "f", " ", "p", "e", "n", "d", "u", "l", "u", "m", "_", "h", "(", "x", ")", ":", "\n", " ", " ", " ", " ", "r", "e", "t", "u", "r", "n", " ", "n", "p", ".", "a", "r", "r", "a", "y", "(", "[", "x", "[", "0", "]", "]", ")", "\n", "\n", "\n", "u", "k", "f", "_", "n", "o", "d", "e", ".", "w", "r", "i", "t", "e", "_", "R", "O", "S", "N", "o", "d", "e", "_", "t", "o", "_", "r", "c", "l", "p", "y", "(", "\n", " ", " ", " ", " ", "\"", "u", "k", "f", "_", "n", "o", "d", "e", ".", "p", "y", "\"", ",", "\n", " ", " ", " ", " ", "n", "o", "d", "e", "_", "n", "a", "m", "e", "=", "\"", "u", "n", "s", "c", "e", "n", "t", "e", "d", "_", "k", "a", "l", "m", "a", "n", "_", "f", "i", "l", "t", "e", "r", "\"", ",", "\n", " ", " ", " ", " ", "d", "e", "p", "s", "=", "[", "p", "e", "n", "d", "u", "l", "u", "m", "_", "f", ",", " ", "p", "e", "n", "d", "u", "l", "u", "m", "_", "h", "]", ",", "\n", " ", " ", " ", " ", "i", "n", "i", "t", "i", "a", "l", "_", "s", "t", "a", "t", "e", "=", "(", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "n", "p", ".", "a", "r", "r", "a", "y", "(", "[", "0", ".", "0", ",", " ", "0", ".", "0", "]", ")", ",", " ", " ", "#", " ", "x", "\u0302", "_", "0", ":", " ", "[", "\u03b8", ",", " ", "\u03c9", "]", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "n", "p", ".", "e", "y", "e", "(", "2", ")", ",", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#", " ", "P", "_", "0", "\n", " ", " ", " ", " ", ")", ",", "\n", " ", " ", " ", " ", "s", "t", "a", "t", "i", "c", "_", "p", "a", "r", "a", "m", "s", "=", "{", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "f", "_", "n", "l", "\"", ":", " ", "p", "e", "n", "d", "u", "l", "u", "m", "_", "f", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "h", "_", "n", "l", "\"", ":", " ", "p", "e", "n", "d", "u", "l", "u", "m", "_", "h", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "Q", "k", "\"", ":", " ", "n", "p", ".", "d", "i", "a", "g", "(", "[", "1", "e", "-", "4", ",", " ", "1", "e", "-", "3", "]", ")", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "R", "k", "\"", ":", " ", "n", "p", ".", "a", "r", "r", "a", "y", "(", "[", "[", "0", ".", "0", "1", "]", "]", ")", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "a", "l", "p", "h", "a", "\"", ":", " ", "1", "e", "-", "3", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "b", "e", "t", "a", "\"", ":", " ", "2", ".", "0", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "k", "a", "p", "p", "a", "\"", ":", " ", "0", ".", "0", ",", "\n", " ", " ", " ", " ", "}", ",", "\n", " ", " ", " ", " ", "i", "n", "i", "t", "i", "a", "l", "_", "i", "n", "p", "u", "t", "s", "=", "{", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "y", "k", "\"", ":", " ", "n", "p", ".", "a", "r", "r", "a", "y", "(", "[", "0", ".", "0", "]", ")", ",", "\n", " ", " ", " ", " ", " ", " ", " ", " ", "\"", "u", "k", "\"", ":", " ", "0", ".", "0", ",", "\n", " ", " ", " ", " ", "}", ",", "\n", ")" ], "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "ukf-backlink", "metadata": {}, "source": [ "\u2190 [f_h Functions](../observers.ipynb)" ] } ] }