Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

website to deploy dfp model #76

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .isort.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
profile=black
line_length=79
src_paths=src,tests
skip=.tox,.nox,venv,build,dist,resources,model,log
skip=.tox,.nox,venv,build,dist,resources,model,log,site
known_setuptools=setuptools,pkg_resources
known_test=pytest
known_first_party=Deep_floorplan
Expand Down
11 changes: 11 additions & 0 deletions site/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "tf2deepfloorplan-site",
"version": "1.0.0",
"description": "site for deep floorplan deployment",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Leo Leung",
"license": "ISC"
}
99 changes: 98 additions & 1 deletion src/dfp/game/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
from typing import Tuple, Union

import matplotlib.pyplot as plt
import numpy as np
import pygame
from numba import jit, njit
Expand Down Expand Up @@ -93,6 +94,14 @@ def __init__(self, tomlfile: str = "docs/game.toml"):
self.view = View(self.model).register_window(self.win)
self.control = Controller(self.model)

self.statemap = np.zeros(self.model.result.shape[:2])
self.statemap[self.model.result == 0] = 1
self.statemap[self.model.result == 1] = 2
self.statemap[int(self.model.player_y), int(self.model.player_x)] = 5
self.statemap_color = np.zeros(
(self.model.result.shape[0], self.model.result.shape[1], 3)
)

