{
"cells": [
{
"cell_type": "markdown",
"id": "a85cc762",
"metadata": {},
"source": [
"[← Control Systems as Dynamical Systems](../../../getting_started/theory_to_python/control_systems_as_dynamical_systems.rst)"
]
},
{
"cell_type": "markdown",
"id": "9f7593f9",
"metadata": {},
"source": [
"# Example: TurtleBot with Noisy Odometry"
]
},
{
"cell_type": "markdown",
"id": "68525bd5",
"metadata": {},
"source": [
"In this notebook, we model a TurtleBot3 navigating towards waypoints with noisy odometry data and use ``pykal`` to recast it as a composition of dynamical systems.\n",
"\n",
"## System Overview\n",
"\n",
"We consider uneven terrain and wheel slip as process noise, and measurement quantization as measurement noise. The Turtlebot3 offers a high-level controllers that lets us abstract away many details, as we will see below."
]
},
{
"cell_type": "markdown",
"id": "fddaa3a3",
"metadata": {},
"source": [
"## Block Diagram\n",
"\n",
"We can model the TurtleBot3 feedback system we are interested in as follows:\n",
"\n",
"\n",
"\n",
"where **waypoint generator** produces reference trajectories (e.g., \"move to\" coordinates), **velocity command** is a controller that outputs linear and angular velocity, **TurtleBot** is our robot with an odometry sensor, that is, with wheel encoders measuring position and orientation, and **Kalman Filter** is the state observer that fuses control inputs and the measurement from the odometry sensor.\n",
"\n",
":::{note}\n",
"The TurtleBot has an onboard low-level controller that converts linear and angular velocity commands to the to the appropriate wheel speeds. Thus, our \"velocity controller\" is simply an algorithm that generates such commands.\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "13d262bf",
"metadata": {},
"source": [
"### Discrete-time Dynamical Systems\n",
"\n",
"For a minimal working knowledge of the theory of discrete-time dynamical systems, check out the :doc:`\"DynamicalSystem\" <./dynamical_system>` notebook under \"Modules\" . We assume a basic familiarity with the theory and proceed with casting our diagram blocks as dynamical system blocks.\n",
"\n",
"
\n",
"\n",
"We discuss the derivation of each dynamical system block below.\n",
":::{note} This diagram is techincally a lie: as we will soon see, our waypoint generator will require a state estimate to determine which waypoint it generates. So we should draw another $\\hat{x}$ arrow that feeds into the waypoint generator block. But we don't. Why? The state estimate $\\hat{x}$ will be passed in as an explicit paramter, and we choose not to model explicity paramters as arrows to keep our diagrams clean. See \"Function and Diagram Convention\" for more details.\n",
"\n",
":::{tip} Notice that we have introduced a naming convention where subscripts on functions denote the block with which they are associated. In particular, the subscript $k$ is added to all state and output variables. Refer to :doc:`\"DynamicalSystem\" <./dynamical_system>` for the naming convention and why it is a good idea to represent functions and variables in such a way.\n"
]
},
{
"cell_type": "markdown",
"id": "d5da675b",
"metadata": {},
"source": [
"### Block 1: Waypoint Generator\n",
"\n",
"