Updates integrated!

This commit is contained in:
Philipp committed 2022-06-30 15:08:31 +02:00
1 parent 51657fca79
commit b542a28c61
5 files changed
+633 -781

No files matched your search

-754
View File
@@ -1,754 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# A suggestion of curse changes for a robot sailboat\n",
"\n",
"## Motivation\n",
"\n",
"The goal of this project is to suggest good points to change the curse of a sailboat while going from point $A$ to point $B$.\n",
"\n",
"This project is done as part of the curse \"Maschienen Learning\" at the University of Applied Sciences South Westphalia. The code labeling the was writen by the team of the [Sailing Team Darmstadt e.V.](https://www.st-darmstadt.de/). A society of stundens whose goal it is to build the [\"roBOOTer\"](https://www.st-darmstadt.de/ueber-uns/boote/prototyp-ii/) a fully autonomous sailboat able to cross the atlantic ocean. A technical challenge that was mastered the first time only a few years ago by [a Norwegian team](http://sailbuoy.no/). I myself am part of the Sailing Team Darmstadt e.V. for nearly 10 years.\n",
"\n",
"One of the challenges to solve is a highly efficient way to find a path over the Ocean. The boot is only 2 meters long and powered by solar energy. That makes power a relatively spares commodity.\n",
"\n",
"## Situation as is\n",
"At the moment the pathfinding algorithm generates a set of more or less random routes to the goal. Each route than gets optimized by a gradient decent moving the curse change points over the ocean to find a path with the lowest cost that can be found by following the highest gradient. This is relatively inefficient since only local minima can be found for each of the randomly generated route. The route with the lowest cost for the so optimized route will be chosen as the final route.\n",
"The idea of this project is to ascertain if it is possible to generate a better initial route through a neural network to give the system a kind of good instinct for the initial routes to reduce optimization steps and the number fo routes that need to be calculated to find a good route. Even tough the initial calculation effort could be high the parallel calculation of 40 routes and lots of optimization steps make it possible that some calculation time and therefore energy can be saved this way.\n",
"The idea of this project is to ascertain if it is possible to generate a better initial route through a neural network to give the system a kind of good instinct for the initial routes to reduce optimization steps and the number fo routes that need to be calculated to find a good route. Even tough the initial calculation effort could be high the parallel calculation of 40 routes and lots of optimization steps make it possible that some calculation time and energy can be saved this way.\n",
"\n",
"## The Project\n",
"\n",
"The goal of this project is to calculate a good first route. That allows for some simplifications of this problem.\n",
"\n",
"Some solutions and assumptions can be made.\n",
"1. The route proposed by this network will not be the final route. This make a somewhat accurate solution good enough.\n",
"2. Since the neural network should not learn how to interpret a specific map but the concept of a map the map can be rotated.\n",
"This allows the wind to come always from north.\n",
"3. Since curse speed is only somewhat proportional to the wind speed a final course may change depending on wind speed not only direction.\n",
"These changes are however somewhat small compared to other influences and can hopefully be ignored since later processing of a proposed route should strait these details out.\n",
"4. When the wind comes always from the same direction (After map orientation by wind) map and route can be mirrored allowing to use all data twice for each route.\n",
"5. Scale does only matter when the curvature of the earth has a significant influence. Allowing for different scaling of the problem for additional training data.\n",
"\n",
"Since there is a solution for this project that only needs some optimisation we can used labeled data to train the network.\n",
"\n",
"### The generell structure\n",
"\n",
"Since"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
},
{
"cell_type": "code",
"execution_count": 451,
"metadata": {
"collapsed": true,
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"from typing import Optional, Union, Any\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"from PIL import ImageDraw, Image\n",
"from shapely.geometry import Polygon, Point\n",
"from shapely.ops import unary_union"
]
},
{
"cell_type": "code",
"execution_count": 452,
"outputs": [],
"source": [
"SIZE_INNER = 75\n",
"SIZE_ROUTE = 100\n",
"MIN_DESTINATION_DISTANCE = 25"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 453,
"outputs": [],
"source": [
"# https://stackoverflow.com/questions/16444719/python-numpy-complex-numbers-is-there-a-function-for-polar-to-rectangular-co\n",
"def polar_to_cartesian(\n",
" radii: np.ndarray,\n",
" angles: np.ndarray,\n",
"):\n",
" \"\"\"Transforms polar coordinates into cartesian coordinates.\n",
"\n",
" Args:\n",
" radii: A array of radii.\n",
" angles: A array of angles.\n",
"\n",
" Returns:\n",
" An array of cartesian coordinates.\n",
" \"\"\"\n",
" return radii * np.exp(2j * angles * np.pi)\n",
"\n",
"\n",
"def cartesian_to_polar(\n",
" x: np.ndarray,\n",
"):\n",
" \"\"\"Transforms cartesian coordinates into polar coordinates.\n",
"\n",
" Args:\n",
" x: A set of complex number to be separated into polar coordinates.\n",
"\n",
" Returns:\n",
" An distance array and an angle array.\n",
" \"\"\"\n",
" return abs(x), np.angle(x)"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 454,
"outputs": [
{
"data": {
"text/plain": "(array('d', [26.73842492254689, 24.737172393549677, 26.02664010787553, 26.73842492254689]),\n array('d', [37.247658792208725, 35.001670575973314, 32.95721707278007, 37.247658792208725]))"
},
"execution_count": 454,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def random_polygon(\n",
" radius_mean: float = 2,\n",
" radius_sigma: float = 1.5,\n",
"):\n",
" \"\"\"Generates the simplest of polygons, a triangle with a size described by a random polygon.\n",
"\n",
" Args:\n",
" radius_mean: The average radius defining a circumcircle of a triangle.\n",
" radius_sigma: The variance of a radius defining a circumcircle of a triangle.\n",
"\n",
" Returns:\n",
" A single triangle.\n",
" \"\"\"\n",
" array = polar_to_cartesian(\n",
" np.random.lognormal(radius_mean, radius_sigma), np.random.rand(3)\n",
" )\n",
" offset = np.random.randint(low=-SIZE_ROUTE, high=SIZE_ROUTE, size=(2,))\n",
" return_values = np.zeros((3, 2), dtype=float)\n",
" # return_values[1, :] = np.real(offset)\n",
" return_values[:] = offset\n",
" return_values[:, :] += np.array((np.real(array), np.imag(array))).T\n",
" return Polygon(return_values)\n",
" # return np.array( + offset[0], np.imag(array) + offset[1])\n",
"\n",
"\n",
"random_polygon().exterior.xy"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 455,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"POLYGON ((-86.43301358227995 93.04181448099787, -74.21505182510836 90.98362331906574, -82.7595147462848 95.20011372852156, -86.43301358227995 93.04181448099787))\n"
]
}
],
"source": [
"print(random_polygon())"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 456,
"outputs": [],
"source": [
"def generate_obstacles(\n",
" seed=None,\n",
" number_of_polygons: int = 50,\n",
" radius_mean: float = 2,\n",
" radius_sigma: float = 1,\n",
"):\n",
" \"\"\"Generates a set of obstacles from a union of triangles.\n",
"\n",
" The union of triangles meas that if polygons overlap o polygon containing the union of those polygons is returned.\n",
" Args:\n",
" seed: A seed to generate a set of obstacles from.\n",
" number_of_polygons: The number of polygons that should be drawn.\n",
" radius_mean: The average radius defining a circumcircle of an obstacle triangle.\n",
" radius_sigma: The variance of a radius defining a circumcircle of an obstacle triangle.\n",
"\n",
" Returns:\n",
" A list of unified obstacles.\n",
" \"\"\"\n",
" if seed is not None:\n",
" np.random.seed(seed)\n",
" polygons = []\n",
" for _ in range(number_of_polygons):\n",
" poly = random_polygon(radius_mean, radius_sigma)\n",
" if poly.contains(Point(0, 0)):\n",
" continue\n",
" polygons.append(poly)\n",
" polygon_list = list(unary_union(polygons).geoms)\n",
" return polygon_list"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 457,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"POINT (-61 31)\n"
]
}
],
"source": [
"def generate_destination(obstacles: list[Polygon], seed: Optional[int] = None) -> Point:\n",
" \"\"\"Generates for a map.\n",
"\n",
" Can be used to generate a valid destination for list of obstacles.\n",
" Args:\n",
" obstacles: A list of obstacles.\n",
" seed: The seed determining the point.\n",
"\n",
" Returns:\n",
" A goal that should be reached by the ship.\n",
" \"\"\"\n",
" # sets the seed\n",
" if seed is not None:\n",
" np.random.seed(seed)\n",
"\n",
" # generates the point\n",
" point: Optional[Point] = None\n",
" while (\n",
" point is None\n",
" or abs(point.x) < MIN_DESTINATION_DISTANCE\n",
" or abs(point.y) < MIN_DESTINATION_DISTANCE\n",
" or any(obstacle.contains(point) for obstacle in obstacles)\n",
" ):\n",
" point = Point(np.random.randint(-SIZE_INNER, SIZE_INNER, size=(2,), dtype=int))\n",
" return point\n",
"\n",
"\n",
"print(generate_destination(generate_obstacles(42), 42))"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 469,
"outputs": [
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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e8Fut2Pjxo3YunUrlixZgkWLFl3aNa6ocgf4VatWFbtduQP8jBkz0KRJk2I/HhGFiJEjJdO9KCVoiyI8nAHej0IiwKekp+Daz6/FtZ9fiwspFy6dT0lP8dlzVKxYEdOmTcNbb70FrTXS09Px8MMPo127dmjRogXef/99AMCRI0fQtWtXtGrVCs2aNcPy5cvx2GOPITExEa1atcLw4cMBALGxsQCAZcuWoVu3bhg4cCAaN26M4cOHXypD+9xzz6Fdu3Zo1qwZxo4dC6015syZg/j4eAwfPhytWrVCYmIiunXrBlehoFmzZqF58+Zo1qwZHn300Uvtj42Nxfjx49GyZUt07NgRR5kMQxR62rSRIGyUjAwgW+eDjBUSAb7/rP747cBv+O3Ab6g+tfql8/1n9ffp89StWxfp6ek4duwYPvjgA5QqVQpr167F2rVrMX36dOzbtw9ffPEFevfujY0bN2LTpk1o1aoVJk+efGk0YObMmXked8OGDXjttdfw999/Y+/evVi5ciUAYNy4cVi7di3++usvJCYm4vvvv8fAgQMRFxeHmTNnYuPGjTm2kz18+DAeffRR/Prrr9i4cSPWrl2LefPmAZB95Dt27IhNmzaha9eumD59uk//N1SI9HSgXDlgzx6zW0Kh7MknJbkuKsqYx09JYQ/ej0IiwLskpiXibPJZJKb5aE1nAX766Sd8+umnaNWqFTp06ICTJ09i165daNeuHT766CNMmDABW7ZsQYkSJQp9rPbt26N69eoICwtDq1atsH//fgDA0qVL0aFDBzRv3hy//vortm7dWuDjrF27Ft26dUOFChUQHh6O4cOH4/fffwcgde779u0LAGjbtu2l5yA/cTolw7h+fWDqVLNbQ6FKKWD2bKBaNSDMgPCQnAz884/vH5fcCokA//XNXyPSFpnjskhbJObcPCefexTP3r17YbPZULFiRWit8eabb2Ljxo3YuHEj9u3bh169eqFr1674/fffUa1aNYwePfrSTnQFicp2NG2z2ZCWloakpCTcfffdmDNnDrZs2YI77rjD4y1l3YmIiLi0va3rOciPSpSQzTwefhho187s1lAoi40FliwBYmKMefx9+4x5XMojJAL8oK8G5ZlvT0lPwcCvBvrsOY4fP4677roL48aNg1IKvXv3xrvvvovU1FQAwM6dO3Hx4kUcOHAAlSpVwh133IExY8Zc2i42IiLi0m094Qrm5cuXx4ULF3LsS59969ns2rdvj99++w0nTpxAeno6Zs2ahSuvvNKbP5t87aWXgC5dzG4Fhbq6dYG5c41ZzsZqdn4TUuvg7eF2RNoifZZc50qMS01NRXh4OEaMGIEHMndKGjNmDPbv3482bdpAa40KFSpg3rxLine truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAfgAAAHiCAYAAAAEZd6CAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAACEqElEQVR4nO3dd3iT1RcH8O/tTrrYe8qUWaAgQ5ChDBVQBBEQREXE9XOLigNRFEUZTkRBVBABFQciUzbKlL33RobQlY6k9/fHaWjapm3GO5PzeZ48bdP0fW+bNOe96xwhpQRjjDHGAkuI3g1gjDHGmPI4wDPGGGMBiAM8Y4wxFoA4wDPGGGMBiAM8Y4wxFoA4wDPGGGMBiAM8Y4wxFoA4wDMWZIQQKS63bCGEzeXrQT4cb6UQYpgabWWM+S5M7wYwxrQlpYxxfi6EOAZgmJRymX4tYoypgXvwjDEAgBAiRAjxohDisBDikhBirhCiVM73ooQQM3PuvyKE2CSEKC+EGAugPYCPc0YAPtb3t2CMOXGAZ4w5PQHgDgA3AagE4D8An+R87z4A8QCqAigNYAQAm5RyFIA1AB6XUsZIKR/XutGMMfc4wDPGnEYAGCWlPCWlzAAwGkBfIUQYgCxQYK8tpXRIKbdIKZN0bCtjrBg8B88Yc6oOYL4QItvlPgeA8gC+BfXevxdClAAwE3QxkKV5KxljHuEePGPM6SSAHlLKEi63KCnlaSlllpTyDSllAwBtAdwOYEjOz3FJSsYMiAM8Y8xpCoCxQojqACCEKCuE6J3zeSchRGMhRCiAJNCQvbOnfx7AdXo0mDFWOA7wjDGnyQB+BbBECJEM4G8AN+R8rwKAH0DBfS+AVaBhe+fP9RVC/CeE+FDbJjPGCiOk5NE1xhhjLNBwD54xxhgLQIoEeCHEdCHEv0KIXS73lRJCLBVCHMz5WDLnfiGE+FAIcUgIsUMI0VyJNjDGGGMsl1I9+BkAuue770UAy6WUdQAsz/kaAHoAqJNzGw7gM4XawBhjjLEcigR4KeVqAJfz3d0bwNc5n38NypDlvP8bSf4GUEIIUVGJdjDGGGOMqDkHX15KeTbn83OgZBkAUBm039bpVM59jDHGGFOIJpnspJRSCOHVcn0hxHDQED6io6Nb1K9fX5W2McZYwNqyhT6GhAAVKgAVebDUTLZs2XJRSlnW159XM8CfF0JUlFKezRmC/zfn/tOglJdOVXLuy0NKORXAVABITEyUmzdvVrGpjDEWYDIygOhowOEAsrOBFi2AX3/Vu1XMC0KI4/78vJpD9L+CKlAh5+MvLvcPyVlN3xrAVZehfMYYY0qw2wEh6PPYWGDoUF2bw7SnSA9eCDEbQEcAZYQQpwC8DmAcgLlCiAcBHAdwd87DFwK4FcAhAGkA7leiDYwxxlzY7TQ0DwCZmUD3/BudWKBTJMBLKQcU8q0ubh4rATymxHkZY4wVwrUH36ULYLXq2x6mOdOWi83KysKpU6eQnp6ud1OCRlRUFKpUqYLw8HC9m8IYK46zB8/D80HLtAH+1KlTiI2NRY0aNSCcV6lMNVJKXLp0CadOnULNmjX1bg5jrDh2O92ys4EePfRuDdOBaXPRp6eno3Tp0hzcNSKEQOnSpXnEhDGzsNuBrCzgppuAmBi9W8N0YNoAD4CDu8b4782Yidjt9JGH54OWqQO8EZw6dQq9e/dGnTp1UKtWLTz55JPIzMzEjBkz8Pjjj3t8nEmTJiEtLc2nNqxcuRK33367Tz8b9L77Dli0SO9WMKY8hwOIiABuu03vljCdBE6Ar1CBVowqdatQodhTSinRp08f3HHHHTh48CAOHDiAlJQUjBo1yuvm+xPgmY/sduDJJ4EdO/RuCWPKq1sXuHwZiIvTuyVMJ4ET4M+f1/x4f/75J6KionD//bSVPzQ0FBMnTsT06dORlpaGkydPomPHjqhTpw7eeOMNAEBqaipuu+02NG3aFI0aNcKcOXPw4Ycf4syZM+jUqRM6deoEAHjkkUeQmJiIhg0b4vXXX792zk2bNqFt27Zo2rQpWrVqheTk5DxtSk1NxQMPPIBWrVqhWbNm+OWXX8AK8dNPwMWLQO3aereEMXVER+vdAqYj066iN4Ldu3ejRYsWee6Li4tDtWrVYLfbsXHjRuzatQtWqxUtW7bEbbfdhuPHj6NSpUr4/fffAQBXr15FfHw8JkyYgBUrVqBMmTIAgLFjx6JUqVJwOBzo0qULduzYgfr166N///6YM2cOWrZsiaSkJFgsljznHzt2LDp37ozp06fjypUraNWqFW6++WZE8z96QW++SR+vu07fdjDGmAoCpwdvQLfccgtKly4Ni8WCPn36YO3atWjcuDGWLl2KkSNHYs2aNYiPj3f7s3PnzkXz5s3RrFkz7N69G3v27MH+/ftRsWJFtGzZEgBdTISF5b1GW7JkCcaNG4eEhAR07NgR6enpOHHihOq/q+ls2AAcOQKEhnKAZ4wFJO7B+6FBgwb44Ycf8tyXlJSEEydOICwsrMCqcyEE6tati61bt2LhwoV45ZVX0KVLF7z22mt5Hnf06FG8//772LRpE0qWLImhQ4d6vD1NSokff/wR9erV8++XC3RjxwJpabR9iOcoGWMBiHvwfujSpQvS0tLwzTffAAAcDgeeffZZDB06FFarFUuXLsXly5dhs9nw888/o127djhz5gysVivuvfdePP/889i6dSsAIDY29tp8elJSEqKjoxEfH4/z58/jjz/+AADUq1cPZ8+exaZNmwAAycnJsDu3wuTo1q0bPvroI1BGYOCff/7R5G9hKqdOAUuX0udVqujbFsYYUwkHeD8IITB//nzMmzcPderUQd26dREVFYW3334bANCqVSvcddddaNKkCe666y4kJiZi586daNWqFRISEvDGG2/glVdeAQAMHz4c3bt3R6dOndC0aVM0a9YM9evXx8CBA9GuXTsAQEREBObMmYMnnngCTZs2xS233FKgZ//qq68iKysLTZo0QcOGDfHqq69q+0cxgwkTKLsXANSpo29bGGNMJcLZ0zMyd/Xg9+7di+uvvz73jgoVlF1JX748cO6ccscLEAX+7maTmkrPbWoqff3SS0DOBRljjBmJEGKLlDLR158PnDl4DsbMEzNm5H4eHU17hRljLADxED0LHtnZwDvv5PbeeQU9YyyAcYBnwWPxYuDq1dyvs7KAWrX0aw9jjKkocIboGSvOmDFASkru11lZQMWK+rXHYPbt24fbevdBVr6dGfm9+PxzeHTEcI1axZgb1aoBJ08W/v0ZM4D77tOsOUbFAZ4Fh927ge3b895XvjwQwoNYTvv27cMVGYXITg8V+pi0/euwZt06DvBMP9nZQLduwNGjVDcEyK0h4vy8QQP92mcgHOBZcHjnHSAzM+99NWvq0xYDC4uMRkSZaoV+P+P0PgBXNGsPYwWEhABffKF3K0yBuy9+CA0NRUJCAho2bIimTZvigw8+QLZzf7WX3s63Vatt27Y+t2vGjBk4c+bMta+HDRuGPXv2+Hw807twAfjxRyqf6aphQ33awxhjGuAA7weLxYJt27Zh9+7dWLp0Kf74449rVeO8lT/Ar1+/3ud25Q/wX375JRoE85DVJ58UvC8yEjDzfn7GGCtGUAT4TEcmeszsgR4zeyAlM+Xa55mOzOJ/2EPlypXD1KlT8fHHH0NKCYfDgeeffx4tW7ZEkyZN8PnnnwMAzp49iw4dOiAhIQGNGjXCmjVr8OKLL8JmsyEhIQGDBg0CAMTExAAAVq5ciY4dO6Jv376oX78+Bg0adC0N7ZgxY9CyZUs0atQIw4cPh5QSP/zwAzZv3oxBgwYhISEBNpsNHTt2hDNR0OzZs9G4cWM0atQII0eOvNb+mJgYjBo1Ck2bNkXr1q1xXunyu3rJzAQmTwby5/KPjOQV9IyxgBYUAb737N5YdXwVVh1fhSoTqlz7vPfs3oqe57rrroPD4cC///6LadOmIT4+Hps2bcKmTZvwxRdf4OjRo/juu+/QrVs3bNu2Ddu3b0dCQgLGjRt3bTRg1qxZBY77zz//YNKkSdizZw+OHDmCdevWAQAef/xxbNq0Cbt27YLNZsOCBQvQt29fJCYmYtasWdi2bVuecrJnzpzByJEj8eeff2Lbtm3YtGkTfv75ZwBUR75169bYvn07OnTogC8CZY5rzhzA3arw7GzeA88YC2hBEeCdbHYbrmZchc1uU/1cS5YswTfffIOEhATccMMNuHTpEg4ePIiWLVviq6++wujRo7Fz507ExsYWe6xWrVqhSpUqCAkJQUJCAo4dOwYAWLFiBW644QY0btwYf/75J3bv3l3kcTZt2oSOHTuibNmyCAsLw6BBg7B69WoAlOf+9ttvBwC0aNHi2jlMTUqq+e66Nc7JZuNFdoyxgBYUAX7e3fMQERqR576I0Aj8cPcPhfyEb44cOYLQ0FCUK1cOUkp89NFH2LZtG7Zt24ajR4+ia9eu6NChA1avXo3KlStj6NCh1yrRFSUyMvLa56GhobDb7UhPT8ejjz6KH374ATt37sRDDz3kcUlZd8LDw6+Vt3Wew/TWrgVc1iLkERsLuIxuMMZYoAmKAN9vbr8C8+2Zjkz0ndtXsXNcuHABI0aMwOOPPw4hBLp164bPPvsMWVlZAIADBw4gNTUVx48fR/ny5fHQQw9h2LBh18rFhoeHX3usJ5zBvEyZMkhJSclTl9619KyrVq1aYdWqVbh48SIcDgdmz56Nm266yZ9f29jefDM3LW1+Vatq2xbGGNNYUO2Dt4RZEBEaodjiOufCuKysLISFhWHw4MF45plnANDWtGPHjqF58+aQUqJs2bL4+eefsXLlSowfPx7h4eGIiYm51oMfPnw4mjRpgubNm7udh8+vRIkSeOihh9CoUSNUqFABLVu2vPa9oUOHYsSIEbBYLPjrr7+u3V+xYkWMGzcOnTp1gpQSt912G3r3VnYdgmEcOQKsWVP49+vV064Line truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAfgAAAHiCAYAAAAEZd6CAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAACFk0lEQVR4nO3dd3jTVRcH8O9tupKWTdl7yShQoCCibGQqS5GpIApuVIaAOFBEBUV9UUFREBFEEUUR2coGkYLI3hsKlNmVtml73z9OQ9M2bbN/I+fzPH3apml6unJ+995zzxVSSjDGGGNMXwKUDoAxxhhjnscJnjHGGNMhTvCMMcaYDnGCZ4wxxnSIEzxjjDGmQ5zgGWOMMR3iBM8YY4zpECd4xvyMECLR5iVTCGG2eX+wC4+3UQjxpDdiZYy5LlDpABhjviWlDLe+LYQ4A+BJKeV65SJijHkDj+AZYwAAIUSAEGKCEOKkEOK6EGKJEKJk1sdChRALs26/JYTYJYQoK4SYCqA1gM+yZgA+U/a7YIxZcYJnjFm9AKA3gLYAKgC4CeDzrI8NBVAMQGUApQA8DcAspZwEYAuA56WU4VLK530dNGPMPk7wjDGrpwFMklJekFKmApgM4GEhRCAACyix15JSZkgpd0sp4xWMlTFWCF6DZ4xZVQWwTAiRaXNbBoCyAL4Djd5/EEIUB7AQdDFg8XmUjDGH8AieMWZ1HkA3KWVxm5dQKeVFKaVFSvmWlLI+gFYAHgDwWNbn8ZGUjKkQJ3jGmNUXAKYKIaoCgBAiQgjRK+vt9kKIhkIIA4B40JS9daR/BUANJQJmjOWPEzxjzOp/AJYDWCuESADwN4C7sz5WDsBSUHI/DGATaNre+nkPCyFuCiFm+jZkxlh+hJQ8u8YYY4zpDY/gGWOMMR3ySIIXQswTQlwVQhywua2kEGKdEOJ41usSWbcLIcRMIcQJIcQ+IURTT8TAGGOMsWyeGsHPB9A1120TAPwppawN4M+s9wGgG4DaWS8jAcz2UAyMMcYYy+KRBC+l3AzgRq6bewH4Nuvtb0Edsqy3L5DkbwDFhRDlPREHY4wxxog31+DLSiljs96+DGqWAQAVQfttrS5k3cYYY4wxD/FJJzsppRRCOFWuL4QYCZrCR1hYWLO6det6JTbGGGNMjXbv3n1NShnh6ud7M8FfEUKUl1LGZk3BX826/SKo5aVVpazbcpBSzgEwBwCio6NlTEyMF0NljDHG1EUIcdadz/fmFP1y0AlUyHr9m83tj2VV07cEcNtmKp8xxhhjHuCREbwQYjGAdgBKCyEuAHgTwPsAlgghngBwFsAjWXdfCaA7gBMAkgE87okYGGOMMZbNIwleSjkwnw91tHNfCeA5T3xdxhhjjNnHx8Uy12VkAPHxwK1b2S+3b2e/ffMmcPUqEBcHXL9O78fHA4mJwHvvAU88oWj4jDGmZ5zgmevGjwdmzABCQ4HgYEAIQEpK/BYLkJaW93MCAoCyZYEOHXwfL2OM+RFO8Mx1EyYAly4Bv/1GI/PCBAUBlSsDW7cC5bm3EWOMeRMfNsNcV7o08P33wJo1QLVqgMmU/31DQoC6dYFduzi5M8aYD3CCZ+677z7g2DFg0iRK8gZDzo8bjUCzZsD27UDJksrEyBhjfoYTPPOMoCDg1VeBQ4eAdu2yR/MmE9C2LfDXX0B4uKIhMsaYP+EEzzyralVg/Xpg0SKgXDmgd2/g999pip4xxpjPcJEd847evemFMcaYIngEzxhjjOkQJ3jGGGNMhzjBM8YYYzrECZ4xxhjTIU7wjDHGmA5xgtcrKZWOgDHGmII4weuFlMDhw8D77wONGtEBMF9/rXRUjDHGFML74PXg77+BPn2Ay5epTWxGBt3+4ovAwYN04lsAX8sxxpg/4QSvB5UqAc88A+zZQ61iz53LTuiffAKcOQMsW6ZkhEwDjhw5gh69+sKSnl7g/SaMG4tnnx7po6gYY67iBK8HlSoBb7yR/b6UdIzr0aPAkSPcJpY55MiRI7glQxHSfkS+90k+ug1btm3jBM+YBnCC1yMhgIoV6aVDB6WjYRoSGBKG4NJV8v146sUjAG75LB7GmOt4YZYxxhjTIU7wjDHGmA5xgmeMMcZ0iBM8Y4wxpkOc4BljjDEd4gTPGGOM6RAneMYYY0yHOMEzxhhjOsQJnjHGGNMhTvCMMcaYDnGCZ4wxxnSIEzxjjOmFEMDGjUpHwVSCEzxjjOnJhg1KR8BUghM8Y4zpCSd4loUTPGOM6cmWLUpHwFSCEzxjjOlFu3ZKR8BUhBM8Y4zpRfv2SkfAVIQTPGOM6UWbNvTaYlE2DqYKgUoHwBjzrfj4eCQnJ+e5/ebNmw59vjnZjMuXL+e53WAwICIiwu34mBtq1KDXZ84AtWsrGgpTHid4xvxMo6bRuHLlKgyBef/9w6O6Ffi5QaUqYt0f36NWvcg8HzMn3MLhQ4dQp04dj8XKnFS+PL0+fJgTPOMEz5i/qV+/ARJqdUGRqK5Of25opQYIfWp+ntvTE65Bfvciqlat6oEImcuCguj15s1Az57KxsIUx2vwjPmZ4Y8NRsDpHR59zOSj2/Bgz54ICQnx6OMyF61fr3QE+jNxInUK1BBO8Iz5me7duyPp4jFkJDm25u4IcWo7Hn90sMcej7khJAT47z+lo9Cf7t3pdWamsnE4gRM8Y37GZDKha/fuSD66zSOPZ7l1GZabsejQoYNHHo+5qW1bpSPQp/vuo9erVysbhxM4wTPmhx5/dDDEqe0eeayUo1vRt29fBFnXf5myrM1u0tIUDUN3rNPz06YpG4cTOMEz5oc6d+6MlLhzSI+/5vZjyZPbMXTIIA9ExTzCulXu9Gll49CjevWogFEjOMEz5odCQkLwYM+eSD7qXt9yy/ULkMk30cbaYIUpr1Ilen38uLJx6NH48fRaSmXjcJBXE7wQ4i4hxF6bl3ghxEtCiMlCiIs2t3f3ZhyMsbw8MU2fcnQL+j/SHwaDwUNRMbdVrkyvjx1TNg496t+fXh88qGwcDvJqgpdSHpVSRkkpowA0A5AMYFnWhz+2fkxKudKbcTDG8urQoQPSb1+F5VbernSOkFIi8+R2PDZkoIcjY26xNrvZu1fRMHQpNJRez5ihbBwO8uUUfUcAJ6WUZ334NRlj+QgMDETfvn1hPuLaNL3l2lkEZaahZcuWHo6MucW22Q3zvJAQYP58paNwiC8T/AAAi23ef14IsU8IMU8IUSL3nYUQI4UQMUKImLi4ON9FyZgfGfboYMDFafrUI1swcGB/BARwKY/qFC0KnOWxlFdY1+E1wCf/mUKIYAA9AfyUddNsADUBRAGIBZBnvkNKOUdKGS2ljOYDLBjzjvvuuw8w34bl+nmnPk9KifQT2/DYYK6eV6Vmzeh1Sopj9//xR6B3b2DECODNN4Hr170WmuY99RS91sA2RF9dencDsEdKeQUApJRXpJQZUspMAF8BaOGjOBhjNgwGA/r374+Uo1ud+ry0yycQFhKIpk2beiky5pa77qLXp045dv/AQGDFCuDrr4GpU4GOHR2/OPA3FSoAZjMQHKx0JIXyVYIfCJvpeSFEeZuP9QFwwEdxMMZyeWzwQGSc2AbpxNYfy/GteHTwQAiN9eb2G9a98I5ulXvoIWDdOiA8HMjIAI4eBR55RFNtWX3KWmyncl5P8EKIMAD3A/jF5ubpQoj9Qoh9ANoDeNnbcTDG7GvZsiWCkQ5LnGONUaTMROqxbXiUp+d9Kz4euOng+QGubJVr3x7Ytg0oWZKmn//8Exg71vk4mWp4PcFLKZOklKWklLdtbntUStlQStlIStlTShnr7TgKpZHGBYx5mhACQwYNQKqD0/SpF4+gVPGiiIzMeyY886Lhw4Hnn3fsvtYEv3+/c1+jUSPg33/p8y0W4IsvgNmznXsMphpc/grQH3L9+sB55wqNGNOLIYMGIv24Y9P06ce3YuijPHr3uagoYPFi4OTJwu9r7WbnSkOWKlWAPXuAyEggPR14+WVg1SrnH4cpjhM8QPtG69QBXn1V6UgYU0STJk0QbgpB2uWC12xlZgZSjm3H4IHc3MbnGjakmcaJEwu/b4UK9NqRiwF7SpYEtm8HOnWi6fo+ffgIWg3iBG81ahTw/ffAkSNKR8KYzwkh8NigAUg7VvA0fer5g6hQoTzq1Knjo8jYHfXrU+X2779TEVxBgoKAIkWA27eB5GTXvl5oKH2tJ54AUlOBDh2AixddeyymCE7wVu3bA+XKAaNHKx0JY4oYMngQ0o5tA+1etS/9xFY8zifHKaNGDRrBp6UBEyYUfv+qVem1q6N4ADAYgDlzgHfeAW7coKNoExJcfzzmU5zgrQICaBS/ahUQE6N0NIz5XIMGDVC6VAmkXjxs9+MyIx3JR7dj4MABPo6MAaBkW7EibV1bswY4dKjg+3//PRAdnd261lVCAJMmUXvWU6eAHj1obZ6pHid4W088Qf9Eo0YpHQljihg2ZBDSj22z+7GUs/+hRs2aqFatmm+DYtmsOxdSU4FXXin4vg0bArt2AXXreuZrDx1KA6Bdu4Ann+SdRxrACd5W6dLAgw8CO3YAf/2ldDSM+dyggQNgPrYNMjMjz8cyTmzF8McGKxAVu6N5cxqEZGbSc9S+fb79+p07U/HdypXAN9/49mszp3GCz826Bv/CC3yFyvxO7dq1UalSRaScy7l/WqZbkHR8J/o/8ohCkWmIlLT11hsiI4GwMHo7JQUYN847X6cgTZrQKP7hh33/tZlTOMHndt991OTh0CFg2bLC78+Yzgx/dDAyTuScpjef3o369SNRsWJFhaJSmcxM4Nw5GkV/9RUNDO6/H6heHTAaHdvK5ooGDbLbx0oJbNlCe9Z9rWpVOrGOqRon+NyEoH9WIajBQ0beqUrG9GzAgP5IPrYDMiO7kEqe3I4nhvrx9LyUwBtvAG3bUhOZkBCgXj2gb1/gpZeAjz8G1q+nI1p796aiNG+oWTPnITALine truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAfgAAAHiCAYAAAAEZd6CAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAACXOUlEQVR4nO2dd3xT5ffHP0+ajiQte29kiGyhIA6WoGxB9hYcqAg/98QBKg5woLjAhQtE4MsQHAwBWSqggOw9CmXIamk60uT5/XEakrZpmyY3uSPn/XrdV5Kb5OZk3c/znOcMIaUEwzAMwzDGwqS2AQzDMAzDKA8LPMMwDMMYEBZ4hmEYhjEgLPAMwzAMY0BY4BmGYRjGgLDAMwzDMIwBYYFnGIZhGAPCAs8wEYYQ4orX5hJCpHvdHhbA8dYIIe4Nha0MwwSOWW0DGIYJL1LKePd1IcRRAPdKKVeqZxHDMKGAZ/AMwwAAhBAmIcQzQohDQojzQogfhBBlcu6LE0J8m7P/khBisxCiohBiMoC2AD7I8QB8oO67YBjGDQs8wzBuxgPoA6A9gCoALgL4MOe+uwCUBFAdQFkADwBIl1JOALAOwDgpZbyUcly4jWYYxjcs8AzDuHkAwAQpZZKUMhPARAD9hRBmAA6QsNeVUjqllFullCkq2sowTBHwGjzDMG5qAlgohHB57XMCqAjgG9Ds/XshRCkA34IGA46wW8kwjF/wDJ5hGDcnAHSTUpby2uKklCellA4p5SQpZUMANwHoCWBkzvO4JSXDaBAWeIZh3HwCYLIQoiYACCHKCyF651zvKIRoIoSIApACctm7Z/pnAFyjhsEMwxQMCzzDMG7eA7AEwHIhRCqAPwDckHNfJQDzQeK+B8BakNve/bz+QoiLQoj3w2sywzAFIaRk7xrDMAzDGA2ewTMMwzCMAVFE4IUQXwghzgohdnrtKyOEWCGEOJBzWTpnvxBCvC+EOCiE2CGEaKGEDQzDMAzDeFBqBj8LQNc8+54BsEpKWQ/AqpzbANANQL2cbQyAjxWygWEYhmGYHBQReCnl7wAu5NndG8BXOde/AlXIcu//WhJ/ACglhKishB0MwzAMwxChXIOvKKVMzrl+GlQsAwCqgvJt3STl7GMYhmEYRiHCUslOSimFEMUK1xdCjAG58GGz2Vo2aNAgeEMyMoDUVKB8+eCPFYk4HMCpU8D583SbMzByIwRQqRJQuTJdZwInMxM4fJj+sy5X0Y9niofJBNSqBZQunXu/y0X3MZpg69at/0kpAxasUAr8GSFEZSllco4L/mzO/pOgkpduquXsy4WUciaAmQCQmJgot2zZEpw1v/0G9OoFtGgBrFsX3LEijZMngYkTgW+/BZxOFvaCkBK4fJlOkF9+Cdx2m9oW6Q+nE3j7bfq9ZWayuIcKlwu4dAnYtg1ISKB9+/YBzZsDP/xA50pGdYQQx4J5fiiHaktAHaiQc7nYa//InGj6NgAue7nyQ8PHHwM9ewLp6cBzz4X0pQxFUhJw771A3brAV1/RbMrBpccLxW6nAVGfPvSbS0pS2yL9sGsXCcykSfRfZXEPLXY78Mwznts1agBZWUD//sDixQU/j9EPUsqgNwBzACSDylcmAbgH1HlqFYADAFYCKJPzWAFqQXkIwL8AEos6fsuWLWVAZGdLOXaslFarlICUVapI6XQGdqxI4vhxKe++W8q4OCmjo+mz4634m9lMv73XXpMyK0vtb1W7ZGVJ+eKLUlosUgqh/vcWSZvFIuW2bZ7vonZt2h8dTedPRlUAbJEycG1WxEUvpRxSwF2dfDxWAnhIidctlNRU4I47gL/+opGqzQY89RSvLxXGiRPASy8Bc+aQq5Rn68GRnU3bq68CM2YAs2YBHTqobZW2+OcfYNAg8nqkp6ttTeSRng6MGEGuepMJaNMGOHIEaNQIiIpS2zomSIypdseOkatv0yYSd4DGq3ffrapZmuXECfps6tendXZ2xSuL3U6/yR49gL59gdOn1bZIfTIygCeeAG6+GThwwPM/ZcLP4cPAp5/S9bZt6fKh0M/BmNBjPIHftAlo1gw4epSCdADAbAZGjvQEkzAEC3t4sduBpUsppuGdd2h2H4ls2kS/uY8+4lm7FkhLo8HWuXNA69Z0nhwwQG2rGAUwlsB/8w3QuTNFMnsH6JjNwOOPq2eX1jh+HBg9moVdDRwOOqG++CLQoAGwcaPaFoWPtDTgwQeBTp1ocMnirh2ysoBx44CWLYGUFKBkSbUtYhTAGALvclE06AMP+Hb1tWlDs6ZI59gx4K67gGuvBb77joVdTdLSgEOHaEA6ZAjNnozMb78BdepQNgYLu/bIyiLvEqcQGwr9C7zdTsF006f7Fvf4eE6NA8gdes015OVgYdcO6enA//5H382HH1Jwo5G4fJmWx3r2BM6cYXHXMnY7fVd8bjAM+hb45GQgMRFYtargIJ3SpWmWFOm0aQM8/zwweDBdr14diIuj5YuEBHLJ2WycZaAGWVnAlSvA008DjRsDmzerbZEyLF1KA5cffmBh1wtnzwJTpqhtBaMQgrLWtI3PSnb//EOVwi5fLjhYyWYD3nyTI0ILIzWVUpSSkmg7cQI4eJAia5OSyHWckQFYLJQ243TSydpoM00tYbFQkNO77wJlyqhtTfE5fx4YMwb45ReOjtcjViuwezdQs6balkQ8QoitUsrEgJ+vS4FfuBAYPrzok4fVSiNSmy20Bhqd9PT8g4BDh2hLSqLP+MoVEiazmWIi0tMjN0pcCWJjaXv7bcp00ItnZd484L776PvPylLbGiYQoqKoXsPKlWpbEvEEK/BhaTajGFICkycDr71WtMsvOppOjCzuwWOxUJBiYYGKmZm0ZOIeBBw/Tl6AQ4doQHDmDEXnxsXRd+Ny0XNYBHyTmUnbI48A778PfP011XbQKqdPU2bG77/zrF3vOJ3AH39QudrevdW2hgkC/czgN2ygCPAff/TvBBIXR26m2rVDbyDjHw4HCYF7EJCURIOAgwdpQHDmDDXAiImhTUqP0EU6FgtVHJsyRVspTFJSZPz48fQ9cYCWcShfnqra8SRJNSLDRd+8udwSFQXs2eN/sE7nzsCKFaE1jFEep5Nc/t6DgKNHqdrZsWM0QLhwgZYCYmKoLWtmJsUJGJ3YWBq4vv8+ib3aLWlPnaIUvy1beNZuRCwW4P77KRaEUYXIEPjoaLlFCP9nB/HxwJIlQMeOoTWMUQcpKfgv7yBg2jT6jdhsJPomEwmi+7djFBGy2ahIzqxZFHWvFl9+ScF0HGthXCwWyupo1EhtSyKSyBB4IWSxusHXqkWuX7VnOEx4adCAelonJAAXL1KGhfcg4NgxWg44coRmn//9R7EAcXE0GMjOpkGADv4TEILsvuceiklRowyzy0Xr7vPnG2fwxORGCOD668lLw+fTsBNZQXb+YLMBzz7LP8ZIpGlTEviuXSkSuEwZ2po2Lfg5KSm5BwEbNwKffw7ceCMNAs6epdl/XBwdMztbG73KpSQ7PvsMmD2bChkNHBje373JRLN4l4uK9bDIGw8p6T81axYN5hhdYbwZfHw8BWtZraE0idEiU6ZQsZh584D+/QM7htNJ7v9KlTz7rlwpulZAerqncJAatQJsNhrIfPkllSIOJy4Xpa0uXswib1RKlCDPlx7rMugYdtF7ExNDRW3eeSfUJjFaZNkySuu5cIFOSOEkPZ1m/AXVCjhzJvS1AkwmCsQbOxaYNCm80c8uFzBsGMW+sMgbj9hY8hB9/bXalkQULPDexMWRO6lGjVCbxGiRK1eAbduAW25R2xLfZGXlrhXgPQhw1wq4fNlTK0BKyg4obq0Ai4U8WTNmAH36+O2237t3L3r07gtHEYOOZ558AmMfGJP/DqcTGDqUStSyyBsPi4XKgt94o9qWRAws8N506wb89FOozWGY0JGd7btWwKFDnjTBS5doABATQ88pqFaAzUa9Gj7/nDq5FcGiRYtwz1MvI7bdfQU+xr5vA7rVisKcb77y/QCnk/od/PQTi7wRqVMH2LuXvFBMyOEgOzfu4DqG0TNmM1CtGm0F4XIVXisgOZmWKbKygLVrgeuuo0s/Zl7mWBtiyhXsAcs8uRfApYIPEBUFfP891dL/9VcWeaORnEx58U8+qbYljB8YR+ArVdKua5ZhlMRkot97pUo0Q/eFlNT0xT0ACGe+fFQUdZAbMABYvpxF3kjY7cDEiVTgqLBBKKMJ9NHBoqhGG/HxwIQJnBrHMG6EAMqVo/r1PXuGP0/ebKZshs6dOaPFaGRlUYEjRvPoQ+CvuYbScEqWJDHPu/4jBI0oGYbRDmYzsGABcOutFKDFGIPsbFry+eUXtS1hikAfAl+yJPDNN7Su+NtvwBNPUBOZuDhK33jgAbrOMIy2MJupCE7HjizyRsJuB0aN8r83CKMK+hB4NyYT0KoV8PrrFFm8bx/w6afknmcYRptERwOLFgHt27PIG4mUFKq3wGgWfQl8XmrUoK5aWmqfyTBMfqKjqQhOu3Ys8kYhPZ06G+7fr7YlTAHoW+AZhtEPbpG/5RYWeaOQmQmMHKmPBk0RCAs8wzDhIyaGKt3ddBOLvBFwuYCdO4E5c9S2hPEBCzzDMOElJob6Btx4I4u8EUhLox4gly6pbQmTBxZ4hmHCT2wslbO94QbOgDEC6emU3cRoChZ4hmHUITYW+PlnFnkjkJkJzJ4NbPG7sTcTBljgGYZRj7g4KpjSqhWLvN5JT6eCZE6n2pYwObDAMwyjLnFxVLO+ZUsWeb2TlAR8+KHaVjA5sMAzDKM+cXHAihXA9dezyOuZtDTgueeorTGjOizwDMNoA4sFWLmSGuSwyOuXrCzgwQfVtoIBCzzDMFrCagVWrQKaNmWR1ysOBy25rFqltiURDws8wzDawmqlplJNmlCkPaM/7Hbgrrsoup5RDRZ4hmG0h80GrF4NNG7MIq9XLl4EXntNbSsiGnPRD2EYxkikpKTAbrfn23/Line truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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c9fmzcDs2UD//v45PoUG13UdSgG1awMTJ5rWHApdmzdvRteuXYtcV6lSJTRq1Ah5eXlYsWIFNm3aBKvVim7duuHKK6/E/v37Ua9ePfzyyy8AgLNnz6Jy5cp46623MG/ePNSoUQMAMH78eFSrVg0OhwP9+vXDhg0b0KZNGwwZMgRTpkxBt27dkJaWBovFUuT5x48fj0suuQSffvopzpw5g+7du6N///5ITEwMzC/FC+Eb4LUG1q2ThWBTpgB79kjv3LlyvPgwtdUK3HIL8MEHQFQYDWysWwcMHeq/4A7I73TMGFlwF06jHuS+7Gy5OFmtwMyZQHKyeW2isDVgwABUr14dADB48GAsWrQIV1xxBR599FE8+eSTuOqqq9CrV69SH/vtt99i4sSJyMvLw5EjR7BlyxYopVC3bl1069YNgJxMFDdz5kxMnz4db7zxBgDZbXDgwAGcd955fnqVvgvfAP/DD8DNN0ugz82V63JySr+v1Qrcc4/Mw4dTgDp40PftcJ4819SpwI03+v+5KPgcPw4kJMiUjcUio2CsAEleatu2LaZOnVrkurS0NBw4cAAxMTElVp0rpdCqVSusWbMGv/76K5599ln069cP//znP4vcb+/evXjjjTewcuVKVK1aFbfffrvb29O01vj+++/RunVr315cAIVRV7WY7t2lJ+4M7mWxWoHHHwfefDO8gnt6OnDJJbIrIBAyM6XKXHnFaih8HT0q01pWq6xtGTzY7BZRCOvXrx9sNhu+/PJLAIDD4cCjjz6K22+/HVarFbNmzcKpU6dgt9vx008/oWfPnjh8+DCsVituueUWPP7441izZg0AIDk5+dx8elpaGhITE1G5cmUcPXoUv/32GwCgdevWOHLkCFauXAkASE9PR16xz7JLL70U7777LpzJ4dauXRuQ34UvwjfAN2woc8LlBW2LRbb0PP98wJoVEHl5wNVXG7cdzl2nTwOffRa456PgceyYnFSmpLAYEflMKYUff/wR3333HVq2bIlWrVohISEBL730EgCge/fuuP7669GxY0dcf/31SE1NxcaNG9G9e3ekpKRg3LhxePbZZwEAo0ePxmWXXYa+ffuiU6dO6Ny5M9q0aYObb74ZPXv2BADExcVhypQpeOCBB9CpUycMGDCgRM/+ueeeQ25uLjp27Ih27drhueeeC+wvxQvhnap22TIJ8qUNUVss0mu/917fGxhMtAZGjQImTzZ+xbw7qlWTTHnx8YF/bjLPr7/K/9KaNbLVlELW1q1bi84r16lj7Er62rULt1TSOSV+72CxmfL16AE0aSKrvF1ZLMCHHwIjRpjSLL966y3/B3eLRRYsArKwyuEAqlaVD4JOnQpvo8hxxRXA3r3htUCVBINxyArvAA8Azz4rPdqMDPnZYgG++CI8F4P99JPs5/d2xXxUlPx+YmJk+2BWllxXo4bkC2jaFGjRQgrMNGggl/r15fZwWr9A3mFwJwoq4R/gr79eMrgBsgDo22+BK680t03+sHo1MHx42cE9JkaCd1SUzNFnZcnPNWtKoHYG74YNJWg7g3cp20WIiCj4hX+Aj40FHn1UFtNNny7bxsKN1nIik5MjQTsnRwJz7doSsJs3B5o1K9rrrldPtjURFdi2bRuuHDQYuRXshHjq8cdw3z2jA9QqIvJW+Ad4AHj6aUmnGq5JN5SSPej5+RLAa9cOr0x8FBDbtm3DGZ2A+L6jyryPbftiLFy8mAGeKARERoBXKnyDu1Oq1wstic6JiU9EXI1GZd6efWgbgDMBaw8ReY+rYoiIKKhER0cjJSUF7dq1Q6dOnfDmm28i37VuiAece+edLrzwQq/b9fnnn+Pw4cPnfr7rrruwZcsWr4/nbwzwREQUVCwWC9atW4fNmzdj1qxZ+O23385VjfNU8QC/ZMkSr9tVPMB/8sknaNu2rdfH8zcGeCIi8kqOIweX/+9yXP6/y5GRk3Hu+xxHGXU/vFCrVi1MnDgR7733HrTWcDgcePzxx9GtWzd07NgRH330EQDgyJEj6N27N1JSUtC+fXssXLgQTz31FOx2O1JSUjB8+HAAQFJSEgBg/vz56NOnD2644Qa0adMGw4cPP5eG9oUXXkC3bt3Qvn17jB49GlprTJ06FatWrcLw4cORkpICu92OPn36wJmEbfLkyejQoQPat2+PJ5988lz7k5KSMHbsWHTq1Ak9evTAUaPL75aDAZ6IiLwyaPIgLNi/AAv2L0CDtxqc+37Q5EGGPk+zZs3gcDhw7Ngx/Pe//0XlypWxcuVKrFy5Eh9//DH27t2Lr7/+GpdeeinWrVuH9evXIyUlBa+88sq50YBJkyaVOO7atWsxYcIEbNmyBXv27MHixYsBAGPGjMHKlSuxadMm2O12zJgxAzfccANSU1MxadIkrFu3rkg52cOHD+PJJ5/E3LlzsW7dOqxcuRI//fQTAKkj36NHD6xfvx69e/fGxx9/bOjvpjwM8ERE5BN7nh1ns8/CnufHstQFZs6ciS+//BIpKSk4//zzcfLkSezcuRPdunXDZ599hueffx4bN25EshsLq7t3744GDRogKioKKSkp2LdvHwBLine truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"def plot_situation(\n",
" obstacles: list[Polygon],\n",
" destination: Point,\n",
" obstacle_color: Optional[str] = None,\n",
" legend: bool = True,\n",
") -> None:\n",
" \"\"\"PLots the obstacles into a matplotlib plot.\n",
"\n",
" Args:\n",
" obstacles: A list of obstacles.\n",
" destination: The destination that should be reached by the boat.\n",
" obstacle_color: The color the obstacles should have. Can be None.\n",
" If none all obstacles will have different colors.\n",
" legend: If true plots a legend.\n",
" Returns:\n",
" None\n",
" \"\"\"\n",
" plt.figure(figsize=(8, 8))\n",
" plt.axis([-SIZE_ROUTE, SIZE_ROUTE, -SIZE_ROUTE, SIZE_ROUTE])\n",
" plt.title(\"Test\")\n",
" for polygon in obstacles:\n",
" if obstacle_color is not None:\n",
" plt.fill(*polygon.exterior.xy, color=obstacle_color, label=\"Obstacle\")\n",
" else:\n",
" plt.fill(*polygon.exterior.xy)\n",
" plt.scatter(*destination.xy, marker=\"X\", color=\"green\", label=\"Destination\")\n",
" plt.scatter(0, 0, marker=\"o\", color=\"green\", label=\"Start\")\n",
" # https://www.geeksforgeeks.org/matplotlib-pyplot-arrow-in-python/\n",
" plt.arrow(\n",
" 0,\n",
" int(SIZE_ROUTE * 0.9),\n",
" 0,\n",
" -int(SIZE_ROUTE * 0.1),\n",
" head_width=10,\n",
" width=4,\n",
" label=\"wind (3Bft)\",\n",
" )\n",
" if legend:\n",
" # https://stackoverflow.com/questions/13588920/stop-matplotlib-repeating-labels-in-legend\n",
" handles, labels = plt.gca().get_legend_handles_labels()\n",
" by_label = dict(zip(labels, handles))\n",
" plt.legend(by_label.values(), by_label.keys())\n",
" plt.show()\n",
"\n",
"\n",
"for s in range(20):\n",
" o = generate_obstacles(s)\n",
" plot_situation(o, generate_destination(o, s), \"RED\")"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 459,
"outputs": [
{
"data": {
"text/plain": "<PIL.Image.Image image mode=RGB size=200x200>",
"image/png": "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\n"
},
"execution_count": 459,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def generate_image_from_map(\n",
" obstacles: list[Polygon], destination: Point, solution\n",
") -> Image:\n",
" \"\"\"Generate an image from the map.\n",
"\n",
" Can be used to feed an ANN.\n",
" - Obstacles are marked as reed.\n",
" - The destination is marked as green.\n",
" - The points where the route will likely change are blue.\n",
"\n",
" Args:\n",
" obstacles: A list of obstacles as shapely Polygons.\n",
" destination: A destination that should be navigated to.\n",
" \"\"\"\n",
" img = Image.new(\n",
" \"RGB\",\n",
" (SIZE_ROUTE * 2, SIZE_ROUTE * 2),\n",
" \"#ffffff\",\n",
" )\n",
" draw = ImageDraw.Draw(img)\n",
" for polygon in obstacles:\n",
" draw.polygon(\n",
" list(np.dstack(polygon.exterior.xy).reshape((-1)) + SIZE_ROUTE),\n",
" fill=\"#FF0000\",\n",
" outline=\"#FF0000\",\n",
" )\n",
" img.putpixel((int(destination.x) + 100, int(destination.y) + 100), (0, 0xFF, 0))\n",
" return img\n",
"\n",
"\n",
"o = generate_obstacles(42)\n",
"g = generate_destination(o, 42)\n",
"og_img = generate_image_from_map(o, g, None)\n",
"og_img"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 460,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.97 ms ± 24.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
"source": [
"def generate_all_to_series(\n",
" seed: Optional[int] = None, image: bool = False\n",
") -> pd.Series:\n",
" \"\"\"Generates everything and aggregates all data into a `pd:Series`.\n",
"\n",
" Args:\n",
" seed:The seed that should be used to generate map and destination.\n",
" image: If an image should be generated or if that should be postponed to save memory.\n",
" Returns:\n",
" Contains a `pd.Series`containing the following.\n",
" - The seed tha generated the map.\n",
" - The destination in x\n",
" - The destination in y\n",
" - A list of Obstacle polygons.\n",
" - The route generated for this map by the roBOOTer navigation system.\n",
" - Optionally the image containing all the information. Can be generated at a later date without the fear for a loss of accuracy.\n",
" \"\"\"\n",
" obstacles = generate_obstacles(seed)\n",
" destination = generate_destination(obstacles, seed)\n",
"\n",
" return pd.Series(\n",
" data={\n",
" \"seed\": str(seed),\n",
" \"obstacles\": obstacles,\n",
" \"destination_x\": destination.x,\n",
" \"destination_y\": destination.y,\n",
" \"image\": generate_image_from_map(obstacles, destination, None)\n",
" if image\n",
" else pd.NA,\n",
" }\n",
" )\n",
"\n",
"\n",
"%timeit generate_all_to_series()"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 461,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7.09 s ± 161 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
},
{
"data": {
"text/plain": " obstacles destination_x \\\nseed \n0 [POLYGON ((-93.1050012242828 -66.3114919371247... -28.0 \n1 [POLYGON ((-81.48957922766184 -77.835510803987... -38.0 \n2 [POLYGON ((-85.70808367996737 -96.461421605594... -53.0 \n3 [POLYGON ((-72.36680200571271 -83.042653386020... -75.0 \n4 [POLYGON ((-49.01542037068429 -91.156604355820... 47.0 \n... ... ... \n995 [POLYGON ((-50.76852976356937 -111.76285175833... 53.0 \n996 [POLYGON ((-72.9562194541358 -97.5919820487205... -66.0 \n997 [POLYGON ((-40.30122912398245 -93.905261647772... 41.0 \n998 [POLYGON ((-107.12872081817716 -106.2700055400... -45.0 \n999 [POLYGON ((-65.09067978612013 -95.812774257958... -59.0 \n\n destination_y image \nseed \n0 42.0 <NA> \n1 65.0 <NA> \n2 -32.0 <NA> \n3 -54.0 <NA> \n4 54.0 <NA> \n... ... ... \n995 52.0 <NA> \n996 73.0 <NA> \n997 51.0 <NA> \n998 64.0 <NA> \n999 42.0 <NA> \n\n[1000 rows x 4 columns]",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>obstacles</th>\n <th>destination_x</th>\n <th>destination_y</th>\n <th>image</th>\n </tr>\n <tr>\n <th>seed</th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>[POLYGON ((-93.1050012242828 -66.3114919371247...</td>\n <td>-28.0</td>\n <td>42.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>1</th>\n <td>[POLYGON ((-81.48957922766184 -77.835510803987...</td>\n <td>-38.0</td>\n <td>65.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>2</th>\n <td>[POLYGON ((-85.70808367996737 -96.461421605594...</td>\n <td>-53.0</td>\n <td>-32.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>3</th>\n <td>[POLYGON ((-72.36680200571271 -83.042653386020...</td>\n <td>-75.0</td>\n <td>-54.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>4</th>\n <td>[POLYGON ((-49.01542037068429 -91.156604355820...</td>\n <td>47.0</td>\n <td>54.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>995</th>\n <td>[POLYGON ((-50.76852976356937 -111.76285175833...</td>\n <td>53.0</td>\n <td>52.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>996</th>\n <td>[POLYGON ((-72.9562194541358 -97.5919820487205...</td>\n <td>-66.0</td>\n <td>73.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>997</th>\n <td>[POLYGON ((-40.30122912398245 -93.905261647772...</td>\n <td>41.0</td>\n <td>51.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>998</th>\n <td>[POLYGON ((-107.12872081817716 -106.2700055400...</td>\n <td>-45.0</td>\n <td>64.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>999</th>\n <td>[POLYGON ((-65.09067978612013 -95.812774257958...</td>\n <td>-59.0</td>\n <td>42.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n </tbody>\n</table>\n<p>1000 rows × 4 columns</p>\n</div>"
},
"execution_count": 461,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%timeit pd.DataFrame([generate_all_to_series(i) for i in range(1000)]).set_index(\"seed\")\n",
"df = pd.DataFrame([generate_all_to_series(i) for i in range(1000)]).set_index(\"seed\")\n",
"df.to_pickle(\"test.pickle\")\n",
"df"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 462,
"outputs": [
{
"data": {
"text/plain": " obstacles destination_x \\\nseed \n0 [POLYGON ((-93.1050012242828 -66.3114919371247... -28.0 \n1 [POLYGON ((-81.48957922766184 -77.835510803987... -38.0 \n2 [POLYGON ((-85.70808367996737 -96.461421605594... -53.0 \n3 [POLYGON ((-72.36680200571271 -83.042653386020... -75.0 \n4 [POLYGON ((-49.01542037068429 -91.156604355820... 47.0 \n... ... ... \n995 [POLYGON ((-50.76852976356937 -111.76285175833... 53.0 \n996 [POLYGON ((-72.9562194541358 -97.5919820487205... -66.0 \n997 [POLYGON ((-40.30122912398245 -93.905261647772... 41.0 \n998 [POLYGON ((-107.12872081817716 -106.2700055400... -45.0 \n999 [POLYGON ((-65.09067978612013 -95.812774257958... -59.0 \n\n destination_y image \nseed \n0 42.0 <NA> \n1 65.0 <NA> \n2 -32.0 <NA> \n3 -54.0 <NA> \n4 54.0 <NA> \n... ... ... \n995 52.0 <NA> \n996 73.0 <NA> \n997 51.0 <NA> \n998 64.0 <NA> \n999 42.0 <NA> \n\n[1000 rows x 4 columns]",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>obstacles</th>\n <th>destination_x</th>\n <th>destination_y</th>\n <th>image</th>\n </tr>\n <tr>\n <th>seed</th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>[POLYGON ((-93.1050012242828 -66.3114919371247...</td>\n <td>-28.0</td>\n <td>42.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>1</th>\n <td>[POLYGON ((-81.48957922766184 -77.835510803987...</td>\n <td>-38.0</td>\n <td>65.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>2</th>\n <td>[POLYGON ((-85.70808367996737 -96.461421605594...</td>\n <td>-53.0</td>\n <td>-32.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>3</th>\n <td>[POLYGON ((-72.36680200571271 -83.042653386020...</td>\n <td>-75.0</td>\n <td>-54.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>4</th>\n <td>[POLYGON ((-49.01542037068429 -91.156604355820...</td>\n <td>47.0</td>\n <td>54.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>995</th>\n <td>[POLYGON ((-50.76852976356937 -111.76285175833...</td>\n <td>53.0</td>\n <td>52.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>996</th>\n <td>[POLYGON ((-72.9562194541358 -97.5919820487205...</td>\n <td>-66.0</td>\n <td>73.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>997</th>\n <td>[POLYGON ((-40.30122912398245 -93.905261647772...</td>\n <td>41.0</td>\n <td>51.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>998</th>\n <td>[POLYGON ((-107.12872081817716 -106.2700055400...</td>\n <td>-45.0</td>\n <td>64.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n <tr>\n <th>999</th>\n <td>[POLYGON ((-65.09067978612013 -95.812774257958...</td>\n <td>-59.0</td>\n <td>42.0</td>\n <td>&lt;NA&gt;</td>\n </tr>\n </tbody>\n</table>\n<p>1000 rows × 4 columns</p>\n</div>"
},
"execution_count": 462,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2 = pd.read_pickle(\"test.pickle\")\n",
"df2"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "markdown",
"source": [
"https://programtalk.com/python-examples/PIL.ImageDraw.Draw.polygon/)\n",
"https://stackoverflow.com/questions/3654289/scipy-create-2d-polygon-mask"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
View File
Whitespace-only changes.
+632
View File
@@ -0,0 +1,632 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# A suggestion of curse changes for a robot sailboat\n",
"\n",
"## Motivation\n",
"\n",
"The goal of this project is to suggest good points to change the curse of a sailboat while going from point $A$ to point $B$.\n",
"\n",
"This project is done as part of the curse \"Maschienen Learning\" at the University of Applied Sciences South Westphalia. The code labeling the was writen by the team of the [Sailing Team Darmstadt e.V.](https://www.st-darmstadt.de/). A society of stundens whose goal it is to build the [\"roBOOTer\"](https://www.st-darmstadt.de/ueber-uns/boote/prototyp-ii/) a fully autonomous sailboat able to cross the atlantic ocean. A technical challenge that was mastered the first time only a few years ago by [a Norwegian team](http://sailbuoy.no/). I myself am part of the Sailing Team Darmstadt e.V. for nearly 10 years.\n",
"\n",
"One of the challenges to solve is a highly efficient way to find a path over the Ocean. The boot is only 2 meters long and powered by solar energy. That makes power a relatively spares commodity.\n",
"\n",
"## Situation as is\n",
"At the moment the pathfinding algorithm generates a set of more or less random routes to the goal. Each route than gets optimized by a gradient decent moving the curse change points over the ocean to find a path with the lowest cost that can be found by following the highest gradient. This is relatively inefficient since only local minima can be found for each of the randomly generated route. The route with the lowest cost for the so optimized route will be chosen as the final route.\n",
"The idea of this project is to ascertain if it is possible to generate a better initial route through a neural network to give the system a kind of good instinct for the initial routes to reduce optimization steps and the number fo routes that need to be calculated to find a good route. Even tough the initial calculation effort could be high the parallel calculation of 40 routes and lots of optimization steps make it possible that some calculation time and therefore energy can be saved this way.\n",
"The idea of this project is to ascertain if it is possible to generate a better initial route through a neural network to give the system a kind of good instinct for the initial routes to reduce optimization steps and the number fo routes that need to be calculated to find a good route. Even tough the initial calculation effort could be high the parallel calculation of 40 routes and lots of optimization steps make it possible that some calculation time and energy can be saved this way.\n",
"\n",
"## The Project\n",
"\n",
"The goal of this project is to calculate a good first route. That allows for some simplifications of this problem.\n",
"\n",
"Some solutions and assumptions can be made.\n",
"1. The route proposed by this network will not be the final route. This make a somewhat accurate solution good enough.\n",
"2. Since the neural network should not learn how to interpret a specific map but the concept of a map the map can be rotated.\n",
"This allows the wind to come always from north.\n",
"3. Since curse speed is only somewhat proportional to the wind speed a final course may change depending on wind speed not only direction.\n",
"These changes are however somewhat small compared to other influences and can hopefully be ignored since later processing of a proposed route should strait these details out.\n",
"4. When the wind comes always from the same direction (After map orientation by wind) map and route can be mirrored allowing to use all data twice for each route.\n",
"5. Scale does only matter when the curvature of the earth has a significant influence. Allowing for different scaling of the problem for additional training data.\n",
"\n",
"Since there is a solution for this project that only needs some optimisation we can used labeled data to train the network.\n",
"\n",
"### The generell structure\n",
"\n",
"Since"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"pycharm": {
"name": "#%%\n",
"is_executing": true
}
},
"outputs": [],
"source": [
"from typing import Optional\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"from PIL import ImageDraw, Image\n",
"from shapely.geometry import Polygon, Point\n",
"from shapely.ops import unary_union"
]
},
{
"cell_type": "code",
"execution_count": 76,
"outputs": [],
"source": [
"SIZE_INNER = 75\n",
"SIZE_ROUTE = 100\n",
"MIN_DESTINATION_DISTANCE = 25"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 77,
"outputs": [],
"source": [
"# https://stackoverflow.com/questions/16444719/python-numpy-complex-numbers-is-there-a-function-for-polar-to-rectangular-co\n",
"def polar_to_cartesian(\n",
" radii: np.ndarray,\n",
" angles: np.ndarray,\n",
"):\n",
" \"\"\"Transforms polar coordinates into cartesian coordinates.\n",
"\n",
" Args:\n",
" radii: A array of radii.\n",
" angles: A array of angles.\n",
"\n",
" Returns:\n",
" An array of cartesian coordinates.\n",
" \"\"\"\n",
" return radii * np.exp(2j * angles * np.pi)\n",
"\n",
"\n",
"def cartesian_to_polar(\n",
" x: np.ndarray,\n",
"):\n",
" \"\"\"Transforms cartesian coordinates into polar coordinates.\n",
"\n",
" Args:\n",
" x: A set of complex number to be separated into polar coordinates.\n",
"\n",
" Returns:\n",
" An distance array and an angle array.\n",
" \"\"\"\n",
" return abs(x), np.angle(x)"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 78,
"outputs": [
{
"data": {
"text/plain": "(array('d', [58.14925495607776, 57.991505776535874, 57.76398376244, 56.384785221067744, 55.81452229141463, 56.285256940049436, 56.785512495130604, 58.14925495607776]),\n array('d', [-62.57469140842694, -62.279867618259566, -62.04187518408968, -61.94019571244569, -62.6896502705296, -63.99539776490992, -64.20651127735718, -62.57469140842694]))"
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def random_polygon(\n",
" radius_mean: float = 2,\n",
" radius_sigma: float = 1.5,\n",
"):\n",
" \"\"\"Generates the simplest of polygons, a triangle with a size described by a random polygon.\n",
"\n",
" Args:\n",
" radius_mean: The average radius defining a circumcircle of a triangle.\n",
" radius_sigma: The variance of a radius defining a circumcircle of a triangle.\n",
"\n",
" Returns:\n",
" A single triangle.\n",
" \"\"\"\n",
" number_of_corners = np.random.randint(3, 10)\n",
" array = polar_to_cartesian(\n",
" np.random.lognormal(radius_mean, radius_sigma),\n",
" np.sort(np.random.rand(number_of_corners)),\n",
" )\n",
" offset = np.random.randint(low=-SIZE_ROUTE, high=SIZE_ROUTE, size=(2,))\n",
" return_values = np.zeros((number_of_corners, 2), dtype=float)\n",
" # return_values[1, :] = np.real(offset)\n",
" return_values[:] = offset\n",
" return_values[:, :] += np.array((np.real(array), np.imag(array))).T\n",
" return Polygon(return_values)\n",
" # return np.array( + offset[0], np.imag(array) + offset[1])\n",
"\n",
"\n",
"random_polygon().exterior.xy"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 79,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"POLYGON ((64.24234834022612 114.96629329424587, 62.58155390362512 115.71472980681563, -73.35243626054171 120.99282453832782, -193.33402301375247 -80.4360840218972, 64.24234834022612 114.96629329424587))\n"
]
}
],
"source": [
"print(random_polygon())"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 80,
"outputs": [],
"source": [
"def generate_obstacles(\n",
" seed=None,\n",
" number_of_polygons: int = 40,\n",
" radius_mean: float = 2,\n",
" radius_sigma: float = 1,\n",
"):\n",
" \"\"\"Generates a set of obstacles from a union of triangles.\n",
"\n",
" The union of triangles meas that if polygons overlap o polygon containing the union of those polygons is returned.\n",
" Args:\n",
" seed: A seed to generate a set of obstacles from.\n",
" number_of_polygons: The number of polygons that should be drawn.\n",
" radius_mean: The average radius defining a circumcircle of an obstacle triangle.\n",
" radius_sigma: The variance of a radius defining a circumcircle of an obstacle triangle.\n",
"\n",
" Returns:\n",
" A list of unified obstacles.\n",
" \"\"\"\n",
" if seed is not None:\n",
" np.random.seed(seed)\n",
" polygons = []\n",
" for _ in range(number_of_polygons):\n",
" poly = random_polygon(radius_mean, radius_sigma)\n",
" if poly.contains(Point(0, 0)):\n",
" continue\n",
" polygons.append(poly)\n",
" polygon_list = list(unary_union(polygons).geoms)\n",
" return polygon_list"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 81,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"POINT (-61 31)\n"
]
}
],
"source": [
"def generate_destination(obstacles: list[Polygon], seed: Optional[int] = None) -> Point:\n",
" \"\"\"Generates for a map.\n",
"\n",
" Can be used to generate a valid destination for list of obstacles.\n",
" Args:\n",
" obstacles: A list of obstacles.\n",
" seed: The seed determining the point.\n",
"\n",
" Returns:\n",
" A goal that should be reached by the ship.\n",
" \"\"\"\n",
" # sets the seed\n",
" if seed is not None:\n",
" np.random.seed(seed)\n",
"\n",
" # generates the point\n",
" point: Optional[Point] = None\n",
" while (\n",
" point is None\n",
" or abs(point.x) < MIN_DESTINATION_DISTANCE\n",
" or abs(point.y) < MIN_DESTINATION_DISTANCE\n",
" or any(obstacle.contains(point) for obstacle in obstacles)\n",
" ):\n",
" point = Point(np.random.randint(-SIZE_INNER, SIZE_INNER, size=(2,), dtype=int))\n",
" return point\n",
"\n",
"\n",
"print(generate_destination(generate_obstacles(42), 42))"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 82,
"outputs": [
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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JSQlJdEjPZ2BXbuydtUqmjVrxv/+9z8Adu3aRZ06dXjmmWeYOnUqDRo0AGDUqFHUr1+f/Px8+vfvz6JFi2jfvj3nn38+H374IT169GD37t0kJibu9/ijRo3i+OOP56233mLnzp307NmTE044geTk5ND8UapBW/ButW6dq2eOKhdbswYGD4Yjj4Tp0yMruYMsjfv3v52OIqKdeOKJpKamkpiYyNnnnMMPf/5J586dmTx5MnfddRczZ86kTp06pd73o48+onv37nTr1o2lS5eybNkyfv/9d5o2bUqPHj0A+TARE7N/+/fbb79l9OjRpKWl0bdvX7Kysli3bl3Qf9ea0ATvRp9/DoccAuef772ZySp8bd0K110na44/+0xmxkfih8z27eXDjQqaDh06MG/evP2O7d69m3Xr1hETE1Ni1rmpW5d2HTowf/58OnfuzH333cfDDz9c4rx//vknTz31FN9//z2LFi1i4MCBlV6eZq3lk08+YcGCBSxYsIB169ZxeJivv9cE7zbr1sHQofL9F19Av35wwFiRUgGVkSHjzYccAm+9JbPi8/KcjsoZKSnwyCNOR+F5/fv3x+fz8e677wKQn5/PbbfdxrBhw0hKSmLy5Mls374dv9/PxIkT6d27Nxs2bCApKYmLLrqIO+64g/nz5wNQq1atvePpu3fvJjk5mTp16rBp0ya++uorAA477DA2btzInDlzANizZw95B/yPDxgwgBdeeIGi8u6//vprSP4WNaEJ3k1yc+G00/Z1ifr9MHcu9Oghe2crFUg5OfD887Lk7amn5P/O5euNa6xRI9lkRgWVMYZPP/2Ujz/+mLZt29KuXTsSEhJ49NFHAejZsyfnnHMOXbp04ZxzziE9PZ3FixfTs2dP0tLSeOihh7jvvvsAGD58OCeffDL9+vWja9eudOvWjfbt23PhhRfSu3dvAOLi4vjwww+54YYb6Nq1KyeeeGKJlv39999Pbm4uXbp0oWPHjtx///2h/aNUg2424yY33ihrjA8c84yJkYIPM2ZAu3bOxKa8o6BASsreequ03iNhVnxlpKTAK6/IagEPW758+f5dz02aBHYmfePG2iApRYm/O7rZTGT58MPSx9zz8mQdaI8e8M03cNRRoY9NuZ+18O23UnrVLVu3hlJiIgwZ4nQUoafJ2LW0i95NFi+Gc8+VN5oDWQu7d0P//jBpUuhjU+72yy8yceycc2THN03u+0tOhvvuk94ypVxCE7ybNGokG3bMmAGdO8ubzoF8PmllvPpq6ONT7vP773DKKdC3L8yZo4m9LFFRcOWVTkehVJVognej9HRYsABeekk2ukhI2P96v1/GT++9NzKXMamK/f03XHyxVKD79lvw+/kNaBObQIu4xHIvL0dFWCs2IUHK7yYlOR2JUlUSYa9UD4mKgksvhbPPhgcekBZ7drZMkAJJ8s89B2vXwjvvaNeiEjt2SJGWV1+VuRvF5nT8BuxMPZj4gbeUeXff7z8y8+cJXFcQQcvkjIGbb3Y6CqWqTFvwblerFjzzDCxcCMcdt3+3vc8Hn34KJ56oXa+Rzu+HRx+Fgw+WmeBlbN8aE5tAXIMWZV6iU1IdCN5BsbFwySX7tiVVykU0wXtF27YwZQp8/LHscFXUnej3w+zZMoFqyxZnY1Shl5cHr70ma9lHjZIPel7dvjUYoqNlqEuFVHR0NGlpaXTs2JGuXbvy9NNPU1DUO1lFRWvni/Tq1avacb399tts2LBh789XXnkly5Ytq/b5gk0TvNeccgqsXg333y9JPjZWuu5//13GW1etcjpCFQrWwiefQKtWMh9j+/bIqxlfU1FRMHAgtGjhdCQRJzExkQULFrB06VImT57MV199xUMPPVStcx2Y4GfNmlXtuA5M8G+88QYdOnSo9vmCTRO8F8XFwd13w8qVsmd1YqK05DZuhCOOkOp3yrumTZNVFpdeCuvX6/BMdcXHw4MPOh1FWMvJz+GU90/hlPdPISMnY+/3Ofk5AXuMRo0a8dprr/Hiiy9irSU/P5877riDHj160KVLF/7zn/8AsHHjRvr06UNaWhqdOnVi5syZ3H333fj9ftLS0hhaWOI7JSUFgGnTptG3b18GDx5M+/btGTp06N4ytA8//DA9evSgU6dODB8+HGstEyZMYO7cuQwdOpS0tDT8fj99+/alqAjb+PHj6dy5M506deKuu+7aG39KSgojR46ka9euHHXUUWwK9Pa75dAE72VNm0pxnKlTZYOQpCTYtUvG6gtrMCsPWbQI+vSRVufSpZrYa+rII6FTJ6ejCGuDxg9i+trpTF87nebPNN/7/aDxgwL6OK1btyY/P5/Nmzfz5ptvUqdOHebMmcOcOXN4/fXX+fPPPxk3bhwDBgxgwYIFLFy4kLS0NEaPHr23N2Ds2LElzvvrr7/y7LPPsmzZMlavXs2PP/4IwIgRI5gzZw5LlizB7/fzxRdfMHjwYNLT0xk7diwLFizYbzvZDRs2cNdddzFlyhQWLFjAnDlzmDhxIiD7yB911FEsXLiQPn368Prrrwf0b1MeTfCR4MgjYckSmVVfp4502Z92mmwcoryjf3/Line truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 576x576 with 1 Axes>",
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"def plot_situation(\n",
" obstacles: list[Polygon],\n",
" destination: Point,\n",
" obstacle_color: Optional[str] = None,\n",
" legend: bool = True,\n",
") -> None:\n",
" \"\"\"PLots the obstacles into a matplotlib plot.\n",
"\n",
" Args:\n",
" obstacles: A list of obstacles.\n",
" destination: The destination that should be reached by the boat.\n",
" obstacle_color: The color the obstacles should have. Can be None.\n",
" If none all obstacles will have different colors.\n",
" legend: If true plots a legend.\n",
" Returns:\n",
" None\n",
" \"\"\"\n",
" plt.figure(figsize=(8, 8))\n",
" plt.axis([-SIZE_ROUTE, SIZE_ROUTE, -SIZE_ROUTE, SIZE_ROUTE])\n",
" plt.title(\"Test\")\n",
" for polygon in obstacles:\n",
" if obstacle_color is not None:\n",
" plt.fill(*polygon.exterior.xy, color=obstacle_color, label=\"Obstacle\")\n",
" else:\n",
" plt.fill(*polygon.exterior.xy)\n",
" plt.scatter(*destination.xy, marker=\"X\", color=\"green\", label=\"Destination\")\n",
" plt.scatter(0, 0, marker=\"o\", color=\"green\", label=\"Start\")\n",
" # https://www.geeksforgeeks.org/matplotlib-pyplot-arrow-in-python/\n",
" plt.arrow(\n",
" 0,\n",
" int(SIZE_ROUTE * 0.9),\n",
" 0,\n",
" -int(SIZE_ROUTE * 0.1),\n",
" head_width=10,\n",
" width=4,\n",
" label=\"Wind (3Bft)\",\n",
" )\n",
" if legend:\n",
" # https://stackoverflow.com/questions/13588920/stop-matplotlib-repeating-labels-in-legend\n",
" handles, labels = plt.gca().get_legend_handles_labels()\n",
" by_label = dict(zip(labels, handles))\n",
" plt.legend(by_label.values(), by_label.keys())\n",
" plt.show()\n",
"\n",
"\n",
"for s in range(5):\n",
" o = generate_obstacles(s)\n",
" plot_situation(o, generate_destination(o, s), \"RED\")"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 83,
"outputs": [
{
"data": {
"text/plain": "<PIL.Image.Image image mode=RGB size=200x200>",
"image/png": "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\n"
},
"execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def generate_image_from_map(\n",
" obstacles: list[Polygon], destination: Point, solution: list[Point]\n",
") -> Image:\n",
" \"\"\"Generate an image from the map.\n",
"\n",
" Can be used to feed an ANN.\n",
" - Obstacles are marked as reed.\n",
" - The destination is marked as green.\n",
" - The points where the route will likely change are blue.\n",
"\n",
" Args:\n",
" obstacles: A list of obstacles as shapely Polygons.\n",
" destination: A destination that should be navigated to.\n",
" \"\"\"\n",
" img = Image.new(\n",
" \"RGB\",\n",
" (SIZE_ROUTE * 2, SIZE_ROUTE * 2),\n",
" \"#ffffff\",\n",
" )\n",
" draw = ImageDraw.Draw(img)\n",
" for polygon in obstacles:\n",
" draw.polygon(\n",
" list(np.dstack(polygon.exterior.xy).reshape((-1)) + SIZE_ROUTE),\n",
" fill=\"#FF0000\",\n",
" outline=\"#FF0000\",\n",
" )\n",
" img.putpixel((int(destination.x) + 100, int(destination.y) + 100), (0, 0xFF, 0))\n",
" return img\n",
"\n",
"\n",
"o = generate_obstacles(42)\n",
"g = generate_destination(o, 42)\n",
"og_img = generate_image_from_map(o, g, None)\n",
"og_img"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 84,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.39 ms ± 209 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
"source": [
"def generate_all_to_series(\n",
" seed: Optional[int] = None, image: bool = False\n",
") -> pd.Series:\n",
" \"\"\"Generates everything and aggregates all data into a `pd:Series`.\n",
"\n",
" Args:\n",
" seed:The seed that should be used to generate map and destination.\n",
" image: If an image should be generated or if that should be postponed to save memory.\n",
" Returns:\n",
" Contains a `pd.Series`containing the following.\n",
" - The seed tha generated the map.\n",
" - The destination in x\n",
" - The destination in y\n",
" - A list of Obstacle polygons.\n",
" - The route generated for this map by the roBOOTer navigation system.\n",
" - Optionally the image containing all the information. Can be generated at a later date without the fear for a loss of accuracy.\n",
" \"\"\"\n",
" obstacles = generate_obstacles(seed)\n",
" destination = generate_destination(obstacles, seed)\n",
"\n",
" return pd.Series(\n",
" data={\n",
" \"seed\": str(seed),\n",
" \"obstacles\": obstacles,\n",
" \"destination_x\": destination.x,\n",
" \"destination_y\": destination.y,\n",
" \"image\": generate_image_from_map(obstacles, destination, None)\n",
" if image\n",
" else pd.NA,\n",
" \"route\": None,\n",
" }\n",
" )\n",
"\n",
"\n",
"%timeit generate_all_to_series()"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 85,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.22 s ± 197 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
},
{
"data": {
"text/plain": " obstacles destination_x \\\nseed \n0 [POLYGON ((-17.62168766659423 -98.369266220295... -66.0 \n1 [POLYGON ((-97.82715137072381 -82.221167700698... -38.0 \n2 [POLYGON ((-46.23706006792075 -76.756994820638... 73.0 \n3 [POLYGON ((-7.4210414351932155 -83.11109606339... 31.0 \n4 [POLYGON ((-77.97638439917915 -70.239097296919... 47.0 \n... ... ... \n995 [POLYGON ((-58.363834699771374 -78.10250502922... 53.0 \n996 [POLYGON ((-45.38105849246964 -86.568664678920... -66.0 \n997 [POLYGON ((-82.90222667221566 -92.864813148784... 41.0 \n998 [POLYGON ((-37.1039416590347 -88.1790371955828... -45.0 \n999 [POLYGON ((-119.59353826736813 -30.54685916387... 74.0 \n\n destination_y image route \nseed \n0 -54.0 <NA> None \n1 65.0 <NA> None \n2 49.0 <NA> None \n3 56.0 <NA> None \n4 54.0 <NA> None \n... ... ... ... \n995 52.0 <NA> None \n996 73.0 <NA> None \n997 51.0 <NA> None \n998 64.0 <NA> None \n999 -25.0 <NA> None \n\n[1000 rows x 5 columns]",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>obstacles</th>\n <th>destination_x</th>\n <th>destination_y</th>\n <th>image</th>\n <th>route</th>\n </tr>\n <tr>\n <th>seed</th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>[POLYGON ((-17.62168766659423 -98.369266220295...</td>\n <td>-66.0</td>\n <td>-54.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>1</th>\n <td>[POLYGON ((-97.82715137072381 -82.221167700698...</td>\n <td>-38.0</td>\n <td>65.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>2</th>\n <td>[POLYGON ((-46.23706006792075 -76.756994820638...</td>\n <td>73.0</td>\n <td>49.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>3</th>\n <td>[POLYGON ((-7.4210414351932155 -83.11109606339...</td>\n <td>31.0</td>\n <td>56.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>4</th>\n <td>[POLYGON ((-77.97638439917915 -70.239097296919...</td>\n <td>47.0</td>\n <td>54.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>995</th>\n <td>[POLYGON ((-58.363834699771374 -78.10250502922...</td>\n <td>53.0</td>\n <td>52.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>996</th>\n <td>[POLYGON ((-45.38105849246964 -86.568664678920...</td>\n <td>-66.0</td>\n <td>73.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>997</th>\n <td>[POLYGON ((-82.90222667221566 -92.864813148784...</td>\n <td>41.0</td>\n <td>51.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>998</th>\n <td>[POLYGON ((-37.1039416590347 -88.1790371955828...</td>\n <td>-45.0</td>\n <td>64.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>999</th>\n <td>[POLYGON ((-119.59353826736813 -30.54685916387...</td>\n <td>74.0</td>\n <td>-25.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n </tbody>\n</table>\n<p>1000 rows × 5 columns</p>\n</div>"
},
"execution_count": 85,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%timeit pd.DataFrame([generate_all_to_series(i) for i in range(1000)]).set_index(\"seed\")\n",
"df = pd.DataFrame([generate_all_to_series(i) for i in range(1000)]).set_index(\"seed\")\n",
"df.to_pickle(\"test.pickle\")\n",
"df"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 86,
"outputs": [
{
"data": {
"text/plain": " obstacles destination_x \\\nseed \n0 [POLYGON ((-17.62168766659423 -98.369266220295... -66.0 \n1 [POLYGON ((-97.82715137072381 -82.221167700698... -38.0 \n2 [POLYGON ((-46.23706006792075 -76.756994820638... 73.0 \n3 [POLYGON ((-7.4210414351932155 -83.11109606339... 31.0 \n4 [POLYGON ((-77.97638439917915 -70.239097296919... 47.0 \n... ... ... \n995 [POLYGON ((-58.363834699771374 -78.10250502922... 53.0 \n996 [POLYGON ((-45.38105849246964 -86.568664678920... -66.0 \n997 [POLYGON ((-82.90222667221566 -92.864813148784... 41.0 \n998 [POLYGON ((-37.1039416590347 -88.1790371955828... -45.0 \n999 [POLYGON ((-119.59353826736813 -30.54685916387... 74.0 \n\n destination_y image route \nseed \n0 -54.0 <NA> None \n1 65.0 <NA> None \n2 49.0 <NA> None \n3 56.0 <NA> None \n4 54.0 <NA> None \n... ... ... ... \n995 52.0 <NA> None \n996 73.0 <NA> None \n997 51.0 <NA> None \n998 64.0 <NA> None \n999 -25.0 <NA> None \n\n[1000 rows x 5 columns]",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>obstacles</th>\n <th>destination_x</th>\n <th>destination_y</th>\n <th>image</th>\n <th>route</th>\n </tr>\n <tr>\n <th>seed</th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>[POLYGON ((-17.62168766659423 -98.369266220295...</td>\n <td>-66.0</td>\n <td>-54.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>1</th>\n <td>[POLYGON ((-97.82715137072381 -82.221167700698...</td>\n <td>-38.0</td>\n <td>65.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>2</th>\n <td>[POLYGON ((-46.23706006792075 -76.756994820638...</td>\n <td>73.0</td>\n <td>49.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>3</th>\n <td>[POLYGON ((-7.4210414351932155 -83.11109606339...</td>\n <td>31.0</td>\n <td>56.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>4</th>\n <td>[POLYGON ((-77.97638439917915 -70.239097296919...</td>\n <td>47.0</td>\n <td>54.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>995</th>\n <td>[POLYGON ((-58.363834699771374 -78.10250502922...</td>\n <td>53.0</td>\n <td>52.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>996</th>\n <td>[POLYGON ((-45.38105849246964 -86.568664678920...</td>\n <td>-66.0</td>\n <td>73.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>997</th>\n <td>[POLYGON ((-82.90222667221566 -92.864813148784...</td>\n <td>41.0</td>\n <td>51.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>998</th>\n <td>[POLYGON ((-37.1039416590347 -88.1790371955828...</td>\n <td>-45.0</td>\n <td>64.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n <tr>\n <th>999</th>\n <td>[POLYGON ((-119.59353826736813 -30.54685916387...</td>\n <td>74.0</td>\n <td>-25.0</td>\n <td>&lt;NA&gt;</td>\n <td>None</td>\n </tr>\n </tbody>\n</table>\n<p>1000 rows × 5 columns</p>\n</div>"
},
"execution_count": 86,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2 = pd.read_pickle(\"test.pickle\")\n",
"df2"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "markdown",
"source": [
"https://programtalk.com/python-examples/PIL.ImageDraw.Draw.polygon/)\n",
"https://stackoverflow.com/questions/3654289/scipy-create-2d-polygon-mask"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
},
{
"cell_type": "markdown",
"source": [
"Ich würde auch zu 1. tendieren, stimme Ihnen aber zu, dass das Thema sehr umfangreich ist. Könnte man sich nicht einen Teilbereich herauspicken? Ich verstehe nicht viel vom Segeln, daher lassen Sie mich kurz zusammenfassen, was Sie vorhaben: - Sie generieren Trainingsdaten mit dem existierenden aber langsamen GD Algorithmus. Ich nehme an, es handelt sich um lokale Routen in einem relativ kleinen Kartenausschnitt. Lässt es die Laufzeit zu, dass Sie eine große Menge an Routen berechnen. - Sie haben dann eine Karte und als Ausgabe eine Liste der Wendepunkte - Warum wollen Sie daraus eine Heatmap berechnen? Diesen Schritt habe ich noch nicht verstanden - Wenn Sie aus einer Karte eine Heatmap trainieren wollen und dafür genügend Beispiele haben, könnnten GANs hilfreich sein: https://arxiv.org/abs/1611.07004 Ich würde Ihnen raten, das Problem möglichst so zu reduzieren, dass es im Rahmen des Moduls noch handhabbar bleibt. Alles Weitere kann man sich auch für spätere Arbeiten aufbewahren. Das 2. Thema ist auch ok. Aber vielleicht nicht ganz so spannend. Ich überlasse Ihnen die Entscheidung. Freundliche Grüße Heiner Giefers"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+1 -1
Submodule pyrate updated: 1415645163...d148e65134.
-26
View File
@@ -1,26 +0,0 @@
FROM ros:humble-ros-base-jammy
# Resolve APT dependencies
RUN apt-get update -qq
RUN apt-get install apt-utils software-properties-common -yqq
RUN add-apt-repository ppa:antiprism/ppa -y
RUN apt-get install apt-utils software-properties-common python3-pip g++ python3-dev python3-gdal libgdal-dev libsqlite3-mod-spatialite antiprism git libqt5gui5 libqt5core5a qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libxtst6 libasound2 -yqq
# Clone and install Pyrate
COPY pyrate/ pyrate
RUN pip3 install ./pyrate
# Clone and install Model
COPY model/ model
RUN pip3 install ./model
# Clone ROS nodes and install requirements
COPY ros-nodes/ ros-nodes
WORKDIR ros-nodes
RUN pip3 install -r requirements.txt
RUN rosdep update -q
RUN rosdep install -q -y -i --from-path src --as-root pip:false
RUN pip install jupyter
SHELL ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash && colcon build --symlink-install"]
RUN source install/setup.bash