{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pick a stereo baseline\n",
    "\n",
    "EECE 5554 Robotics Sensing and Navigation, Lecture 13. Put `stereo_baseline.py` in the same folder as this notebook, then run the cells in order."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each dark box below is a code cell. Edit it, then press **Run** or **Shift+Enter**. Cells share variables from top to bottom, like Jupyter."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "from stereo_baseline import focal_px, depth_error, closest_depth, max_range, baseline_for, table\n",
    "\n",
    "f = focal_px(5.0)          # our 5 mm lens on 4.5 um pixels\n",
    "print(f'f = {f:.0f} px')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Depth from disparity, and its error\n",
    "Z = f B / d, and δZ = Z² δd / (f B)."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "B = 0.5\n",
    "for Z in (3, 5, 10, 15, 20, 40):\n",
    "    print(f'Z = {Z:2d} m: disparity {f * B / Z:6.1f} px, error {100 * depth_error(Z, f, B):6.1f} cm')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Plot it for three baselines"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "Z = np.linspace(1, 40, 200)\n",
    "for B in (0.3, 0.5, 0.8):\n",
    "    plt.plot(Z, 100 * depth_error(Z, f, B), label=f'B = {B} m')\n",
    "plt.xlabel('distance (m)'); plt.ylabel('depth error (cm)'); plt.ylim(0, 100); plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. The other side of the trade\n",
    "The matcher searches 256 pixels of disparity. Anything closer than f B / 256 is out of range."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "for B in (0.3, 0.5, 0.8, 1.2):\n",
    "    print(f'B = {B} m: closest {closest_depth(f, B):.1f} m, 10 cm accuracy out to {max_range(0.10, f, B):.1f} m')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Your turn\n",
    "Write down your own requirement: a range and an accuracy. What baseline does it need, and can the 3 m garage test still be measured?"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "my_range, my_accuracy = 20.0, 0.15\n",
    "B = baseline_for(my_range, my_accuracy, f)\n",
    "print(f'baseline {B:.2f} m, closest usable depth {closest_depth(f, B):.1f} m')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}