947 lines
38 KiB
Plaintext
947 lines
38 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%% md\n"
|
||
}
|
||
},
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/pyrate\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"%cd /pyrate/"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 15,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"is_executing": true,
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"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": 23,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"START\n",
|
||
"[<pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d9c00>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d89a0>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d88b0>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8880>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8820>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d87c0>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8760>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8700>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8640>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8550>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d85b0>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8250>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d9d20>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d9b10>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d9030>, <pyrate.plan.nearplanner.timing_frame.TimingFrame object at 0x7f96ca5d8f40>]\n",
|
||
"[C] Construction finished with 4 remaining\n",
|
||
"EvaluatedTimingFrame([[ 0. 0. ]\n",
|
||
" [ 26.43818117 12.62331955]\n",
|
||
" [ 50.6782909 18.29214599]\n",
|
||
" [ 44.80120821 35.03692309]\n",
|
||
" [ 17.25507975 36.62852036]\n",
|
||
" [ 24.69135802 63.98756667]\n",
|
||
" [ 78.25984163 72.64748198]\n",
|
||
" [ 82.03172913 76.84603024]\n",
|
||
" [ 0.42157698 98.41464665]\n",
|
||
" [ 0. 100. ]])\n",
|
||
"667.5603860950698\n",
|
||
"955.189600304951\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"from experiments import generate_route"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"SIZE_INNER = 75\n",
|
||
"SIZE_ROUTE = 100\n",
|
||
"MIN_DESTINATION_DISTANCE = 25"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"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)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(array('d', [84.94149230207856, 78.04507967759636, 79.05686913703596, 80.08400830987347, 81.70255259062077, 83.61415975738558, 85.33508086545056, 85.47040615575028, 86.0245499015864, 84.94149230207856]),\n",
|
||
" array('d', [72.74676391639998, 70.74544900500507, 67.2549918581008, 66.46078189157683, 65.98644621136356, 66.31332436288989, 67.74737384448065, 67.96201813311431, 69.99066912301528, 72.74676391639998]))"
|
||
]
|
||
},
|
||
"execution_count": 18,
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"POLYGON ((13.575412783607412 14.141511830603921, 11.886568098525395 13.482167281052025, 8.703912627668682 7.6730441887238605, 8.974534426860235 6.144904064619676, 21.215855344806364 6.946074653972472, 13.575412783607412 14.141511830603921))\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(random_polygon())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 21,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"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))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 22,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
},
|
||
"scrolled": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"ename": "NameError",
|
||
"evalue": "name 'asdf' is not defined",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
|
||
"Input \u001b[0;32mIn [22]\u001b[0m, in \u001b[0;36m<cell line: 45>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 43\u001b[0m plt\u001b[38;5;241m.\u001b[39mlegend(by_label\u001b[38;5;241m.\u001b[39mvalues(), by_label\u001b[38;5;241m.\u001b[39mkeys())\n\u001b[1;32m 44\u001b[0m plt\u001b[38;5;241m.\u001b[39mshow()\n\u001b[0;32m---> 45\u001b[0m \u001b[43masdf\u001b[49m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m5\u001b[39m):\n\u001b[1;32m 48\u001b[0m o \u001b[38;5;241m=\u001b[39m generate_obstacles(s)\n",
|
||
"\u001b[0;31mNameError\u001b[0m: name 'asdf' is not defined"
|
||
]
|
||
}
|
||
],
|
||
"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",
|
||
" if obstacles:\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 seed in range(5):\n",
|
||
" obstacles = generate_obstacles(seed)\n",
|
||
" plot_situation(obstacles, generate_destination(obstacles, seed), \"RED\")\n",
|
||
" (route,) = generate_route()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "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\n",
|
||
"text/plain": [
|
||
"<PIL.Image.Image image mode=RGB size=200x200>"
|
||
]
|
||
},
|
||
"execution_count": 9,
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 10,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"5.3 ms ± 111 µ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()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 11,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"5.83 s ± 398 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>1000 rows × 5 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" obstacles destination_x \\\n",
|
||
"seed \n",
|
||
"0 [POLYGON ((-17.62168766659423 -98.369266220295... -66.0 \n",
|
||
"1 [POLYGON ((-97.82715137072381 -82.221167700698... -38.0 \n",
|
||
"2 [POLYGON ((-46.23706006792075 -76.756994820638... 73.0 \n",
|
||
"3 [POLYGON ((-7.4210414351932155 -83.11109606339... 31.0 \n",
|
||
"4 [POLYGON ((-77.97638439917915 -70.239097296919... 47.0 \n",
|
||
"... ... ... \n",
|
||
"995 [POLYGON ((-58.363834699771374 -78.10250502922... 53.0 \n",
|
||
"996 [POLYGON ((-45.38105849246964 -86.568664678920... -66.0 \n",
|
||
"997 [POLYGON ((-82.90222667221566 -92.864813148784... 41.0 \n",
|
||
"998 [POLYGON ((-37.1039416590347 -88.1790371955828... -45.0 \n",
|
||
"999 [POLYGON ((-119.59353826736813 -30.54685916387... 74.0 \n",
|
||
"\n",
|
||
" destination_y image route \n",
|
||
"seed \n",
|
||
"0 -54.0 NaN NaN \n",
|
||
"1 65.0 NaN NaN \n",
|
||
"2 49.0 NaN NaN \n",
|
||
"3 56.0 NaN NaN \n",
|
||
"4 54.0 NaN NaN \n",
|
||
"... ... ... ... \n",
|
||
"995 52.0 NaN NaN \n",
|
||
"996 73.0 NaN NaN \n",
|
||
"997 51.0 NaN NaN \n",
|
||
"998 64.0 NaN NaN \n",
|
||
"999 -25.0 NaN NaN \n",
|
||
"\n",
|
||
"[1000 rows x 5 columns]"
|
||
]
|
||
},
|
||
"execution_count": 11,
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 12,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</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>NaN</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>1000 rows × 5 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" obstacles destination_x \\\n",
|
||
"seed \n",
|
||
"0 [POLYGON ((-17.62168766659423 -98.369266220295... -66.0 \n",
|
||
"1 [POLYGON ((-97.82715137072381 -82.221167700698... -38.0 \n",
|
||
"2 [POLYGON ((-46.23706006792075 -76.756994820638... 73.0 \n",
|
||
"3 [POLYGON ((-7.4210414351932155 -83.11109606339... 31.0 \n",
|
||
"4 [POLYGON ((-77.97638439917915 -70.239097296919... 47.0 \n",
|
||
"... ... ... \n",
|
||
"995 [POLYGON ((-58.363834699771374 -78.10250502922... 53.0 \n",
|
||
"996 [POLYGON ((-45.38105849246964 -86.568664678920... -66.0 \n",
|
||
"997 [POLYGON ((-82.90222667221566 -92.864813148784... 41.0 \n",
|
||
"998 [POLYGON ((-37.1039416590347 -88.1790371955828... -45.0 \n",
|
||
"999 [POLYGON ((-119.59353826736813 -30.54685916387... 74.0 \n",
|
||
"\n",
|
||
" destination_y image route \n",
|
||
"seed \n",
|
||
"0 -54.0 NaN NaN \n",
|
||
"1 65.0 NaN NaN \n",
|
||
"2 49.0 NaN NaN \n",
|
||
"3 56.0 NaN NaN \n",
|
||
"4 54.0 NaN NaN \n",
|
||
"... ... ... ... \n",
|
||
"995 52.0 NaN NaN \n",
|
||
"996 73.0 NaN NaN \n",
|
||
"997 51.0 NaN NaN \n",
|
||
"998 64.0 NaN NaN \n",
|
||
"999 -25.0 NaN NaN \n",
|
||
"\n",
|
||
"[1000 rows x 5 columns]"
|
||
]
|
||
},
|
||
"execution_count": 12,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"df2 = pd.read_pickle(\"test.pickle\")\n",
|
||
"df2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%% md\n"
|
||
}
|
||
},
|
||
"source": [
|
||
"https://programtalk.com/python-examples/PIL.ImageDraw.Draw.polygon/)\n",
|
||
"https://stackoverflow.com/questions/3654289/scipy-create-2d-polygon-mask"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%% md\n"
|
||
}
|
||
},
|
||
"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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"pycharm": {
|
||
"name": "#%%\n"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": []
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3 (ipykernel)",
|
||
"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.10.4"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 1
|
||
} |