implemented new disarming in auto mode

This commit is contained in:
s452645 2021-06-06 22:00:42 +02:00
parent 985c7c0d77
commit 70fb44f69e
24 changed files with 5572 additions and 12071 deletions

View File

@ -1,17 +1,18 @@
import os import os
import json import json
from matplotlib import pyplot
from joblib import dump, load from joblib import dump, load
from sklearn import tree from sklearn import tree
from sklearn.feature_extraction import DictVectorizer from sklearn.feature_extraction import DictVectorizer
from objects.mines.disarming.mine_parameters import MineParameters from disarming.parameters.mine_parameters import MineParameters
from objects.mines.disarming.parameter_json import generate_data from disarming.parameters.parameter_json import generate_data
class DecisionTree: class DecisionTree:
def __init__(self, clf_source: str = None, vec_source: str = None): def __init__(self, load_from_file: bool = False):
if clf_source is not None and vec_source is not None: if load_from_file:
clf_source = r"algorithms/learn/decision_tree/decision_tree.joblib"
vec_source = r"algorithms/learn/decision_tree/dict_vectorizer.joblib"
self.load(clf_source, vec_source) self.load(clf_source, vec_source)
else: else:
self.clf = None self.clf = None
@ -48,8 +49,8 @@ class DecisionTree:
# fig.savefig("decistion_tree.png") # fig.savefig("decistion_tree.png")
def save(self): def save(self):
dump(self.clf, 'decision_tree.joblib') dump(self.clf, r'algorithms/learn/decision_tree/decision_tree.joblib')
dump(self.vec, 'dict_vectorizer.joblib') dump(self.vec, r'algorithms/learn/decision_tree/dict_vectorizer.joblib')
def load(self, clf_file, vec_file): def load(self, clf_file, vec_file):
self.clf = load(clf_file) self.clf = load(clf_file)
@ -84,7 +85,7 @@ class DecisionTree:
if __name__ == "__main__": if __name__ == "__main__":
# generate_data("training_set.txt", 12000) generate_data("training_set.txt", 12000)
decision_tree = DecisionTree() decision_tree = DecisionTree()
decision_tree.build("training_set.txt", 15) decision_tree.build("training_set.txt", 15)
decision_tree.test() decision_tree.test()

View File

@ -16,14 +16,16 @@ class NNType(Enum):
class NeuralNetwork: class NeuralNetwork:
def __init__(self, network_type: NNType, saved_model_path=None, classes_path=None, img_height=180, img_width=180): def __init__(self, network_type: NNType, load_from_file: bool = False, img_height=180, img_width=180):
self.type = network_type self.type = network_type
self.training_data_dir = pathlib.Path(fr"../../../resources/data/neural_network/{self.type.value[0]}/train") self.training_data_dir = pathlib.Path(fr"../../../resources/data/neural_network/{self.type.value[0]}/train")
self.img_height = img_height self.img_height = img_height
self.img_width = img_width self.img_width = img_width
if saved_model_path is not None and classes_path is not None: if load_from_file:
saved_model_path = fr"algorithms/learn/neural_network/{self.type.value[0]}/saved_model.h5"
classes_path = fr"algorithms/learn/neural_network/{self.type.value[0]}/saved_model_classes.joblib"
self.load(saved_model_path, classes_path) self.load(saved_model_path, classes_path)
else: else:
self.model = None self.model = None
@ -113,10 +115,8 @@ class NeuralNetwork:
predictions = self.model.predict(img_array) predictions = self.model.predict(img_array)
score = tf.nn.softmax(predictions[0]) score = tf.nn.softmax(predictions[0])
print( # returns class, condifdence
"This image most likely belongs to {} with a {:.2f} percent confidence." return self.class_names[np.argmax(score)], 100 * np.max(score)
.format(self.class_names[np.argmax(score)], 100 * np.max(score))
)
if __name__ == "__main__": if __name__ == "__main__":
@ -128,7 +128,7 @@ if __name__ == "__main__":
# neural_network.save() # neural_network.save()
# Loading a model from file: # Loading a model from file:
neural_network = NeuralNetwork(NNType.SPECIFICITY, r"specificity/saved_model.h5", r"specificity/saved_model_classes.joblib") neural_network = NeuralNetwork(NNType.SPECIFICITY, load_from_file=True)
# Test # Test
image = r"../../../resources/data/neural_network/specificity/disarm/tanks/1-35-British-Tank-FV-214-Conqueror-MK-II-Amusing-Hobby-35A027-AH-35A027_b_0.JPG" image = r"../../../resources/data/neural_network/specificity/disarm/tanks/1-35-British-Tank-FV-214-Conqueror-MK-II-Amusing-Hobby-35A027-AH-35A027_b_0.JPG"

View File

