Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
471fb90
Initial commit with working state machine
marlow-fawn Mar 29, 2024
fca8d64
Added (not very good) A*
marlow-fawn Apr 2, 2024
552ac97
After much A* work, just built a simple reactive navigation. Needs tw…
marlow-fawn Apr 5, 2024
40b963c
Bug fixes to navigation. Still need to figure out player radius
marlow-fawn Apr 11, 2024
5add8e1
utils for adding interact boxes
helenlu66 Apr 23, 2024
429c92e
added docstrings to make interact box funcs easier to understand
helenlu66 Apr 23, 2024
4e63089
example environment after adding interaction areas
helenlu66 Apr 23, 2024
5337c03
added interaction areas to locs
helenlu66 Apr 23, 2024
fe22db1
Merge remote-tracking branch 'upstream/main'
helenlu66 Apr 23, 2024
713381b
fixed issue with interact in the env
helenlu66 Apr 24, 2024
9be1aab
using the ta's astar
helenlu66 Apr 24, 2024
ed2661a
navigation and getcontainer works for static multiagent
helenlu66 Apr 25, 2024
7d4b705
readme for running the agent
helenlu66 Apr 25, 2024
443058a
fixed issues with project collision
helenlu66 Apr 25, 2024
7f55ab8
edge cases
helenlu66 Apr 25, 2024
2349a31
fixed edge cases in proj_collision
helenlu66 Apr 25, 2024
5a72d3f
make sure to update self.env at transition
helenlu66 Apr 25, 2024
afd9538
make sure to update self.env at transition
helenlu66 Apr 25, 2024
e350844
Merge pull request #1 from marlow-fawn/static_multiagent
helenlu66 Apr 25, 2024
d4eaeba
changed low level astar to high level planning
helenlu66 Apr 26, 2024
52a2e92
integrated high level planning
helenlu66 Apr 26, 2024
611a6f3
Update socket_agent_proj.py - added add_to_container function
tonkology Apr 27, 2024
c5b1a92
Update socket_agent_proj.py
tonkology Apr 27, 2024
d92b456
Update socket_agent_proj.py
tonkology Apr 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode/
*__pycache__*
29 changes: 0 additions & 29 deletions Q_Learning_agent.py

This file was deleted.

10 changes: 5 additions & 5 deletions enums/direction.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


class Direction(Enum):
NONE = 0,
NORTH = 1,
SOUTH = 2,
EAST = 3,
WEST = 4
NORTH = 0
SOUTH = 1
EAST = 2
WEST = 3
NONE = 4
19 changes: 19 additions & 0 deletions final_proj/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Installing
Clone the repo

```
git clone https://github.com/marlow-fawn/propershopper.git
```

## Running keyboard input
Running the simulation with keyboard input is a good way to get a sense of the physics of the simulation and how interaction with objects works.

To run keyboard input, while in the "proppershopper" directory, run

