{
"cells": [
{
"cell_type": "markdown",
"id": "abdd4aba",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"id": "23d8e5dc",
"metadata": {},
"source": [
"# Stereo Visual Odometry\n",
"\n",
"A 3D stereo visual odometry example.\n",
"\n",
" - robot starts at origin\n",
" - moves forward, taking periodic stereo measurements\n",
" - takes stereo readings of many landmarks"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip -q install gtbook # also installs latest gtsam pre-release"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"import gtsam\n",
"from gtsam import noiseModel, Pose3, StereoPoint2, Point3\n",
"import gtsam.utils.plot as gtsam_plot"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Stereo Rig Calibration\n",
"\n",
"Just a regular pinhole calibration, plus a baseline, which in this case is 54 cm."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"focal length ~ 722.0, baseline = 54.0cm\n"
]
}
],
"source": [
"# read camera calibration info from file\n",
"# focal lengths fx, fy, skew s, principal point u0, v0, baseline b\n",
"calibration_loc = gtsam.findExampleDataFile(\"VO_calibration.txt\")\n",
"fx, fy, s, u0, v0, b =np.loadtxt(calibration_loc)\n",
"\n",
"# create stereo camera calibration object\n",
"K = gtsam.Cal3_S2Stereo(fx, fy, s, u0, v0, b)\n",
"print(f\"focal length ~ {np.round(fx)}, baseline = {np.round(100*b)}cm\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Camera Poses\n",
"\n",
"We already have a very good initial estimate on file..."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"pose_loc = gtsam.findExampleDataFile(\"VO_camera_poses_large.txt\")\n",
"pose_array = np.loadtxt(pose_loc)\n",
"initial_estimate = gtsam.Values()\n",
"for row in pose_array:\n",
" initial_estimate.insert(gtsam.symbol('x', int(row[0])), Pose3(row[1:].reshape(4,4)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create Factor Graph\n",
"\n",
"We have about 8000 measurements, specified in a file as 8 numbers per row:\n",
"\n",
"- i, j: pose and landmark indices\n",
"- uL, uR, v: the stereo measurement\n",
"- X, Y, Z: an initial estimate for the corresponding point $l_j$, resulting from triangulation"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"factor_loc = gtsam.findExampleDataFile(\"VO_stereo_factors_large.txt\")\n",
"factor_array = np.loadtxt(factor_loc)\n",
"\n",
"graph = gtsam.NonlinearFactorGraph ()\n",
"model = noiseModel.Isotropic.Sigma(3, 1) # 1 pixel standard deviation\n",
"for i, j, uL, uR, v, X, Y, Z in factor_array:\n",
" measured = StereoPoint2(uL, uR, v)\n",
" pose_key, point_key = gtsam.symbol('x', int(i)), gtsam.symbol('l', int(j))\n",
" graph.add(gtsam.GenericStereoFactor3D(\n",
" measured, model, pose_key, point_key, K))\n",
" # if the landmark variable included in this factor has not yet been added\n",
" # to the initial variable value estimate, add it\n",
" if not initial_estimate.exists(point_key):\n",
" wTc = initial_estimate.atPose3(pose_key)\n",
" worldPoint = wTc.transformFrom(Point3(X, Y, Z))\n",
" initial_estimate.insert(point_key, worldPoint)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Batch Optimization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We constrain the first pose such that it cannot change from its original value during optimization.\n",
"NOTE: NonlinearEquality forces the optimizer to use QR rather than Cholesky QR is much slower than Cholesky, but numerically more stable."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"first_pose = initial_estimate.atPose3(gtsam.symbol('x', 1))\n",
"graph.add(gtsam.NonlinearEqualityPose3(gtsam.symbol('x', 1), first_pose))\n",
"\n",
"# create Levenberg-Marquardt optimizer to optimize the factor graph\n",
"params = gtsam.LevenbergMarquardtParams()\n",
"params.setOrderingType(\"METIS\")\n",
"optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial_estimate, params)\n",
"result = optimizer.optimize()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us bring the first 3 poses:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"R: [\n",
"\t1, 0, 0;\n",
"\t0, 1, 0;\n",
"\t0, 0, 1\n",
"]\n",
"t: 0 0 0\n",
"\n",
"R: [\n",
"\t0.999997, -0.00234524, 0.000667659;\n",
"\t0.00234572, 0.999997, -0.000714904;\n",
"\t-0.000665981, 0.000716469, 1\n",
"]\n",
"t: 0.00254935 0.00430119 0.959176\n",
"\n",
"R: [\n",
"\t0.999993, -0.00363586, 0.000733503;\n",
"\t0.00363353, 0.999988, 0.00316275;\n",
"\t-0.000744993, -0.00316007, 0.999995\n",
"]\n",
"t: 0.00112241 0.00989265 1.9179\n",
"\n"
]
}
],
"source": [
"for i in pose_array[:3,0]:\n",
" pose_key = gtsam.symbol('x', int(i))\n",
" print(result.atPose3(pose_key))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also plot the result (needs more work):"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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OH78uBBCiEcffVT069dP/PDDD0IIId555x2RmJgotFqtmDp1qvj222+veO6EEJf8bbw43NrNLXZFeoDCwkL06NEDGo31kGdzN0PreSoAUFBQgN69e7f8npCQ0LJMW/edO3cOFovFDVtwKWdsDwDU1NRg1KhRuPbaa/HCCy+0HCNwN1u352q88fnpiDc/P8XFxdi0aROmTJkCwLOen7b0798fe/fuxf79++Hj44P+/fsDAFatWoXa2lrEx8cDAB5//HHk5uaiqKgI//3vf1v+Jq2VlZXhpZdewttvvw3A+vcSHY+O9yoMNg9xeb93ey+01stdvown9Z13dntiY2NRVFSEjIwMbNu2Dbt27cLrr7/ummJtYOv22NOGnDq7Pd78/NTU1OCOO+7Ac889h2uvvbbdNjxRVFQUhg8fjg8++AAAsHnzZiQkJFxx5eyoqKgrHms2m7F9+3acO3cOr7/+OjZt2oS33noLgHdsuz0YbB4gLi4ORUVFLQMnhBAoLCxs+RbWrPWZvwEgPz+/ZZnL7zt79ix69uwpy8UHnbE9vr6+LW/O8PBwPPLIIx2egshVbN2eq/HG5+dqvPX5qa2txa233opp06bhd7/7XcvtnvT8dGTlypVYuXIlkpOT8corr+Ddd98FADz22GPYsmULAKCxsRG9evXCrFmzcPToUfTs2RNJSUl46qmnsHDhQqxatQqrV6/GF198gbKyMjk3xzWu1k8peIzNbZoPDgthPfjd+uBws+aDw60HW7z99ttCCCFqampE9+7dLzn4/Yc//MFt9V+us9tz8eJFYTAYhBBC6PV6cdddd4n/+7//c1v9l7Nle5q1dUzKG5+fZm1tjzc+P7W1teK6664Tzz///BX3edrz42x79uwRI0eObPl96tSpYtasWeK+++4TdXV1lxxn86Jjbhw84umaDw4nJSWJESNGXHJw+PPPP29Z7p133hF9+/YVffr0EY8++mjLh4sQQnz++eeif//+om/fvmLGjBmiurra7dvRrLPbs3nzZjF48GBxzTXXiEGDBomnnnpK6PV6WbZFCNu2R6/Xi549e4rIyEih1WpFz549LxlZ523Pz9W2xxufnyVLlgiNRiOGDh3a8rNkyZKWNjzp+XG2oqIiMWDAgJa/RXp6uggKChJ///vfhRBCZGZmig0bNshZoiPazS2eUouIqAs4duwY3nnnHRQWFmLPnj144IEHsHTpUgDAunXr8M4772DXrl0wm81Qq9XeMJG73eI8rwOZiIicbsiQIVi8eDFOnjyJBx98sCXUAOsx06SkJADWwTWAdw8o4R4bEVEXUlZWhsjISJw/fx45OTmQJAl//etfIUkSxo8fj/3792Pu3LmYMWMGysvLUVVV1XIZHA/DkyATEZH1vJMVFRV44oknUFdXh5iYGOzatQuzZ89Gnz59MGnSpJaTJavVanzwwQeYO3cuYmNjZa7cdtxjIyLqgpr33ADg17/+NRYsWIB+/foBAM6fP4+3334bM2bMwIABAxAQECBnqe3hMTYiIvpZREQEAOD06dP44YcfEBoaCsB6Vpb3338fp06dQlZW1iWhZsOOkEdgVyQRURfUPDgkIiICvXv3hp+fH4qKivD+++8jJycHDz30EG655RZkZmairq4OqampLaff8vSBJdxjI+qk+++/H3/+858vuW3y5MlOO8XUli1bsHDhQqe0RXS5sLAwbNiwAb6+vlixYgXOnDmDW2+9Fbfddhtefvll/POf/8TcuXORlpYGwDtGS3KPjaiTli9fjmHDhmHGjBkYNWoUVq1ahYaGBjz77LNOaX/atGmYNm2aU9oiaktISAjKy8tRWlqKSZMm4e677wYAlJSUICwsDF9//TVuv/12BAUF4cEHH5S52o5xj42ok8LCwrBy5Uo8/PDDyMnJweLFi/Hee++1eZ7BpUuXYtSoURg+fDhSU1Oxb98+AEBWVhZ69eqFvLw8AMA///lPTJkyBUIIrF27FnfddRcA6wU1r7/+egwdOhRDhgzBX/7yF/dtKClaREQEli5dirvvvhtfffUVAGDOnDlobGxEeHg4Nm7cCJPJhMbGRpkrtcHVTksieEotIps98cQTIiQkRKxatardZUpKSlr+f+/evWLw4MEtv3/00UdixIgRYseOHSIhIUGUlpYKIYRYs2aNmDlzphBCiPnz54uXXnqp5THl5eXO3gzq4kpLS8WECRPE+vXrhRBC3HPPPWLTpk1CCCEaGxvlLO1y7eYWuyKJnGThwoXYuHEjHnvssXaXOXToEF566SWUl5dDo9EgMzMTBoMBPj4+uPfee7Fjxw5MnjwZ3333XctQ7NbGjx+PhQsXQqfTYcKECZg0aZIrN4m6oMjISCxfvhxz5syBXq9HYGAg9u7dizvvvBM+Pj5yl2cTdkUSOYlarb7qZU4MBgNmzpyJpUuX4vjx49i5cyeEEDAYDAAAk8mE48ePIzw8HOfOnWuzjZkzZ2L37t3o378/li9fjqlTp7pkW6hrS0lJwZo1a7Br1y6YTCbcc889XjFopBn32IjcRK/Xw2g0Ii4uDgBaLvLYbNGiRejfvz/ee+89TJw4ESNGjGiZMNvs1KlTSExMxIMPPojU1FRcd911bqufupaUlBSsWrUKQgio1Wq5y7ELg43ITYKDg/HCCy8gNTUV8fHxl4x03Lp1K7766iv89NNP8Pf3x2uvvYZZs2Zh7969l7TxySef4MMPP4SPjw+EEFixYoW7N4O6EE+80KoteEotIiLyRjylFhERdQ0MNiIiUhQGGxERKQqDjYiIFIXBRkREisJgIyIiRWGwERGRojDYiIhIURhsRESkKAw2IiJSFAYbEREpCoONiIgUhcFGRESKwmAjIiJFYbAREZGiMNiIiEhRGGxERKQoDDYiIlIUBhsRESkKg42IiBSFwUZERIrCYCMiIkVhsBERkaIw2IiISFEYbEREpCgMNiIiUhQGGxERKQqDjYiIFIXBRkREisJgIyIiRWGwERGRojDYiIhIURhsRESkKAw2IiJSFAYbEREpCoONiIgUhcFGRESKwmAjIiJFYbAREZGiMNiIiEhRGGxERKQoDDYiIlIUBhsRESmKxoZlJJdXQURE5CTcYyMiIkVhsBERkaIw2IiISFEYbEREpCgMNiIiUhQGGxERKQqDjYiIFOX/A/XIhq3DcZg1AAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(0, figsize=(12, 7), dpi=80)\n",
"gtsam_plot.plot_trajectory(0, result, scale=0.1)\n",
"plt.gca().view_init(0, 0)\n",
"plt.gca().set_box_aspect([1,1,1])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"interpreter": {
"hash": "9f7376ced4243bb13dfcffa8a3ba834e0602aa8334cd3a1d8ba8d285f4628083"
},
"kernelspec": {
"display_name": "Python 3.8.12 ('gtbook')",
"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.12"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}