@ -3,9 +3,9 @@ import pygame
import project_constants as const import project_constants as const
from assets import asset_constants as asset from assets import asset_constants as asset
from objects.mines.mine_models.standard_mine import StandardMine from objects.mine_models.standard_mine import StandardMine
from objects.mines.mine_models.chained_mine import ChainedMine from objects.mine_models.chained_mine import ChainedMine
from objects.mines.mine_models.time_mine import TimeMine from objects.mine_models.time_mine import TimeMine
# ================================= # # ================================= #

View File

@ -0,0 +1,85 @@
import os
import random
from disarming.parameters.hash_function import SeriesHash, SpecificityHash
from objects.mine_models.mine import Mine
from algorithms.learn.decision_tree.decision_tree import DecisionTree
from algorithms.learn.neural_network.neural_network import NNType, NeuralNetwork
SERIES_IMAGES_PATH = r"resources/data/neural_network/series/disarm"
SPECIFICITY_IMAGES_PATH = r"resources/data/neural_network/specificity/disarm"
class_to_series = \
{SeriesHash[name].value[2]: SeriesHash[name].value[1] for name, _ in SeriesHash.__members__.items()}
class_to_specificity = \
{SpecificityHash[name].value[2]: SpecificityHash[name].value[1] for name, _ in SpecificityHash.__members__.items()}
class DisarmingHandler:
def __init__(self, mine: Mine):
self.mine = mine
self.mine_params = dict()
self.series_img = None
self.specificity_img = None
self.recognized_series = None
self.recognized_specificity = None
self.correct_wire = None
self.chosen_wire = None
self._set_mine_params()
self._set_correct_wire()
def _set_mine_params(self):
self.mine_params = self.mine.investigate()
def _set_correct_wire(self):
self.correct_wire = self.mine.wire
def get_mine_params(self):
return [self.mine_params["mine_type"], self.mine_params["weight"], self.mine_params["danger_cls"],
self.mine_params["indicator"], self.mine_params["series"], self.mine_params["specificity"]]
def pick_series_image(self):
series_class = SeriesHash[self.mine_params["series"].upper().replace(" ", "_")].value[2]
imgs_dir = os.path.join(SERIES_IMAGES_PATH, series_class)
self.series_img = os.path.join(
imgs_dir, random.choice([x for x in os.listdir(imgs_dir) if os.path.isfile(os.path.join(imgs_dir, x))]))
return self.series_img
def pick_specificity_image(self):
specificity_class = SpecificityHash[self.mine_params["specificity"].upper().replace(" ", "_")].value[2]
imgs_dir = os.path.join(SPECIFICITY_IMAGES_PATH, specificity_class)
self.specificity_img = os.path.join(
imgs_dir, random.choice([x for x in os.listdir(imgs_dir) if os.path.isfile(os.path.join(imgs_dir, x))]))
return self.specificity_img
def recognize_series(self):
nn = NeuralNetwork(NNType.SERIES, load_from_file=True)
answer, confidence = nn.get_answer(self.series_img)
self.recognized_series = class_to_series[answer]
return self.recognized_series, self.mine_params["series"] == self.recognized_series
def recognize_specificity(self):
nn = NeuralNetwork(NNType.SPECIFICITY, load_from_file=True)
answer, confidence = nn.get_answer(self.specificity_img)
self.recognized_specificity = class_to_specificity[answer]
return self.recognized_specificity, self.mine_params["specificity"] == self.recognized_specificity
def choose_wire(self):
dt = DecisionTree(load_from_file=True)
self.chosen_wire = dt.get_answer(self.mine_params)[0]
return self.chosen_wire
def defuse(self):
return self.mine.disarm(self.chosen_wire)

View File

@ -23,14 +23,10 @@ class DangerClassHash(Enum):
class SeriesHash(Enum): class SeriesHash(Enum):
TCH_2990TONER = 128, "TCH 2990toner" TCH_2990TONER = 128, "TCH 2990toner", "T"
TCH_2990INKJET = 110, "TCH 2990inkjet" SWX_5000 = 80, "SWX 5000", "S"
TVY_2400H = 100, "TVY 2400h" WORKHORSE_3200 = 30, "WORKHORSE 3200", "W"
SWX_5000 = 80, "SWX 5000" FX_500 = 15, "FX 500", "F"
SWX_4000 = 50, "SWX 4000"
WORKHORSE_3200 = 30, "WORKHORSE 3200"
FX_500 = 15, "FX 500"
TVY_2400 = 0, "TVY 2400"
class IndicatorHash(Enum): class IndicatorHash(Enum):
@ -42,13 +38,9 @@ class IndicatorHash(Enum):
class SpecificityHash(Enum): class SpecificityHash(Enum):
ANTI_AIRCRAFT = 55, "anti aircraft" ANTI_AIRCRAFT = 55, "anti aircraft", "planes"
ANTI_PERSONNEL = 43, "anti personnel" DEPTH_MINE = 37, "depth mine", "ships"
DEPTH_MINE = 37, "depth mine" ANTI_TANK = 26, "anti tank", "tanks"
ANTI_TANK = 26, "anti tank"
PROXIMITY_MINE = 18, "proximity mine"
PRESSURE_MINE = 9, "pressure mine"
FRAGMENTATION_MINE = 0, "fragmentation mine"
class WeightHash(Enum): class WeightHash(Enum):