```
<python-command> socket_env.py --keyboard_input --random_start --num_players 5
```
## Run our agent
```
<python-command> socket_agent_proj.py
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions final_proj/astar_dynamic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import math
from copy import deepcopy

import numpy as np
from PIL import Image

from enums.direction import Direction
from helper import project_collision_dyn, project_collision, round_float

STEP = 0.15


class Node:
"""A node class for A* Pathfinding"""

def __init__(self, parent=None, position=None):
self.parent = parent
self.position = position

self.g = 0
self.h = 0
self.f = 0

def __eq__(self, other):
return self.position == other.position


# By Nicholas Swift via https://medium.com/@nicholas.w.swift/easy-a-star-pathfinding-7e6689c7f7b2
# Modifications by Marlow Fawn
def astar(goal, player, state):
"""Returns a list of tuples as a path from the given start to the given end in the given maze"""
player_copy = deepcopy(player)
goal_copy = deepcopy(goal)

start = (round(player_copy['position'][1] / STEP), round(player_copy['position'][0] / STEP))
end = (round(goal_copy['position'][1] / STEP), round(goal_copy['position'][0] / STEP))
# Create start and end node
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0

# Initialize both open and closed list
open_list = []
closed_list = []

# Add the start node
open_list.append(start_node)

# Loop until you find the end
while len(open_list) > 0:

# Get the current node
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index

# Pop current off open list, add to closed list
open_list.pop(current_index)
closed_list.append(current_node)

# Found the goal
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1] # Return reversed path

# Generate children
children = []
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]: # Adjacent squares

# Get node position
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])

# Make sure walkable terrain
# todo: If holding cart, even bigger?
# todo: update based on new_position
player_copy['position'][0] = convert_to_real(node_position[0])
player_copy['position'][1] = convert_to_real(node_position[1])
if project_collision(player_copy, state, Direction.NONE):
continue

# Create new node
new_node = Node(current_node, node_position)

# Append
children.append(new_node)

# Loop through children
for child in children:

# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue

# Create the f, g, and h values
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + (
(child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h

# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue

# Add the child to the open list
open_list.append(child)


def convert_to_real(loc):
return loc * STEP


def convert_to_astar(loc):
return round(loc / STEP)
192 changes: 192 additions & 0 deletions final_proj/astar_static.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import math
from copy import deepcopy

import numpy as np
from PIL import Image

from enums.direction import Direction
from helper import project_collision_dyn, project_collision

from warnings import warn
import heapq

STEP = 0.3
BUFFER = 0.3


def init_map(obs):
map_ = []
tile = {
"position": [0, 0],
"width": 0.6,
"height": 0.4,
"index": 0
}
max_width = 25
max_height = 25
while tile["position"][1] < max_height:
map_.append([])
while tile["position"][0] < max_width:
map_[len(map_) - 1].append(project_collision_dyn(tile, obs, Direction.NONE, buffer=BUFFER))
tile["position"][0] += STEP

tile["position"][0] = 0
tile["position"][1] += STEP

# map_ = update_dyn(map_, obs)

x = np.asarray(map_, np.uint8)
im = Image.fromarray(x, 'P')
im.putpalette([0, 0, 0, # Black
255, 0, 0, # Red
0, 255, 0, # g
0, 255, 255]) # b
im.show()

return map_


def update_dyn(map_: [[]], state, index=0):
for player in state['observation']['players']:
if player['index'] == index:
continue
x = round((player['position'][0] - BUFFER) / STEP)
y = round((player['position'][1] - BUFFER) / STEP)
for i in range(math.ceil((player['width'] + BUFFER) / STEP)):
for j in range(math.ceil((player['height'] + BUFFER) / STEP)):
map_[y + j][x + i] = -1
return map_


class Node:
"""
A node class for A* Pathfinding
"""

def __init__(self, parent=None, position=None):
self.parent = parent
self.position = position

self.g = 0
self.h = 0
self.f = 0

def __eq__(self, other):
return self.position == other.position

def __repr__(self):
return f"{self.position} - g: {self.g} h: {self.h} f: {self.f}"

# defining less than for purposes of heap queue
def __lt__(self, other):
return self.f < other.f

# defining greater than for purposes of heap queue
def __gt__(self, other):
return self.f > other.f


def return_path(current_node):
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1] # Return reversed path


def astar(goal, player, maze):
start = (round(player['position'][1] / STEP), round(player['position'][0] / STEP))
end = (round(goal['position'][1] / STEP), round(goal['position'][0] / STEP))

# Create start and end node
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0

# Initialize both open and closed list
open_list = []
closed_list = []

# Heapify the open_list and Add the start node
heapq.heapify(open_list)
heapq.heappush(open_list, start_node)

# Adding a stop condition
outer_iterations = 0
max_iterations = (len(maze[0]) * len(maze) // 2)

# what squares do we search
adjacent_squares = ((0, -1), (0, 1), (-1, 0), (1, 0),)

# Loop until you find the end
while len(open_list) > 0:
outer_iterations += 1

if outer_iterations > max_iterations:
# if we hit this point return the path such as it is
# it will not contain the destination
warn("giving up on pathfinding too many iterations")
return return_path(current_node)

# Get the current node
current_node = heapq.heappop(open_list)
closed_list.append(current_node)

# Found the goal
if current_node == end_node:
return return_path(current_node)

# Generate children
children = []

for new_position in adjacent_squares: # Adjacent squares

# Get node position
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])

# Make sure walkable terrain
if maze[node_position[0]][node_position[1]] != 0:
continue

# Create new node
new_node = Node(current_node, node_position)

# Append
children.append(new_node)

# Loop through children
for child in children:
# Child is on the closed list
if len([closed_child for closed_child in closed_list if closed_child == child]) > 0:
continue

# Create the f, g, and h values
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + (
(child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h

# Child is already in the open list
if len([open_node for open_node in open_list if
child.position == open_node.position and child.g > open_node.g]) > 0:
continue

# Add the child to the open list
heapq.heappush(open_list, child)

warn("Couldn't get a path to destination")
return None


def convert_to_real(loc):
return loc * STEP


def convert_to_index(loc):
return round(loc / STEP)


def get_pathfind_index(obj):
return f"{convert_to_index(obj['position'][1])},{convert_to_index(obj['position'][0])}"
Loading