seally 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seally-0.1.0/.gitignore +20 -0
- seally-0.1.0/.python-version +1 -0
- seally-0.1.0/PKG-INFO +37 -0
- seally-0.1.0/README.md +17 -0
- seally-0.1.0/docs/api.md +1 -0
- seally-0.1.0/docs/getting-started.md +1 -0
- seally-0.1.0/docs/index.md +1 -0
- seally-0.1.0/examples/a_star_search.py +27 -0
- seally-0.1.0/examples/interactive_viz.py +19 -0
- seally-0.1.0/maps/map1.csv +7 -0
- seally-0.1.0/maps/map2.csv +15 -0
- seally-0.1.0/maps/map3.csv +12 -0
- seally-0.1.0/maps/map4.csv +10 -0
- seally-0.1.0/maps/map5.csv +16 -0
- seally-0.1.0/maps/map6.csv +13 -0
- seally-0.1.0/maps/map7.csv +30 -0
- seally-0.1.0/mkdocs.yml +33 -0
- seally-0.1.0/pyproject.toml +39 -0
- seally-0.1.0/src/__init__.py +0 -0
- seally-0.1.0/src/seally/common/__init__.py +0 -0
- seally-0.1.0/src/seally/common/heuristics.py +33 -0
- seally-0.1.0/src/seally/common/path.py +4 -0
- seally-0.1.0/src/seally/env/_init_.py +0 -0
- seally-0.1.0/src/seally/env/grid_map.py +76 -0
- seally-0.1.0/src/seally/planners/__init__.py +0 -0
- seally-0.1.0/src/seally/planners/a_star.py +65 -0
- seally-0.1.0/src/seally/planners/d_star.py +0 -0
- seally-0.1.0/src/seally/planners/jps.py +1 -0
- seally-0.1.0/src/seally/planners/wave_front.py +1 -0
- seally-0.1.0/src/seally/viz/__init__.py +0 -0
- seally-0.1.0/src/seally/viz/vizualizer.py +173 -0
- seally-0.1.0/uv.lock +1246 -0
seally-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
seally-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: seally
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simple planning library for prototyping
|
|
5
|
+
Project-URL: Homepage, https://github.com/nick-Sutton/Seally
|
|
6
|
+
Project-URL: Documentation, https://nick-Sutton.github.io/Seally/
|
|
7
|
+
Project-URL: Repository, https://github.com/nick-Sutton/Seally
|
|
8
|
+
Author-email: Nicholas Sutton <nicksutton46@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: AI,Motion Planning,Robotics
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Requires-Dist: networkx[default]>=3.4
|
|
16
|
+
Requires-Dist: numpy>=2.0
|
|
17
|
+
Requires-Dist: pandas>=3.0
|
|
18
|
+
Requires-Dist: pygame>=2.6
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
### Seally
|
|
22
|
+
Seally is a planning library that I build to prototype planning algorithms. It currently supports static grid based enviroments.
|
|
23
|
+
|
|
24
|
+
#### Todo
|
|
25
|
+
- [ ] Create better visualization tools
|
|
26
|
+
- [ ] Add enviroment builder
|
|
27
|
+
- [ ] Add performance logging
|
|
28
|
+
- [ ] Add Configuration space enviroments
|
|
29
|
+
- [ ] Find a better map file format
|
|
30
|
+
- [ ] Allow for growing regions
|
|
31
|
+
|
|
32
|
+
####
|
|
33
|
+
1. Start with a map
|
|
34
|
+
2. Grag start and goal positions
|
|
35
|
+
3. Left-click to place obstacles
|
|
36
|
+
4. Right-click to delete obstacles
|
|
37
|
+
5. Robot should simulate SLAM
|
seally-0.1.0/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
### Seally
|
|
2
|
+
Seally is a planning library that I build to prototype planning algorithms. It currently supports static grid based enviroments.
|
|
3
|
+
|
|
4
|
+
#### Todo
|
|
5
|
+
- [ ] Create better visualization tools
|
|
6
|
+
- [ ] Add enviroment builder
|
|
7
|
+
- [ ] Add performance logging
|
|
8
|
+
- [ ] Add Configuration space enviroments
|
|
9
|
+
- [ ] Find a better map file format
|
|
10
|
+
- [ ] Allow for growing regions
|
|
11
|
+
|
|
12
|
+
####
|
|
13
|
+
1. Start with a map
|
|
14
|
+
2. Grag start and goal positions
|
|
15
|
+
3. Left-click to place obstacles
|
|
16
|
+
4. Right-click to delete obstacles
|
|
17
|
+
5. Robot should simulate SLAM
|
seally-0.1.0/docs/api.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# API Reference
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Getting Started
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Welcome to My Project
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from seally.common.path import Path
|
|
2
|
+
from seally.common.heuristics import chebyshev_distance
|
|
3
|
+
from seally.env.grid_map import GridMap, GridCell
|
|
4
|
+
from seally.planners.a_star import AStar
|
|
5
|
+
from seally.viz.vizualizer import Visualizer2D
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
# Create an enviroment from a map file
|
|
9
|
+
env: GridMap = GridMap(False, './maps/map2.csv')
|
|
10
|
+
|
|
11
|
+
# Create a planner and pass in the heuristic
|
|
12
|
+
a_star = AStar(env, chebyshev_distance)
|
|
13
|
+
|
|
14
|
+
# Define the source and goal positions
|
|
15
|
+
source = GridCell(0, 4)
|
|
16
|
+
goal = GridCell(11, 2)
|
|
17
|
+
|
|
18
|
+
# Find the shortest path from the start to the goal
|
|
19
|
+
path: Path = a_star.compute_path(source, goal)
|
|
20
|
+
|
|
21
|
+
# Visualize the path
|
|
22
|
+
viz = Visualizer2D(screen_size=(env.x_dim, env.y_dim))
|
|
23
|
+
viz.run_visualization(path, env)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if __name__ == "__main__":
|
|
27
|
+
main()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from seally.common.heuristics import chebyshev_distance
|
|
2
|
+
from seally.env.grid_map import GridMap
|
|
3
|
+
from seally.planners.a_star import AStar
|
|
4
|
+
from seally.viz.vizualizer import InteractiveVisualizer2D
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
# Create an enviroment from a map file
|
|
8
|
+
env: GridMap = GridMap(False, './maps/map7.csv')
|
|
9
|
+
|
|
10
|
+
# Create a planner and pass in the heuristic
|
|
11
|
+
a_star = AStar(env, chebyshev_distance)
|
|
12
|
+
|
|
13
|
+
# Visualize the path
|
|
14
|
+
viz = InteractiveVisualizer2D(planner=a_star)
|
|
15
|
+
viz.run_visualization(env)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,1,1,1,1,1,1,1,1,1,0,1,0,1
|
|
4
|
+
1,0,1,0,0,0,0,0,0,0,1,0,1,0,1
|
|
5
|
+
1,0,1,0,1,1,1,1,1,0,1,0,1,0,1
|
|
6
|
+
1,0,1,0,1,0,0,0,1,0,1,0,1,0,1
|
|
7
|
+
1,0,1,0,1,0,1,0,1,0,0,0,1,0,1
|
|
8
|
+
1,0,0,0,1,0,1,0,1,1,1,1,1,0,1
|
|
9
|
+
1,0,1,0,1,0,1,0,0,0,0,0,0,0,1
|
|
10
|
+
1,0,1,0,0,0,1,1,1,1,1,0,1,0,1
|
|
11
|
+
1,0,1,1,1,1,1,0,0,0,1,0,1,0,1
|
|
12
|
+
1,0,0,0,0,0,0,0,1,0,1,0,0,0,1
|
|
13
|
+
1,0,1,1,1,1,1,1,1,0,1,1,1,0,1
|
|
14
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
15
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
4
|
+
1,0,0,1,1,0,0,1,1,0,0,1
|
|
5
|
+
1,0,0,1,1,0,0,1,1,0,0,1
|
|
6
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
7
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
8
|
+
1,0,0,1,1,0,0,1,1,0,0,1
|
|
9
|
+
1,0,0,1,1,0,0,1,1,0,0,1
|
|
10
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
11
|
+
1,0,0,0,0,0,0,0,0,0,0,1
|
|
12
|
+
1,1,1,1,1,1,1,1,1,1,1,1
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1
|
|
4
|
+
1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1
|
|
5
|
+
1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1
|
|
6
|
+
1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1
|
|
7
|
+
1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1
|
|
8
|
+
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1
|
|
9
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
10
|
+
1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
4
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
5
|
+
1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1
|
|
6
|
+
1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1
|
|
7
|
+
0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0
|
|
8
|
+
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
|
|
9
|
+
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
|
|
10
|
+
0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0
|
|
11
|
+
1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1
|
|
12
|
+
1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1
|
|
13
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
14
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
15
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
16
|
+
1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,1,1,1,1,1,1,1,1,1,0,1
|
|
4
|
+
1,0,1,0,0,0,0,0,0,0,1,0,1
|
|
5
|
+
1,0,1,0,1,1,1,1,1,0,1,0,1
|
|
6
|
+
1,0,1,0,1,0,0,0,1,0,1,0,1
|
|
7
|
+
1,0,1,0,1,0,1,0,1,0,1,0,1
|
|
8
|
+
1,0,1,0,1,0,0,0,1,0,1,0,1
|
|
9
|
+
1,0,1,0,1,1,1,1,1,0,1,0,1
|
|
10
|
+
1,0,1,0,0,0,0,0,0,0,1,0,1
|
|
11
|
+
1,0,1,1,1,1,1,1,1,1,1,0,1
|
|
12
|
+
1,0,0,0,0,0,0,0,0,0,0,0,1
|
|
13
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
|
2
|
+
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
3
|
+
1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1
|
|
4
|
+
1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1
|
|
5
|
+
1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,0,1
|
|
6
|
+
1,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1
|
|
7
|
+
1,0,1,0,1,0,1,1,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1
|
|
8
|
+
1,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1
|
|
9
|
+
1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,1,1,1,0,1,0,1
|
|
10
|
+
1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1
|
|
11
|
+
1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1
|
|
12
|
+
1,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1
|
|
13
|
+
1,0,0,0,1,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,0,1,1,1,0,1,0,1
|
|
14
|
+
1,0,1,0,1,1,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,1
|
|
15
|
+
1,0,1,0,0,0,1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1
|
|
16
|
+
1,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1
|
|
17
|
+
1,0,0,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,0,1,0,1
|
|
18
|
+
1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1
|
|
19
|
+
1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,0,1
|
|
20
|
+
1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
|
|
21
|
+
1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1
|
|
22
|
+
1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1
|
|
23
|
+
1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,1,1,1,0,1
|
|
24
|
+
1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,1
|
|
25
|
+
1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1
|
|
26
|
+
1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,0,1
|
|
27
|
+
1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1
|
|
28
|
+
1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1
|
|
29
|
+
1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,0,1
|
|
30
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
seally-0.1.0/mkdocs.yml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
site_name: Seally
|
|
2
|
+
site_url: https://nick-Sutton.github.io/Seally/
|
|
3
|
+
repo_url: https://github.com/nick-Sutton/Seally
|
|
4
|
+
repo_name: nick-Sutton/Seally
|
|
5
|
+
|
|
6
|
+
theme:
|
|
7
|
+
name: material
|
|
8
|
+
features:
|
|
9
|
+
- navigation.tabs
|
|
10
|
+
- navigation.sections
|
|
11
|
+
- toc.integrate
|
|
12
|
+
- search.suggest
|
|
13
|
+
palette:
|
|
14
|
+
- scheme: default
|
|
15
|
+
toggle:
|
|
16
|
+
icon: material/brightness-7
|
|
17
|
+
name: Switch to dark mode
|
|
18
|
+
- scheme: slate
|
|
19
|
+
toggle:
|
|
20
|
+
icon: material/brightness-4
|
|
21
|
+
name: Switch to light mode
|
|
22
|
+
|
|
23
|
+
nav:
|
|
24
|
+
- Home: index.md
|
|
25
|
+
- Getting Started: getting-started.md
|
|
26
|
+
- API Reference: api.md
|
|
27
|
+
|
|
28
|
+
markdown_extensions:
|
|
29
|
+
- pymdownx.highlight
|
|
30
|
+
- pymdownx.superfences
|
|
31
|
+
- admonition
|
|
32
|
+
- toc:
|
|
33
|
+
permalink: true
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "seally"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A simple planning library for prototyping "
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"networkx[default]>=3.4",
|
|
10
|
+
"numpy>=2.0",
|
|
11
|
+
"pandas>=3.0",
|
|
12
|
+
"pygame>=2.6",
|
|
13
|
+
]
|
|
14
|
+
keywords = ["Motion Planning", "AI", "Robotics"]
|
|
15
|
+
authors = [
|
|
16
|
+
{ name = "Nicholas Sutton", email = "nicksutton46@gmail.com" }
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/nick-Sutton/Seally"
|
|
26
|
+
Documentation = "https://nick-Sutton.github.io/Seally/"
|
|
27
|
+
Repository = "https://github.com/nick-Sutton/Seally"
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["hatchling"]
|
|
30
|
+
build-backend = "hatchling.build"
|
|
31
|
+
|
|
32
|
+
[tool.hatch.build.targets.wheel]
|
|
33
|
+
packages = ["src/seally"]
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"mkdocs>=1.0,<2.0",
|
|
38
|
+
"mkdocs-material>=9.7.6",
|
|
39
|
+
]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from seally.env.grid_map import GridCell
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
def euclidean_distance(source: GridCell, goal: GridCell) -> float:
|
|
5
|
+
source_mat = np.array((source.x, source.y))
|
|
6
|
+
goal_mat = np.array((goal.x, goal.y))
|
|
7
|
+
|
|
8
|
+
dist = np.linalg.norm(source_mat - goal_mat)
|
|
9
|
+
|
|
10
|
+
return dist
|
|
11
|
+
|
|
12
|
+
def manhattan_distance(source: GridCell, goal: GridCell) -> float:
|
|
13
|
+
source_mat = np.array((source.x, source.y))
|
|
14
|
+
goal_mat = np.array((goal.x, goal.y))
|
|
15
|
+
|
|
16
|
+
dist = np.sum(np.abs(source_mat - goal_mat))
|
|
17
|
+
|
|
18
|
+
return dist
|
|
19
|
+
|
|
20
|
+
def chebyshev_distance(source: GridCell, goal: GridCell) -> float:
|
|
21
|
+
source_mat = np.array((source.x, source.y))
|
|
22
|
+
goal_mat = np.array((goal.x, goal.y))
|
|
23
|
+
|
|
24
|
+
dist = np.linalg.norm(source_mat - goal_mat, ord=np.inf)
|
|
25
|
+
|
|
26
|
+
return dist
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
File without changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
class GridCell():
|
|
7
|
+
def __init__(self, x: int, y: int):
|
|
8
|
+
self.x = x
|
|
9
|
+
self.y = y
|
|
10
|
+
|
|
11
|
+
def __hash__(self):
|
|
12
|
+
return hash((self.x, self.y))
|
|
13
|
+
|
|
14
|
+
def __eq__(self, other):
|
|
15
|
+
return self.x == other.x and self.y == other.y
|
|
16
|
+
|
|
17
|
+
class GridMap:
|
|
18
|
+
def __init__(self, gen_random: bool = True, file_path: str = None):
|
|
19
|
+
if gen_random:
|
|
20
|
+
pass
|
|
21
|
+
else:
|
|
22
|
+
self.map = pd.read_csv(file_path).to_numpy()
|
|
23
|
+
|
|
24
|
+
self.x_dim = self.map.shape[1]
|
|
25
|
+
self.y_dim = self.map.shape[0]
|
|
26
|
+
|
|
27
|
+
def is_occupied(self, cell: GridCell) -> bool:
|
|
28
|
+
"""
|
|
29
|
+
Determines if the provided coordinates are in collision with an obstacle
|
|
30
|
+
|
|
31
|
+
param: cell to check
|
|
32
|
+
return: True if the position is in collision
|
|
33
|
+
"""
|
|
34
|
+
return self.map[cell.y, cell.x] > 0
|
|
35
|
+
|
|
36
|
+
def in_bounds(self, cell: GridCell) -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Determines if the provided coordinates within the bounds of the map
|
|
39
|
+
|
|
40
|
+
param: cell to check
|
|
41
|
+
return: True if the position is in bounds
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
if cell.x < 0 or cell.x > self.x_dim - 1:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
if cell.y < 0 or cell.y > self.y_dim - 1:
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
def get_neighbors(self, cell: GridCell) -> List[GridCell]:
|
|
53
|
+
"""
|
|
54
|
+
Retuns a list of all valid neighbors for a given cell in the Gripmap
|
|
55
|
+
A valid cell is a cell that is within the bounds of the map.
|
|
56
|
+
|
|
57
|
+
params: cell to retrieve neighbors for
|
|
58
|
+
returns: A list of the cells valid neighbors
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
# create a mask of the indicies of the neighboring cells relative to the current cell
|
|
62
|
+
shift_mask = np.array([[-1,-1],[-1,0],[-1,1],
|
|
63
|
+
[0,-1], [0,1],
|
|
64
|
+
[1,-1], [1,0], [1,1]])
|
|
65
|
+
|
|
66
|
+
# broadcast the current cell to each of the shift mask offsets and add them to produce an array of neighbor coordinates
|
|
67
|
+
neighbor_indicies = np.array([cell.x, cell.y]) + shift_mask # shape (8, 2)
|
|
68
|
+
|
|
69
|
+
# create a mask to validate that all cells are in the bounds of the map
|
|
70
|
+
bounds_mask = (
|
|
71
|
+
(neighbor_indicies[:, 0] >= 0) & (neighbor_indicies[:, 0] < self.x_dim) &
|
|
72
|
+
(neighbor_indicies[:, 1] >= 0) & (neighbor_indicies[:, 1] < self.y_dim)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# apply the bounds map to each coordinate and return only the cells that are in bounds
|
|
76
|
+
return [GridCell(x, y) for x, y in neighbor_indicies[bounds_mask]]
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
import heapq
|
|
3
|
+
import numpy as np
|
|
4
|
+
from seally.env.grid_map import GridMap, GridCell
|
|
5
|
+
from seally.common.path import Path
|
|
6
|
+
|
|
7
|
+
class AStar():
|
|
8
|
+
def __init__(self, env: GridMap, heuristic: Callable[[GridCell, GridCell], float]):
|
|
9
|
+
self.env = env
|
|
10
|
+
self.heuristic = heuristic
|
|
11
|
+
|
|
12
|
+
def cost(self, source: GridCell, goal: GridCell) -> float:
|
|
13
|
+
"""
|
|
14
|
+
Computes the cost of going from one cell to another in the map
|
|
15
|
+
"""
|
|
16
|
+
dx, dy = abs(source.x - goal.x), abs(source.y - goal.y)
|
|
17
|
+
return np.sqrt(2) if dx + dy == 2 else 1.0
|
|
18
|
+
|
|
19
|
+
def compute_path(self, source: GridCell, goal: GridCell) -> Path:
|
|
20
|
+
if not self.env.in_bounds(source) or self.env.is_occupied(source):
|
|
21
|
+
raise Exception("Source is not a valid position")
|
|
22
|
+
|
|
23
|
+
if not self.env.in_bounds(goal) or self.env.is_occupied(goal):
|
|
24
|
+
raise Exception("Goal is not a valid position")
|
|
25
|
+
|
|
26
|
+
tie_count = 0
|
|
27
|
+
open_set = []
|
|
28
|
+
heapq.heappush(open_set, (0.0, tie_count, source))
|
|
29
|
+
|
|
30
|
+
came_from = {source: None}
|
|
31
|
+
cost_so_far = {source: 0.0}
|
|
32
|
+
closed_set = set() # track fully explored cells
|
|
33
|
+
|
|
34
|
+
while open_set:
|
|
35
|
+
_, _, current = heapq.heappop(open_set)
|
|
36
|
+
|
|
37
|
+
if current in closed_set: # already explored optimally, skip
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
closed_set.add(current)
|
|
41
|
+
|
|
42
|
+
if current == goal:
|
|
43
|
+
break
|
|
44
|
+
|
|
45
|
+
for next_cell in self.env.get_neighbors(current):
|
|
46
|
+
if self.env.is_occupied(next_cell) or next_cell in closed_set:
|
|
47
|
+
continue
|
|
48
|
+
new_cost = cost_so_far[current] + self.cost(current, next_cell)
|
|
49
|
+
if next_cell not in cost_so_far or new_cost < cost_so_far[next_cell]:
|
|
50
|
+
cost_so_far[next_cell] = new_cost
|
|
51
|
+
priority = new_cost + self.heuristic(next_cell, goal)
|
|
52
|
+
tie_count += 1
|
|
53
|
+
heapq.heappush(open_set, (priority, tie_count, next_cell))
|
|
54
|
+
came_from[next_cell] = current
|
|
55
|
+
|
|
56
|
+
if current != goal:
|
|
57
|
+
raise Exception("Path not found")
|
|
58
|
+
|
|
59
|
+
path = []
|
|
60
|
+
current = goal
|
|
61
|
+
while current is not None:
|
|
62
|
+
path.append(current)
|
|
63
|
+
current = came_from.get(current)
|
|
64
|
+
path.reverse()
|
|
65
|
+
return path
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#https://theory.stanford.edu/~amitp/GameProgramming/Variations.html#jump-point-search
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#https://www.ccs.neu.edu/home/rplatt/cs5335_fall2016/slides/bugs_wavefront.pdf
|
|
File without changes
|