def _initialise_game_engine(self):
pygame.init()
self.win = pygame.display.set_mode(
Expand All @@ -101,7 +110,17 @@ def _initialise_game_engine(self):
pygame.display.set_caption("Deep Floorplan Raycasting")
self.clock = pygame.time.Clock()

def colorise_routes(self):
self.statemap_color[self.statemap == 1] = (255, 255, 255)
self.statemap_color[self.statemap == 2] = (255, 255, 0)
self.statemap_color[self.statemap == 3] = (255, 0, 0)
self.statemap_color[self.statemap == 4] = (0, 0, 255)
self.statemap_color[self.statemap == 5] = (0, 255, 0)
self.statemap_color[self.statemap == 6] = (128, 129, 255)

def run(self):
old_destination = self.model.goal

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Expand All @@ -115,6 +134,77 @@ def run(self):
self.view.show_fps(str(int(self.clock.get_fps())))
self.view.draw_player_loc()

# init route data
if (
self.model.auto_navigate
and not self.model.find_route
and old_destination != self.model.goal
):
self.statemap[self.model.goal[1], self.model.goal[0]] = 6
self.parentArr = np.zeros(self.model.result.shape[:2])
h, w = self.model.result.shape
X, Y = np.meshgrid(
np.linspace(0, h - 1, h), np.linspace(0, w - 1, w)
)
H = np.abs(X - self.model.goal[0]) + np.abs(
Y - self.model.goal[1]
)
H = H.T
f = np.ones((h, w)) * np.inf
g = np.ones((h, w)) * np.inf
g[int(self.model.player_y), int(self.model.player_x)] = 0
f[int(self.model.player_y), int(self.model.player_x)] = H[
int(self.model.player_y), int(self.model.player_x)
]
numExpanded = 0
loc = np.array(
[
[int(self.model.player_y), self.model.goal[1]],
[int(self.model.player_x), self.model.goal[0]],
]
)
st_node = np.ravel_multi_index(loc, (h, w))

old_destination = self.model.goal
self.model.display_route = True

if self.model.display_route and not self.model.find_route:
min_dist = np.amin(f.flatten())
current = np.argmin(f.flatten())
if (current == st_node[-1]) or np.isinf(min_dist):
self.model.find_route = True
plt.imshow(self.statemap)
plt.show()

current_ind = np.unravel_index(current, (h, w))
self.statemap[current_ind] = 3
f[current_ind] = np.inf
numExpanded += 1

i = current_ind[0]
j = current_ind[1]
for jw in range(j - 1, j + 2, 2):
if i >= 0 and i <= h - 1 and jw >= 0 and jw <= w - 1:
if (self.statemap[i, jw] == 1) or (
self.statemap[i, jw] == 6
):
self.statemap[i, jw] = 4
g[i, jw] = g[i, j] + 1
f[i, jw] = g[i, j] + H[i, j]
self.parentArr[i, jw] = current

for iw in range(i - 1, i + 2, 2):
if iw >= 0 and iw <= h - 1 and j >= 0 and j <= w - 1:
if (self.statemap[iw, j] == 1) or (
self.statemap[iw, j] == 6
):
self.statemap[iw, j] = 4
g[iw, j] = g[i, j] + 1
f[iw, j] = g[i, j] + H[i, j]
self.parentArr[iw, j] = current

self.colorise_routes()

# calculate player rays
wallangles = loop_rays(
self.model.player_x,
Expand All @@ -129,7 +219,8 @@ def run(self):
)

for idx, (angle, fdist, iswall) in enumerate(wallangles):
self.view.draw_player_rays(angle, fdist)
if not self.model.auto_navigate:
self.view.draw_player_rays(angle, fdist)
wall_color = int(
255 * (1 - (3 * fdist / self.model.MAX_DEPTH) ** 2)
)
Expand All @@ -139,6 +230,12 @@ def run(self):

if iswall:
self.view.draw_3d_wall(idx, wall_color, wall_height)

if self.model.display_route and not self.model.find_route:
route_surf = pygame.surfarray.make_surface(
np.transpose(self.statemap_color, (1, 0, 2))
)
self.win.blit(route_surf, (0, 0))
pygame.display.flip()

self.clock.tick()
Expand Down
80 changes: 80 additions & 0 deletions src/dfp/game/controller.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,78 @@
import math
import sys

import numpy as np
import pygame
from scipy.ndimage.morphology import distance_transform_edt

from .model import Model


class Controller:
def __init__(self, model: Model):
self.model = model
self.get_repulsive_field()

def get_repulsive_field(self):
tmp_result = self.model.result.copy()
tmp_result[0, :] = 1
tmp_result[-1, :] = 1
tmp_result[:, 0] = 1
tmp_result[:, -1] = 1
self.navigate_repulsive_field = distance_transform_edt(1 - tmp_result)
self.navigate_repulsive_field /= np.max(self.navigate_repulsive_field)
self.navigate_repulsive_field = 1 / (
self.navigate_repulsive_field**2 + 0.1
)
self.navigate_repulsive_field *= self.model.nu_auto_navigate

def get_attractive_field(self):
h, w = self.model.result.shape
self.x, self.y = np.meshgrid(
np.linspace(1, w, w), np.linspace(1, h, h)
)
attract_to_target = (self.x - self.model.goal[0]) ** 2 + (
self.y - self.model.goal[1]
) ** 2
attract_to_target /= np.max(attract_to_target)
reject_away_start = -np.sqrt(
(self.x - self.model.player_x) ** 2
+ (self.y - self.model.player_y) ** 2
)
reject_away_start -= np.min(reject_away_start)
reject_away_start /= np.max(reject_away_start)
self.navigate_attractive_field = (
100 * attract_to_target + reject_away_start
)
self.navigate_attractive_field /= np.max(
self.navigate_attractive_field
)
self.navigate_attractive_field *= self.model.xi_auto_navigate

def get_navigate_field(self):
self.model.navigate_field = np.transpose(
self.navigate_attractive_field + self.navigate_repulsive_field,
(1, 0),
)
# self.model.navigate_field = np.transpose(
# self.navigate_attractive_field,
# (1, 0),
# )
# self.model.navigate_field = np.transpose(
# + self.navigate_repulsive_field,
# (1, 0),
# )
self.model.navigate_field /= np.max(self.model.navigate_field)
self.model.navigate_field *= 255
self.model.navigate_field = np.tile(
np.expand_dims(self.model.navigate_field, axis=2), (1, 1, 3)
)

def player_control(self):
keys = pygame.key.get_pressed()
if True in keys:
self.model.auto_navigate = False
state = pygame.mouse.get_pressed()
angle, x, y = (
self.model.player_angle,
self.model.player_x,
Expand All @@ -37,6 +98,25 @@ def player_control(self):
if keys[pygame.K_q]:
pygame.quit()
sys.exit(0)
if state[0]:
destination_pos = pygame.mouse.get_pos()
if (
destination_pos[0] <= self.model.result.shape[1]
and destination_pos[1] <= self.model.result.shape[0]
):
self.model.auto_navigate = True
if self.model.auto_navigate:
if self.model.goal != destination_pos:
self.model.goal = destination_pos # x,y
# get new navigation map
self.get_attractive_field()
self.get_navigate_field()
self.model.navigate_surf = pygame.surfarray.make_surface(
self.model.navigate_field
).convert_alpha()
self.model.find_route = False

self.model.goal = destination_pos # x,y
if x < 0:
x = 0
if x >= self.model.w:
Expand Down
34 changes: 33 additions & 1 deletion src/dfp/game/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import numpy as np
import pygame
from PIL import Image

from ..deploy import main
from ..utils.settings import overwrite_args_with_toml
Expand All @@ -18,10 +19,21 @@ class Model:
SKY_COLOR = (0, 150, 200)
GRD_COLOR = (100, 100, 100)
PLAYER_COLOR = (255, 0, 0)
PLAYER_SIZE = 8
TILE_SIZE = 1
dangle = 0.01
dpos = 1
dpos = 0.1
GAME_TEXT_COLOR = pygame.Color("coral")
MAX_SIZE = 480
auto_navigate = False
find_route = False
display_route = False
goal = (0, 0)
nu_auto_navigate = 2000 # repulsive
d0_auto_navigate = 2
xi_auto_navigate = 5000 # attractive
navigate_field = None
navigate_surf = None
# surf = None

def __init__(self, tomlfile: str = "docs/game.toml"):
Expand All @@ -34,6 +46,7 @@ def __init__(self, tomlfile: str = "docs/game.toml"):

def _initialise_map(self):
self.result = main(self.args)
self.rescale_image()
self.h, self.w = self.result.shape
self.bg = self.rgb_im = np.zeros((self.h, self.w, 3))
self.bg[self.result != 10] = self.FLOOR_COLOR
Expand All @@ -47,8 +60,27 @@ def _initialise_map(self):
self.SCALE = (self.SCREEN_WIDTH / 2) / self.args.casted_rays
self.surf = pygame.surfarray.make_surface(self.bg)

def rescale_image(self):
self.h, self.w = self.result.shape
max_side = max(self.h, self.w)
scale_factor = self.MAX_SIZE / max_side
tmpimg = Image.fromarray(self.result)
if self.h > self.w:
new_shp = (
int(scale_factor * self.w),
self.MAX_SIZE,
)
else:
new_shp = (
self.MAX_SIZE,
int(scale_factor * self.h),
)
tmpimg = tmpimg.resize(new_shp, resample=Image.NEAREST)
self.result = np.asarray(tmpimg).copy()

def _initialise_player_pose(self):
posy, posx = np.where(self.result != 1)
posidx = random.randint(0, len(posy) - 1)
self.player_x, self.player_y = posx[posidx], posy[posidx]
self.player_angle = math.pi
self.dpos = 20 * self.PLAYER_SIZE / self.MAX_DEPTH
4 changes: 3 additions & 1 deletion src/dfp/game/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def register_window(self, win: pygame.Surface) -> View:

def draw_dfp(self):
self.win.blit(self.model.surf, (0, 0))
if self.model.auto_navigate and self.model.navigate_surf:
self.win.blit(self.model.navigate_surf, (0, 0))

def show_fps(self, fps: str):
font = pygame.font.SysFont("Arial", 18)
Expand All @@ -29,7 +31,7 @@ def draw_player_loc(self):
self.win,
self.model.PLAYER_COLOR,
(self.model.player_x, self.model.player_y),
8,
self.model.PLAYER_SIZE,
)

def draw_player_rays(
Expand Down