View File

@ -1,5 +1,5 @@
import random import random
from objects.mines.disarming import hash_function as hf from disarming.parameters import hash_function as hf
class MineParameters: class MineParameters:

View File

@ -1,10 +1,10 @@
import json import json
import objects.mines.disarming.mine_parameters as param import disarming.parameters.mine_parameters as param
import os import os
import project_constants as const import project_constants as const
# this module is self contained, used to generate a json file # this module is self contained, used to generate a json file
DIR_DATA = os.path.join(const.ROOT_DIR, "resources", "data") DIR_DATA = os.path.join(const.ROOT_DIR, "resources", "data", "decision_tree")
# just to show, how mine parameters works # just to show, how mine parameters works

View File

@ -1,8 +1,10 @@
import pygame import pygame
import pygame_gui import pygame_gui
from project_constants import SCREEN_WIDTH, SCREEN_HEIGHT, V_NAME_OF_WINDOW from project_constants import SCREEN_WIDTH, SCREEN_HEIGHT, V_NAME_OF_WINDOW
from assets.asset_constants import ASSET_CONCRETE from assets.asset_constants import ASSET_CONCRETE
from objects.mine_models.mine import Mine
from disarming.disarming_handler import DisarmingHandler
# =========== # # =========== #
# == const == # # == const == #
@ -77,7 +79,7 @@ class SampleWindow:
# main attributes # main attributes
self.running = True self.running = True
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.manager = pygame_gui.UIManager(screen_size, 'theme.json') # TODO : change theme path self.manager = pygame_gui.UIManager(screen_size, 'disarming/theme.json') # TODO : change theme path
# main attributes # main attributes
def gui(): def gui():
@ -501,49 +503,76 @@ class SampleWindow:
# == run == # # == run == #
# ========= # # ========= #
def run(self): def run(self, mine: Mine):
timed_event = pygame.USEREVENT + 1
pygame.time.set_timer(timed_event, 5000)
step = 0
handler = DisarmingHandler(mine)
while self.running: while self.running:
time_delta = self.clock.tick(60) / 1000.0 time_delta = self.clock.tick(60) / 1000.0
keystate = pygame.key.get_pressed()
# all events except QUIT are for testing
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
self.running = False self.running = False
if keystate[pygame.K_a]: if event.type == timed_event:
self.show_params("hello", "yello", "gel", "jello", "yum", "hello") if step == 0:
if keystate[pygame.K_s]: params = handler.get_mine_params()
self.show_series("workhorse 3200wx", True) self.show_params(params[0], params[1], params[2], params[3], params[4], params[5])
if keystate[pygame.K_d]: elif step == 1:
self.show_spec("anti aircraft", False) self.show_cable_calculated(handler.correct_wire)
if keystate[pygame.K_f]: elif step == 2:
self.show_cable_calculated("red")
if keystate[pygame.K_g]: # TODO:
self.show_cable_chosen("blue") img = pygame.transform.scale(
if keystate[pygame.K_q]: pygame.image.load(handler.pick_series_image()),
self.show_pic_series(ASSET_CONCRETE) (1080, 1080)
if keystate[pygame.K_w]: )
self.show_pic_spec(ASSET_CONCRETE)
self.show_pic_series(img)
elif step == 3:
# TODO:
img = pygame.transform.scale(
pygame.image.load(handler.pick_specificity_image()),
(60, 60)
)
self.show_pic_spec(img)
elif step == 4:
answer, is_correct = handler.recognize_series()
self.show_series(answer, is_correct)
elif step == 5:
answer, is_correct = handler.recognize_specificity()
self.show_spec(answer, is_correct)
elif step == 6:
self.show_cable_chosen(handler.choose_wire())
else:
self.running = False
step += 1
self.manager.update(time_delta) self.manager.update(time_delta)
self.window_surface.blit(self.background, (0, 0)) self.window_surface.blit(self.background, (0, 0))
self.manager.draw_ui(self.window_surface) self.manager.draw_ui(self.window_surface)
pygame.display.update() pygame.display.update()
return handler.defuse()
def disarming_popup(): def disarming_popup(mine: Mine = None):
# run the pop-up # run the pop-up
app = SampleWindow() app = SampleWindow()
app.run() result = app.run(mine)
# bring display back to normal # bring display back to normal
pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption(V_NAME_OF_WINDOW) pygame.display.set_caption(V_NAME_OF_WINDOW)
return result
if __name__ == '__main__': if __name__ == '__main__':
pygame.init() pygame.init()

