diff --git a/ForkliftAgent.py b/ForkliftAgent.py index 32b4580..6393746 100644 --- a/ForkliftAgent.py +++ b/ForkliftAgent.py @@ -1,8 +1,10 @@ +from copy import deepcopy from typing import Tuple, List from AgentBase import AgentBase from PatchAgent import PatchAgent from PatchType import PatchType +from data.GameConstants import GameConstants from data.Item import Item from data.Order import Order from data.enum.Direction import Direction @@ -16,7 +18,7 @@ from util.PathDefinitions import GridLocation, GridWithWeights class ForkliftAgent(AgentBase): - def __init__(self, model, game_constants, client_delivery: PatchAgent, drop_off: PatchAgent, + def __init__(self, model, game_constants: GameConstants, client_delivery: PatchAgent, drop_off: PatchAgent, graph: GridWithWeights): super().__init__(model) self.action_queue: List[Action] = [] @@ -28,11 +30,20 @@ class ForkliftAgent(AgentBase): self.drop_off: PatchAgent = drop_off self.graph = graph self.game_constants = game_constants - self.current_order: Order = None - self.current_item = None self.item_station_completed = False self.current_order_delivered_items: List[Item] = [] self.ready_for_execution = False + self.last_delviered_item = None + + self.current_item: Item = None + self.current_order = None + self.base: GridLocation = None + self.goal: GridLocation = None + + def set_base(self, drop_off: PatchAgent): + self.drop_off = drop_off + self.base = self.drop_off.location + self.goal = self.base def queue_movement_actions(self, movement_actions: List[Action]): self.action_queue.extend(movement_actions) @@ -43,120 +54,94 @@ class ForkliftAgent(AgentBase): action_type = action.action_type if action_type == ActionType.ROTATE_UP: - print("rotate {} --> {}".format(self.current_rotation, action_type)) + # print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.top elif action_type == ActionType.ROTATE_RIGHT: - print("rotate {} --> {}".format(self.current_rotation, action_type)) + # print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.right elif action_type == ActionType.ROTATE_DOWN: - print("rotate {} --> {}".format(self.current_rotation, action_type)) + # print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.down elif action_type == ActionType.ROTATE_LEFT: - print("rotate {} --> {}".format(self.current_rotation, action_type)) + # print("rotate {} --> {}".format(self.current_rotation, action_type)) self.current_rotation = Direction.left elif action_type == ActionType.MOVE: if self.current_rotation == Direction.top: - print("move {} --> {}".format(self.current_position, action_type)) + # print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0], self.current_position[1] + 1) elif self.current_rotation == Direction.down: - print("move {} --> {}".format(self.current_position, action_type)) + # print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0], self.current_position[1] - 1) elif self.current_rotation == Direction.right: - print("move {} --> {}".format(self.current_position, action_type)) + # print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0] + 1, self.current_position[1]) elif self.current_rotation == Direction.left: - print("move {} --> {}".format(self.current_position, action_type)) + # print("move {} --> {}".format(self.current_position, action_type)) self.current_position = (self.current_position[0] - 1, self.current_position[1]) - def plan_actions(self): - if len(self.current_order.items) > 0: - i = self.current_order.items.pop(0) - if self.current_item is None: - self.current_order_delivered_items.clear() - self.current_item = i - print("PLAN MOVEMENT") - - # get item + def step(self) -> None: + if len(self.action_queue) > 0: + self.move() + elif self.ready_for_execution: + if self.current_position != self.goal: pathFinder = PathFinderOnStates( self.game_constants, - self.drop_off.location, - PathFinderState(self.current_position, - self.current_rotation, - 0, - Action(ActionType.NONE), - []) - ) - actions = pathFinder.get_action_list() - self.queue_movement_actions(actions) - - elif not self.item_station_completed: - # go through station - - packing_station: GridLocation = None - stations = dict(self.graph.packingStations) - if i.real_type == ItemType.SHELF: - packing_station = stations[PatchType.packingShelf] - elif i.real_type == ItemType.REFRIGERATOR: - packing_station = stations[PatchType.packingRefrigerator] - elif i.real_type == ItemType.DOOR: - packing_station = stations[PatchType.packingC] - - pathFinder = PathFinderOnStates( - self.game_constants, - packing_station, + self.goal, PathFinderState(self.current_position, self.current_rotation, 0, Action( - desired_item=i, + desired_item=None, action_type=ActionType.PICK_ITEM ), []) ) actions = pathFinder.get_action_list() self.queue_movement_actions(actions) - self.item_station_completed = True - else: - # go to client delivery area - pathFinder = PathFinderOnStates( - self.game_constants, - self.client_delivery.location, - PathFinderState(self.current_position, - self.current_rotation, - 0, - Action(ActionType.NONE), - []) - ) - actions = pathFinder.get_action_list() - self.queue_movement_actions(actions) - self.queue_movement_actions( - [Action(ActionType.DROP_ITEM)] - ) + if self.current_order is not None and self.goal == self.base: + self.current_item = self.current_order.items.pop(0) + packing_station: GridLocation = None + stations = dict(self.graph.packingStations) - self.current_order_delivered_items.append(self.current_item) - self.current_item = None - self.item_station_completed = False + if self.current_item.real_type == ItemType.SHELF: + packing_station = stations[PatchType.packingShelf] + elif self.current_item.real_type == ItemType.REFRIGERATOR: + packing_station = stations[PatchType.packingRefrigerator] + elif self.current_item.real_type == ItemType.DOOR: + packing_station = stations[PatchType.packingDoor] - def step(self) -> None: - if len(self.action_queue) > 0: - self.move() - elif self.ready_for_execution and len(self.orderList) > 0: - if (self.current_order is not None and len(self.current_order.items)) == 0: - self.fulfilled_orders.append(self.current_order) - self.current_order = None + self.goal = packing_station - if self.current_order is None: - self.current_order = self.orderList.pop(0) + elif self.goal in [i[1] for i in self.graph.packingStations]: + self.goal = self.client_delivery.location - self.plan_actions() + elif self.goal == self.client_delivery.location: + if self.current_order is not None and len(self.current_order.items) == 0: + + self.current_order_delivered_items.append(self.current_item) + self.current_order.items = deepcopy(self.current_order_delivered_items) + self.fulfilled_orders.append(self.current_order) + + self.current_item = None + self.current_order = None + + self.goal = self.base + else: + self.current_order_delivered_items.append(self.current_item) + self.goal = self.base + self.current_item = None + + elif self.goal == self.base and self.current_order is None: + self.current_order_delivered_items.clear() + self.current_order = self.orderList.pop(0) def creation_log(self): print("Created Forklift Agent [id: {}]".format(self.unique_id)) diff --git a/GameModel.py b/GameModel.py index 162a0f4..358e2a6 100644 --- a/GameModel.py +++ b/GameModel.py @@ -47,6 +47,7 @@ class GameModel(Model): self.grid = MultiGrid(height, width, True) self.schedule = RandomActivation(self) self.current_item_recognition = None + self.current_item = None self.client_delivery: PatchAgent = None self.drop_off: PatchAgent = None @@ -79,8 +80,8 @@ class GameModel(Model): self.initialize_grid(graph, item_display_pos) self.orderList: List[Order] = InitialStateFactory.generate_order_list(orders) self.fulfilled_orders: List[Order] = [] - self.forklift_agent.orderList = self.orderList self.forklift_agent.fulfilled_orders = self.fulfilled_orders + self.forklift_agent.set_base(self.drop_off) self.classificator = classificator print("############## RECOGNISE ITEMS ##############") @@ -104,6 +105,7 @@ class GameModel(Model): print("PATHFINDING") print(actions) self.forklift_agent.queue_movement_actions(actions) + self.current_order = self.forklift_agent.current_order def initialize_grid(self, graph: GridWithWeights, item_display_pos): print("INITIALIZING GRID") @@ -174,9 +176,11 @@ class GameModel(Model): self.grid.place_agent(agent, p) def update_item_display(self): - for index, item in enumerate(self.forklift_agent.current_order_delivered_items): - if item is not None: - self.item_display_agents[index].image = item.image + self.current_item = self.forklift_agent.current_item + for i in range(4): + self.item_display_agents[i].image = None + if len(self.forklift_agent.current_order_delivered_items) > i: + self.item_display_agents[i].image = self.forklift_agent.current_order_delivered_items[i].image def step(self): self.schedule.step() @@ -219,12 +223,15 @@ class GameModel(Model): # print("ORDER {}, PRIO: {}".format(new_orders[i].id, new_orders[i].priority)) self.orderList = new_orders + self.forklift_agent.orderList = self.orderList print("FINISHED CLIENT ORDER SORTING") self.phase = Phase.EXECUTION if self.phase == Phase.EXECUTION: - print("Execution") + self.current_order = self.forklift_agent.current_order + pass + # print("Execution") def recognise_item(self, item: Item): val = image_classification(self.picture_visualization.img, self.classificator) diff --git a/main.py b/main.py index 71326f9..25669b2 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,3 @@ -import math import random from mesa.visualization.ModularVisualization import ModularServer @@ -7,20 +6,15 @@ from tensorflow import keras from ForkliftAgent import ForkliftAgent from GameModel import GameModel -from InitialStateFactory import InitialStateFactory from ItemDisplayAgent import ItemDisplayAgent from PatchAgent import PatchAgent from PatchType import PatchType from PictureVisualizationAgent import PictureVisualizationAgent -from data.Order import Order from data.enum.Direction import Direction -from tensorflow import keras - -from data.enum.Priority import Priority -from genetic_order.GeneticOrder import GeneticOrder from util.PathDefinitions import GridWithWeights from visualization.DisplayAttributeElement import DisplayAttributeElement from visualization.DisplayItemListAttribute import DisplayItemListAttributeElement +from visualization.DisplayOrder import DisplayOrder from visualization.DisplayOrderList import DisplayOrderList colors = [ @@ -104,26 +98,27 @@ if __name__ == '__main__': diagram = GridWithWeights(gridWidth, gridHeight) diagram.walls = [(6, 5), (6, 6), (6, 7), (6, 8), (2, 3), (2, 4), (3, 4), (4, 4), (6, 4)] diagram.puddles = [(2, 2), (2, 5), (2, 6), (5, 4)] - diagram.packingStations = [(PatchType.packingShelf, (4, 8)), (PatchType.packingRefrigerator, (4, 6)), (PatchType.packingDoor, (4, 2))] + diagram.packingStations = [(PatchType.packingShelf, (4, 8)), (PatchType.packingRefrigerator, (4, 6)), + (PatchType.packingDoor, (4, 2))] grid = CanvasGrid(agent_portrayal, gridWidth, gridHeight, scale * gridWidth, scale * gridHeight) display_items = [(6, 11), (7, 11), (8, 11), (9, 11)] readyText = DisplayAttributeElement("phase") - # current_item = DisplayPictureElement("current_item_recognition") provided_itesm = DisplayItemListAttributeElement("provided_items") recognised_items = DisplayItemListAttributeElement("recognised_items") + current_order = DisplayOrder("current_order") + current_item = DisplayAttributeElement("current_item") ordersText = DisplayOrderList("orderList") fulfilled_orders = DisplayOrderList("fulfilled_orders") model = keras.models.load_model("imageClasification/my_model") server = ModularServer(GameModel, - [grid, readyText, provided_itesm, recognised_items, ordersText, - fulfilled_orders], + [grid, readyText, current_item, current_order, fulfilled_orders, ordersText], "Automatyczny Wózek Widłowy", - dict(width=gridHeight, height=gridWidth, graph=diagram, items=50, orders=3, + dict(width=gridHeight, height=gridWidth, graph=diagram, items=60, orders=20, classificator=model, item_display_pos=display_items)) server.port = 8888 diff --git a/visualization/DisplayOrder.py b/visualization/DisplayOrder.py new file mode 100644 index 0000000..eb7d43b --- /dev/null +++ b/visualization/DisplayOrder.py @@ -0,0 +1,46 @@ +from collections import Counter +from typing import List + +from mesa.visualization.modules import TextElement + +from data.Order import Order + + +class DisplayOrder(TextElement): + def __init__(self, attr_name): + ''' + Create a new text attribute element. + + Args: + attr_name: The name of the attribute to extract from the model. + + Example return: "happy: 10" + ''' + self.attr_name = attr_name + + def render(self, model): + val = getattr(model, self.attr_name) + res = self.attr_name + if val is not None: + o = val + itemList = map(lambda x: x.real_type, o.items) + itemCounter = Counter(itemList) + + item_str = "" + + res += f"
  • items: {item_str} priority: {o.priority}
    Client: {vars(o.client_params)}
  • " + + return res diff --git a/visualization/DisplayOrderList.py b/visualization/DisplayOrderList.py index f7b7564..46bc5f5 100644 --- a/visualization/DisplayOrderList.py +++ b/visualization/DisplayOrderList.py @@ -4,7 +4,6 @@ from typing import List from mesa.visualization.modules import TextElement from data.Order import Order -from data.enum.ItemType import ItemType class DisplayOrderList(TextElement): @@ -21,35 +20,36 @@ class DisplayOrderList(TextElement): def render(self, model): val = getattr(model, self.attr_name) + res = "" + if val is not None: + orderList: List[Order] = val - orderList: List[Order] = val + res = self.attr_name + ":
      " - res = self.attr_name + ":
        " + for o in orderList: + if o is None: + continue - for o in orderList: - if o is None: - continue + itemList = map(lambda x: x.real_type, o.items) + itemCounter = Counter(itemList) - itemList = map(lambda x: x.real_type, o.items) - itemCounter = Counter(itemList) + item_str = "" + res += f"
      1. items: {item_str} priority: {o.priority}
        Client: {vars(o.client_params)}
      2. " - res += f"
      3. items: {item_str} priority: {o.priority}
        Client: {vars(o.client_params)}
      4. " - - res += "
      " + res += "
    " return res