SI_InteligentnyWozekWidlowy/GameModel.py

240 lines
8.8 KiB
Python
Raw Normal View History

2022-05-22 16:27:36 +02:00
from enum import Enum
2022-04-16 14:55:25 +02:00
from typing import List
2022-04-28 01:50:56 +02:00
from mesa import Model
2022-04-08 00:43:25 +02:00
from mesa.space import MultiGrid
from mesa.time import RandomActivation
2022-04-16 14:55:25 +02:00
from AgentBase import AgentBase
2022-04-08 00:43:25 +02:00
from ForkliftAgent import ForkliftAgent
2022-04-28 01:50:56 +02:00
from InitialStateFactory import InitialStateFactory
2022-04-08 00:43:25 +02:00
from PatchAgent import PatchAgent
from PatchType import PatchType
2022-04-28 01:50:56 +02:00
from data.GameConstants import GameConstants
2022-05-22 16:27:36 +02:00
from data.Item import Item
from data.Order import Order
from data.enum.Direction import Direction
from data.enum.ItemType import ItemType
from decision.Action import Action
2022-04-28 01:50:56 +02:00
from decision.ActionType import ActionType
2022-04-28 21:22:19 +02:00
from pathfinding.PathfinderOnStates import PathFinderOnStates, PathFinderState
2022-04-28 01:50:56 +02:00
from util.PathDefinitions import GridLocation, GridWithWeights
2022-04-08 00:43:25 +02:00
2022-05-22 16:27:36 +02:00
class Phase(Enum):
INIT = 1
ITEM_RECOGNITION = 2
CLIENT_SORTING = 3
PLAN_MOVEMENT = 4
EXECUTION = 5
2022-04-08 00:43:25 +02:00
class GameModel(Model):
2022-05-22 16:27:36 +02:00
def __init__(self, width, height, graph: GridWithWeights):
2022-04-08 00:43:25 +02:00
# self.num_agents = 5
2022-05-22 16:27:36 +02:00
self.first = True
self.item_recognised = False
2022-04-08 00:43:25 +02:00
self.running = True
self.grid = MultiGrid(height, width, True)
self.schedule = RandomActivation(self)
2022-05-22 16:27:36 +02:00
self.client_delivery: PatchAgent = None
self.drop_off: PatchAgent = None
self.agents = [AgentBase]
2022-04-16 14:55:25 +02:00
self.forklift_agent = ForkliftAgent(self)
2022-04-08 00:43:25 +02:00
self.schedule.add(self.forklift_agent)
self.agents.append(self.forklift_agent)
2022-05-22 16:27:36 +02:00
self.graph = graph
2022-04-28 01:50:56 +02:00
self.game_constants = GameConstants(
width,
height,
2022-04-28 14:03:53 +02:00
graph.walls,
2022-05-22 16:27:36 +02:00
graph.puddles
2022-04-28 01:50:56 +02:00
)
2022-05-22 16:27:36 +02:00
# INITIALIZATION #
print("############## INITIALIZATION ##############")
self.phase = Phase.INIT
self.initialize_grid(graph)
self.orderList: List[Order] = InitialStateFactory.generate_order_list(3)
2022-04-08 00:43:25 +02:00
2022-05-22 16:27:36 +02:00
print("############## RECOGNISE ITEMS ##############")
self.phase = Phase.ITEM_RECOGNITION
self.provided_items = InitialStateFactory.generate_item_list(3)
self.recognised_items: List[Item] = []
print("Relocate forklift agent to loading area for item recognition")
2022-04-28 01:50:56 +02:00
pathFinder = PathFinderOnStates(
self.game_constants,
2022-05-22 16:27:36 +02:00
self.drop_off.location,
2022-04-28 01:50:56 +02:00
PathFinderState(self.forklift_agent.current_position, self.forklift_agent.current_rotation, 0,
2022-05-22 16:27:36 +02:00
Action(ActionType.NONE), [])
2022-04-28 01:50:56 +02:00
)
2022-04-28 21:22:19 +02:00
actions = pathFinder.get_action_list()
2022-04-28 01:50:56 +02:00
print("PATHFINDING")
print(actions)
2022-04-28 02:09:41 +02:00
self.forklift_agent.queue_movement_actions(actions)
2022-04-28 01:50:56 +02:00
2022-05-22 16:27:36 +02:00
def initialize_grid(self, graph: GridWithWeights):
print("INITIALIZING GRID")
# Add the agent to a random grid cell
x = 5
y = 5
self.grid.place_agent(self.forklift_agent, (x, y))
self.forklift_agent.current_position = (x, y)
self.place_logistics()
self.place_walls_agents(graph.walls)
self.place_puddles(graph.puddles)
self.place_packing_stations(graph.packingStations)
def place_logistics(self):
agent = PatchAgent(self, (self.grid.width - 1, int(self.grid.height / 2)), PatchType.pickUp)
2022-04-16 14:55:25 +02:00
self.schedule.add(agent)
2022-05-22 16:27:36 +02:00
self.grid.place_agent(agent, agent.location)
2022-04-08 00:43:25 +02:00
self.agents.append(agent)
2022-05-22 16:27:36 +02:00
self.client_delivery = agent
2022-04-08 00:43:25 +02:00
2022-05-22 16:27:36 +02:00
agent = PatchAgent(self, (0, int(self.grid.height / 2)), PatchType.dropOff)
self.grid.place_agent(agent, agent.location)
2022-04-08 00:43:25 +02:00
self.agents.append(agent)
2022-05-22 16:27:36 +02:00
self.drop_off = agent
2022-04-08 00:43:25 +02:00
2022-04-16 14:55:25 +02:00
def place_walls_agents(self, walls: List[GridLocation]):
for w in walls:
2022-05-22 16:27:36 +02:00
agent = PatchAgent(self, w, PatchType.wall)
2022-04-16 14:55:25 +02:00
self.agents.append(agent)
self.grid.place_agent(agent, w)
2022-04-28 14:03:53 +02:00
def place_puddles(self, puddles: List[GridLocation]):
for p in puddles:
2022-05-22 16:27:36 +02:00
agent = PatchAgent(self, p, PatchType.diffTerrain)
2022-04-28 14:03:53 +02:00
self.agents.append(agent)
self.grid.place_agent(agent, p)
2022-05-22 16:27:36 +02:00
def place_packing_stations(self, packing_stations: List[tuple[PatchType, GridLocation]]):
for p in packing_stations:
agent = PatchAgent(self, p[1], p[0])
self.agents.append(agent)
self.grid.place_agent(agent, p[1])
2022-04-08 00:43:25 +02:00
def step(self):
self.schedule.step()
self.grid.remove_agent(self.forklift_agent)
self.grid.place_agent(self.forklift_agent, self.forklift_agent.current_position)
2022-05-22 16:27:36 +02:00
if self.phase == Phase.ITEM_RECOGNITION:
if not self.item_recognised and self.forklift_agent.current_position == self.drop_off.location:
if len(self.provided_items) == 0:
print("FINISHED ITEM RECOGNITION")
self.item_recognised = True
self.phase = Phase.CLIENT_SORTING
else:
print("BEGIN ITEM RECOGNITION, left: {}".format(len(self.provided_items)))
item_to_recognise = self.provided_items.pop()
recognised = self.recognise_item(item_to_recognise)
self.recognised_items.append(recognised)
if self.phase == Phase.CLIENT_SORTING:
# TODO GENERICS SORTING
sorted(self.orderList, key=lambda x: len(x.items))
print("FINISHED CLIENT ORDER SORTING")
self.phase = Phase.PLAN_MOVEMENT
if self.phase == Phase.PLAN_MOVEMENT:
if len(self.orderList) > 0:
self.plan_actions()
self.phase = Phase.EXECUTION
else:
print("NO MORE ORDERS")
if self.phase == Phase.EXECUTION:
print("Execution")
if (len(self.forklift_agent.action_queue) == 0):
self.phase = Phase.PLAN_MOVEMENT
def plan_actions(self):
order = self.orderList.pop(0)
print("PLAN MOVEMENT")
for i in order.items:
if self.first:
# get item
pathFinder = PathFinderOnStates(
self.game_constants,
self.drop_off.location,
PathFinderState(self.forklift_agent.current_position,
self.forklift_agent.current_rotation,
0,
Action(ActionType.NONE),
[])
)
actions = pathFinder.get_action_list()
self.forklift_agent.queue_movement_actions(actions)
self.first = False
else:
# get item
pathFinder = PathFinderOnStates(
self.game_constants,
self.drop_off.location,
PathFinderState(self.client_delivery.location,
Direction.right,
0,
Action(ActionType.NONE),
[])
)
actions = pathFinder.get_action_list()
self.forklift_agent.queue_movement_actions(actions)
self.first = False
# go through station
packing_station: GridLocation = None
stations = dict(self.graph.packingStations)
if i.real_type == ItemType.PASTA:
packing_station = stations[PatchType.packingA]
elif i.real_type == ItemType.EGG:
packing_station = stations[PatchType.packingB]
elif i.real_type == ItemType.PIZZA:
packing_station = stations[PatchType.packingC]
pathFinder = PathFinderOnStates(
self.game_constants,
packing_station,
PathFinderState(self.drop_off.location,
Direction.left,
0,
Action(
desired_item=i,
action_type=ActionType.PICK_ITEM
),
[])
)
actions = pathFinder.get_action_list()
self.forklift_agent.queue_movement_actions(actions)
# go to client delivery area
pathFinder = PathFinderOnStates(
self.game_constants,
self.client_delivery.location,
PathFinderState(packing_station,
Direction.right,
0,
Action(ActionType.NONE),
[])
)
actions = pathFinder.get_action_list()
self.forklift_agent.queue_movement_actions(actions)
self.forklift_agent.queue_movement_actions(
[Action(ActionType.DROP_ITEM)]
)
def recognise_item(self, item: Item):
# TODO IMAGE PROCESSING
item.guessed_type = item.real_type
return item