View File

@ -7,7 +7,7 @@ from algorithms.search import a_star
from minefield import Minefield from minefield import Minefield
from objects.mines.mine_models.time_mine import TimeMine from objects.mine_models.time_mine import TimeMine
from ui.ui_components_manager import UiComponentsManager from ui.ui_components_manager import UiComponentsManager
from ui.text_box import TextBox from ui.text_box import TextBox

View File

@ -7,9 +7,9 @@ import project_constants as const
from objects.tile import Tile from objects.tile import Tile
# import mine models # import mine models
from objects.mines.mine_models.standard_mine import StandardMine from objects.mine_models.standard_mine import StandardMine
from objects.mines.mine_models.time_mine import TimeMine from objects.mine_models.time_mine import TimeMine
from objects.mines.mine_models.chained_mine import ChainedMine from objects.mine_models.chained_mine import ChainedMine
class JsonGenerator: class JsonGenerator:

View File

@ -1,6 +1,6 @@
import project_constants as const import project_constants as const
from objects import tile as tl, agent as ag from objects import tile as tl, agent as ag
from objects.mines.mine_models.time_mine import TimeMine from objects.mine_models.time_mine import TimeMine
import json_generator as jg import json_generator as jg

View File

@ -3,6 +3,8 @@ from assets import asset_constants as asset
import json import json
from time import sleep from time import sleep
from pygame import transform from pygame import transform
import disarming.popup as popup
from algorithms.learn.decision_tree.decision_tree import DecisionTree from algorithms.learn.decision_tree.decision_tree import DecisionTree
@ -21,21 +23,16 @@ class Agent:
self.row, self.column = int(self.row), int(self.column) self.row, self.column = int(self.row), int(self.column)
self.position = [self.row, self.column] self.position = [self.row, self.column]
self.on_screen_coordinates = const.get_tile_coordinates(tuple(self.position)) self.on_screen_coordinates = const.get_tile_coordinates(tuple(self.position))
self.decision_tree = DecisionTree(const.ROOT_DIR + "/algorithms/learn/decision_tree/decision_tree.joblib",
const.ROOT_DIR + "/algorithms/learn/decision_tree/dict_vectorizer.joblib")
self.direction = const.Direction(data["agents_initial_state"]["direction"]) self.direction = const.Direction(data["agents_initial_state"]["direction"])
self.rotation_angle = -const.Direction(self.direction).value * 90 self.rotation_angle = -const.Direction(self.direction).value * 90
self.going_forward = False self.going_forward = False
self.rotating_left = False self.rotating_left = False
self.rotating_right = False self.rotating_right = False
def defuse_a_mine(self, mine): @staticmethod
mine_params = mine.investigate() def defuse_a_mine(mine):
chosen_wire = self.decision_tree.get_answer(mine_params) is_success = popup.disarming_popup(mine)
# TODO temporarily printing chosen wire return is_success
print("agent's chosen wire: " + str(chosen_wire[0]))
sleep(3)
return mine.disarm(chosen_wire)
def update_and_draw(self, window, delta_time, minefield): def update_and_draw(self, window, delta_time, minefield):
self.update(delta_time, minefield) self.update(delta_time, minefield)

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
from .mine import Mine from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash from disarming.parameters.hash_function import TypeHash
class ChainedMine(Mine): class ChainedMine(Mine):

View File

@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
# type hints # type hints
from typing import Tuple from typing import Tuple
from objects.mines.disarming.mine_parameters import MineParameters from disarming.parameters.mine_parameters import MineParameters
# Mine cannot be instantiated # Mine cannot be instantiated
# all abstract methods must be implemented in derived classes # all abstract methods must be implemented in derived classes
@ -34,7 +34,4 @@ class Mine(ABC):
del mine_parameters["wire"] del mine_parameters["wire"]
self.wire = wire self.wire = wire
# TODO temporarily printing parameters and right wire
print("parameters:", mine_parameters, "\nright wire: " + wire)
return mine_parameters return mine_parameters

View File

@ -1,5 +1,5 @@
from .mine import Mine from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash from disarming.parameters.hash_function import TypeHash
class StandardMine(Mine): class StandardMine(Mine):

View File

@ -1,5 +1,5 @@
from .mine import Mine from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash from disarming.parameters.hash_function import TypeHash
class TimeMine(Mine): class TimeMine(Mine):

File diff suppressed because it is too large Load Diff