Commit 4079af86 authored by 张晓彤's avatar 张晓彤

1.dispatcher.py 拆分-> schedule.py 2. 数据库部分字段修正 3. 解决循环调用问题 4. DispatchInfo 全局数据更新…

1.dispatcher.py 拆分-> schedule.py 2. 数据库部分字段修正 3. 解决循环调用问题 4. DispatchInfo 全局数据更新 in realtime_dispatch.py
parent dc367fbe
......@@ -8,13 +8,8 @@
from para_config import *
from equipment import ExcavatorInfo, DumpInfo, TruckInfo
from core.group import Group
from core.dispatcher import PreSchedule
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo(dump, excavator)
pre_sch = PreSchedule(truck, excavator, dump)
# from core.group import Group
from core.schedule import PreSchedule
class AlgorithmBase:
......@@ -37,7 +32,7 @@ class Congestion(AlgorithmBase):
class for congestion alg.
"""
def __init__(self, group: Group):
def __init__(self, group):
super().__init__()
self.group = group
self.logger = get_logger("zxt.algorithm.congestion")
......@@ -135,7 +130,7 @@ class ExpectedTime(AlgorithmBase):
class for expected traveling time alg.
"""
def __init__(self, group: Group):
def __init__(self, group):
super().__init__()
self.group = group
......
......@@ -13,6 +13,7 @@ from settings import get_logger, session_mysql, redis5
from tables import Dispatch
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
from core.schedule import PreSchedule
import json
import numpy as np
from datetime import datetime, timedelta
......@@ -22,7 +23,7 @@ class Dispatcher:
"""
class for group dispatch program.
"""
def __init__(self, truck: TruckInfo, dump: DumpInfo, excavator: ExcavatorInfo):
def __init__(self, truck: TruckInfo, dump: DumpInfo, excavator: ExcavatorInfo, pre_sch: PreSchedule, request_mode=False):
self.group_list = []
self.truck = truck
self.dump = dump
......@@ -35,7 +36,7 @@ class Dispatcher:
:return: None
"""
global_period_para_update()
# global_period_para_update()
self.dump.dump_para_period_update()
self.excavator.excavator_para_period_update()
......@@ -47,8 +48,8 @@ class Dispatcher:
Generate and initialize dispatch groups.
:return: None
"""
for group_id in DispatchInfo.group_set:
group = Group(group_id, self.truck, self.dump, self.excavator)
for group_id in DispatchInfo.group_dump_dict.keys():
group = Group(group_id, self.truck)
self.group_list.append(group)
def group_dispatch(self):
......@@ -69,12 +70,11 @@ class DispatchSubmission:
Attribute:
"""
def __init__(self, dump, excavator, truck, group):
def __init__(self, dump, excavator, truck):
self.logger = self.logger = get_logger("zxt.submission")
self.dump = dump
self.excavator = excavator
self.truck = truck
self.group = group
def truck_dispatch_to_redis(self, truck_id, dispatch_seq):
"""
......@@ -223,274 +223,3 @@ class DispatchSubmission:
for truck_id, dispatch_plan in dispatch_plan_dict:
self.truck_dispatch_to_redis(truck_id, dispatch_plan)
class PreSchedule:
""" class for the prediction of equipments' trip.
Description:
负责处理所有预测项的计算与更新
基于矿卡最近一次装卸载时间预测其抵达目的地时间
根据矿卡请求队列及抵达信息,计算设备最早可用时间
Attribute:
equipment class: truck, excavator, dump
schedule start time
equipment available time: truck, excavator, dump
"""
def __init__(self, truck, excavator, dump):
# 设备对象域
self.truck = truck
self.excavator = excavator
self.dump = dump
# 调度开始时间
self.start_time = datetime.now()
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
self.logger = get_logger("zxt.pre_schedule")
def update_truck_reach_time(self):
"""
更新矿卡预计抵达目的地时间
:return:
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
"""
try:
dynamic_excavator_num = self.excavator.get_excavator_num()
dumps = self.dump.get_dump_num()
trucks = self.truck.get_truck_num()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
truck_reach_excavator = self.truck.get_truck_reach_excavator()
truck_reach_dump = self.truck.get_truck_reach_dump()
excavator_avl_ls = [[] for _ in range(dynamic_excavator_num)]
dump_avl_ls = [[] for _ in range(dumps)]
# self.logger.info("update_truck_reach_time-trucks")
# self.logger.info(trucks)
for i in range(trucks):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
# self.logger.info("update_truck_reach_time-truck_current_trip")
# self.logger.info(truck_current_trip)
if task in [0, 1]: # 卡车空载行驶或正在入场
reach_time = truck_reach_excavator[i]
excavator_avl_ls[end_area_index].append(
[reach_time, i, end_area_index]
)
elif task in [3, 4]: # 卡车重载行驶或正在入场
reach_time = truck_reach_dump[i]
dump_avl_ls[end_area_index].append([reach_time, i, end_area_index])
elif task == -2:
self.truck_avl_time[i] = (
datetime.now() - self.start_time
) / timedelta(hours=0, minutes=1, seconds=0)
except Exception as es:
self.logger.error("矿卡预计抵达时间计算异常")
self.logger.error(es)
return [], []
return excavator_avl_ls, dump_avl_ls
def update_excavator_avl_time(self, excavator_avl_ls):
"""
更新挖机预计可用时间
:param
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
# 初始化挖机可用时间
self.excavator_avl_time = np.full(
get_value("dynamic_excavator_num"),
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for excavator_id in get_value("dynamic_excavator_set"):
self.excavator_avl_time_dict[excavator_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
loading_time = self.excavator.get_loading_time()
loading_task_time = self.excavator.get_loading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in excavator_avl_ls:
self.logger.info("update_excavator_avl_time-excavator_avl_ls")
self.logger.info(excavator_avl_ls)
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
excavator_index = int(tmp[i][2])
excavator_id = self.excavator.excavator_index_to_uuid_dict[excavator_index]
self.excavator_avl_time[excavator_index] = (
max(tmp[i][0], self.excavator_avl_time[excavator_index])
+ loading_task_time[excavator_index]
)
self.excavator_avl_time_dict[excavator_id] = self.excavator_avl_time[excavator_index]
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
self.truck_avl_time[truck_index] = self.excavator_avl_time[excavator_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.excavator_avl_time[excavator_index] = now
except Exception as es:
self.logger.error("挖机可用时间计算异常")
self.logger.error(es)
return self.excavator_avl_time_dict
def update_dump_avl_time(self, dump_avl_ls):
"""
更新卸载设备预计可用时间
:param
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
dynamic_dump_num = self.dump.get_dump_num()
# 初始化卸载设备可用时间
self.dump_avl_time = np.full(
dynamic_dump_num,
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for dump_id in get_value("dynamic_dump_set"):
self.dump_avl_time_dict[dump_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
unloading_time = self.dump.get_unloading_time()
unloading_task_time = self.dump.get_unloading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in dump_avl_ls:
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
dump_index = int(tmp[i][2])
dump_id = self.dump.dump_index_to_uuid_dict[dump_index]
self.dump_avl_time[dump_index] = (
max(tmp[i][0], self.dump_avl_time[dump_index])
+ unloading_task_time[dump_index]
)
self.dump_avl_time_dict[dump_id] = self.dump_avl_time[dump_index]
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
self.truck_avl_time[truck_index] = self.dump_avl_time[dump_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.dump_avl_time[dump_index] - now) > 60:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[i][1])] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
except Exception as es:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
return self.dump_avl_time_dict
def _reset(self):
"""
重置设备可用时间
:return:
"""
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
def get_dump_avl_time(self):
"""
获取卸载点最早可用时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
dump_avl_time = self.update_dump_avl_time(dump_avl_ls)
return dump_avl_time
def get_excavator_avl_time(self, excavator_id=None):
"""
获取挖机最早可用时间
:param excavator_id: 挖机编号uuid
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
if excavator_id is not None:
return self.update_excavator_avl_time(excavator_avl_ls) \
[self.excavator.excavator_uuid_to_index_dict[excavator_id]]
else:
return self.update_excavator_avl_time(excavator_avl_ls)
def get_truck_avl_time(self, truck_id=None):
"""
获取矿卡最早可用时间
:param truck_id: 矿卡编号uuid
:return: truck_avl_time: (array) 各矿卡完成当前装载或卸载任务的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
self.update_excavator_avl_time(excavator_avl_ls)
self.update_dump_avl_time(dump_avl_ls)
if truck_id is not None:
return self.truck_avl_time[self.truck.truck_uuid_to_index_dict[truck_id]]
else:
return self.truck_avl_time
......@@ -6,25 +6,38 @@
# @File : group.py
# @Software: PyCharm
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @File : group.py
# @Software: PyCharm
from data.dispatchInfo import DispatchInfo
from bidict import bidict
from alg.algorithm import AlgorithmBase, Congestion
from alg.algorithm import AlgorithmBase
class Group:
"""
class for group instance.
"""
def __init__(self, group_id, truck, dump, excavator):
def __init__(self, group_id, truck):
""" Generate a group obj.
:param group_id: (uuid) group_id
"""
self.to_dump_congestion = None
self.group_id = group_id
self.group_mode = 1
self.truck = truck
# group devices
self.excavator_dict = {} # excavator_id -> load_area_id
self.dump_dict = {} # dump_id -> unload_area_id
self.excavator_dict = {} # excavator_id -> unload_area_id
self.dump_dict = {} # dump_id -> load_area_id
self.truck_set = set() # truck_id
# road network info.
......@@ -32,61 +45,157 @@ class Group:
self.to_dump_distance = None
self.park_to_excavator_distance = None
self.to_excavator_congestion = None
self.to_dump_congestion = None
self.park_to_excavator_congestion = None
# self.to_excavator_congestion = None
# self.to_dump_congestion = None
# self.park_to_excavator_congestion = None
# device map
self.truck_uuid_index_dict = bidict()
self.excavator_uuid_index_dict = bidict()
self.dump_uuid_index_dict = bidict()
# device obj.
self.truck = truck
self.dump =dump
self.excavator = excavator
def update_xx_(self):
def update_group_mode(self):
"""
update above parameters.
update group mode.
:param group_mode:
:return:
"""
pass
# DispatchInfo.update_group_mode()
self.group_mode = DispatchInfo.get_group_mode(self.group_id)
def update_device_map(self):
def update_group_device(self):
"""
update above parameters.
update group devices.
:return:
"""
self.truck_uuid_index_dict = DispatchInfo.dump_group_dict
pass
# update group devices
# DispatchInfo.update_device_group_structure()
self.excavator_dict = DispatchInfo.get_excavator_dict(self.group_id)
self.dump_dict = DispatchInfo.get_dump_dict(self.group_id)
self.truck_set = DispatchInfo.get_truck_set(self.group_id)
def update_road_network_info(self, para):
def update_group_road_network(self):
"""
update group road network.
:return:
"""
pass
return
# update group road network
# DispatchInfo.update_route_distance()
self.to_excavator_distance = DispatchInfo.get_to_excavator_distance(self.group_id)
self.to_dump_distance = DispatchInfo.get_to_dump_distance(self.group_id)
self.park_to_excavator_distance = DispatchInfo.get_park_to_excavator_distance(self.group_id)
def group_dispatch(self, solver):
def update_group_device_map(self):
"""
Receive a alg obj. and output dispatch plan for trucks in this group.
:param solver:
update group device map.
:return:
dispatch plan: Dict({truck_id: match_id})
"""
assert isinstance(solver, AlgorithmBase)
s = solver(self) # algorithm init
for truck_id in self.truck_set:
value = s.solve(truck_id) # algorithm solve
# update device map
excavator_index = 0
for i in self.excavator_dict.keys():
self.excavator_uuid_index_dict[i] = excavator_index + 1
return value
dump_index = 0
for i in self.dump_dict.keys():
self.dump_uuid_index_dict[i] = dump_index + 1
def target_2_match_id(self, target):
pass
truck_index = 0
for i in self.truck_set:
self.truck_uuid_index_dict[i] = truck_index + 1
self.truck_uuid_index_dict = bidict(self.truck_uuid_index_dict)
self.excavator_uuid_index_dict = bidict(self.excavator_uuid_index_dict)
self.dump_uuid_index_dict = bidict(self.dump_uuid_index_dict)
group = Group("group123")
# group_excavator_dict = {group_1: {excavator_1: load_area_1}, group_2: {excavator_2: load_area_2}}
group.group_dispatch(Congestion)
def group_dispatch(self, solver: object):
"""
Receive a alg obj. and output dispatch plan for trucks in this group.
:param solver:
:return:
dispatch plan: Dict({truck_id: match_id})
"""
truck_dispatch = {}
assert issubclass(solver, AlgorithmBase)
s = solver(self) # algorithm init
# update truck task type
for i in self.truck_set:
truck_trip = self.truck.get_truck_current_trip(i)
truck_task = self.truck.get_truck_current_task(i)
if truck_task in [-2, 3, 4]:
next_excavator_list = s.solve(i)
min_index = next_excavator_list.index(min(next_excavator_list)) + 1
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
next_dump_id = truck_trip[-1]
truck_dispatch[i] = [next_excavator_id, next_dump_id]
if truck_task in [0, 1]:
next_dump_list = s.solve(i)
min_index = next_dump_list.index(min(next_dump_list)) + 1
next_dump_id = self.dump_uuid_index_dict.inverse[min_index]
next_excavator_id = truck_trip[-1]
truck_dispatch[i] = [next_excavator_id, next_dump_id]
# return dispatch plan
return truck_dispatch
# from data.dispatchInfo import DispatchInfo
# from bidict import bidict
# from alg.algorithm import AlgorithmBase
#
#
# class Group_0:
# """
# class for group instance.
# """
# def __init__(self, group_id):
# """ Generate a group obj.
# :param group_id: (uuid) group_id
# """
#
# self.group_id = group_id
#
# # group devices
# self.excavator_dict = {} # excavator_id -> unload_area_id
# self.dump_dict = {} # dump_id -> load_area_id
# self.truck_set = set() # truck_id
#
# # road network info.
# self.to_excavator_distance = None
# self.to_dump_distance = None
# self.park_to_excavator_distance = None
#
# self.to_excavator_congestion = None
# self.to_dump_congestion = None
# self.park_to_excavator_congestion = None
#
# # device map
# self.truck_uuid_index_dict = bidict()
# self.excavator_uuid_index_dict = bidict()
# self.dump_uuid_index_dict = bidict()
#
# def update_xx_(self):
# """
# update above parameters.
# :return:
# """
# pass
#
# def group_dispatch(self, solver):
# """
# Receive a alg obj. and output dispatch plan for trucks in this group.
# :param solver:
# :return:
# dispatch plan: Dict({truck_id: match_id})
# """
# assert isinstance(solver, AlgorithmBase)
# s = solver(self) # algorithm init
# return s.solve() # algorithm solve
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/6/9 18:22
# @Author : Opfer
# @Site :
# @File : schedule.py
# @Software: PyCharm
from data.dispatchInfo import DispatchInfo
# from core.group import Group
# from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
import json
import numpy as np
from datetime import datetime, timedelta
class PreSchedule:
""" class for the prediction of equipments' trip.
Description:
负责处理所有预测项的计算与更新
基于矿卡最近一次装卸载时间预测其抵达目的地时间
根据矿卡请求队列及抵达信息,计算设备最早可用时间
Attribute:
equipment class: truck, excavator, dump
schedule start time
equipment available time: truck, excavator, dump
"""
def __init__(self, truck, excavator, dump):
# 设备对象域
self.truck = truck
self.excavator = excavator
self.dump = dump
# 调度开始时间
self.start_time = datetime.now()
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
self.logger = get_logger("zxt.pre_schedule")
def update_truck_reach_time(self):
"""
更新矿卡预计抵达目的地时间
:return:
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
"""
try:
dynamic_excavator_num = self.excavator.get_excavator_num()
dumps = self.dump.get_dump_num()
trucks = self.truck.get_truck_num()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
truck_reach_excavator = self.truck.get_truck_reach_excavator()
truck_reach_dump = self.truck.get_truck_reach_dump()
excavator_avl_ls = [[] for _ in range(dynamic_excavator_num)]
dump_avl_ls = [[] for _ in range(dumps)]
# self.logger.info("update_truck_reach_time-trucks")
# self.logger.info(trucks)
for i in range(trucks):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
# self.logger.info("update_truck_reach_time-truck_current_trip")
# self.logger.info(truck_current_trip)
if task in [0, 1]: # 卡车空载行驶或正在入场
reach_time = truck_reach_excavator[i]
excavator_avl_ls[end_area_index].append(
[reach_time, i, end_area_index]
)
elif task in [3, 4]: # 卡车重载行驶或正在入场
reach_time = truck_reach_dump[i]
dump_avl_ls[end_area_index].append([reach_time, i, end_area_index])
elif task == -2:
self.truck_avl_time[i] = (
datetime.now() - self.start_time
) / timedelta(hours=0, minutes=1, seconds=0)
except Exception as es:
self.logger.error("矿卡预计抵达时间计算异常")
self.logger.error(es)
return [], []
return excavator_avl_ls, dump_avl_ls
def update_excavator_avl_time(self, excavator_avl_ls):
"""
更新挖机预计可用时间
:param
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
# 初始化挖机可用时间
self.excavator_avl_time = np.full(
get_value("dynamic_excavator_num"),
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for excavator_id in get_value("dynamic_excavator_set"):
self.excavator_avl_time_dict[excavator_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
loading_time = self.excavator.get_loading_time()
loading_task_time = self.excavator.get_loading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in excavator_avl_ls:
self.logger.info("update_excavator_avl_time-excavator_avl_ls")
self.logger.info(excavator_avl_ls)
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
excavator_index = int(tmp[i][2])
excavator_id = self.excavator.excavator_index_to_uuid_dict[excavator_index]
self.excavator_avl_time[excavator_index] = (
max(tmp[i][0], self.excavator_avl_time[excavator_index])
+ loading_task_time[excavator_index]
)
self.excavator_avl_time_dict[excavator_id] = self.excavator_avl_time[excavator_index]
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
self.truck_avl_time[truck_index] = self.excavator_avl_time[excavator_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.excavator_avl_time[excavator_index] = now
except Exception as es:
self.logger.error("挖机可用时间计算异常")
self.logger.error(es)
return self.excavator_avl_time_dict
def update_dump_avl_time(self, dump_avl_ls):
"""
更新卸载设备预计可用时间
:param
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
dynamic_dump_num = self.dump.get_dump_num()
# 初始化卸载设备可用时间
self.dump_avl_time = np.full(
dynamic_dump_num,
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for dump_id in get_value("dynamic_dump_set"):
self.dump_avl_time_dict[dump_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
unloading_time = self.dump.get_unloading_time()
unloading_task_time = self.dump.get_unloading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in dump_avl_ls:
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
dump_index = int(tmp[i][2])
dump_id = self.dump.dump_index_to_uuid_dict[dump_index]
self.dump_avl_time[dump_index] = (
max(tmp[i][0], self.dump_avl_time[dump_index])
+ unloading_task_time[dump_index]
)
self.dump_avl_time_dict[dump_id] = self.dump_avl_time[dump_index]
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
self.truck_avl_time[truck_index] = self.dump_avl_time[dump_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.dump_avl_time[dump_index] - now) > 60:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[i][1])] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
except Exception as es:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
return self.dump_avl_time_dict
def _reset(self):
"""
重置设备可用时间
:return:
"""
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
def get_dump_avl_time(self):
"""
获取卸载点最早可用时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
dump_avl_time = self.update_dump_avl_time(dump_avl_ls)
return dump_avl_time
def get_excavator_avl_time(self, excavator_id=None):
"""
获取挖机最早可用时间
:param excavator_id: 挖机编号uuid
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
if excavator_id is not None:
return self.update_excavator_avl_time(excavator_avl_ls) \
[self.excavator.excavator_uuid_to_index_dict[excavator_id]]
else:
return self.update_excavator_avl_time(excavator_avl_ls)
def get_truck_avl_time(self, truck_id=None):
"""
获取矿卡最早可用时间
:param truck_id: 矿卡编号uuid
:return: truck_avl_time: (array) 各矿卡完成当前装载或卸载任务的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
self.update_excavator_avl_time(excavator_avl_ls)
self.update_dump_avl_time(dump_avl_ls)
if truck_id is not None:
return self.truck_avl_time[self.truck.truck_uuid_to_index_dict[truck_id]]
else:
return self.truck_avl_time
\ No newline at end of file
......@@ -128,8 +128,8 @@ class DispatchInfo:
"""
try:
for value in session_postgre.query(DiggingWorkArea).all():
cls.load_exactor_dict[value.Id] = value.Exactorld
cls.exactor_load_dict[value.Exactorld] = value.Id
cls.load_exactor_dict[value.Id] = value.ExactorId
cls.exactor_load_dict[value.ExactorId] = value.Id
except Exception as es:
logger.error("初始化数据更新异常")
logger.error(es)
......@@ -148,9 +148,11 @@ class DispatchInfo:
for item in session_postgre.query(WalkTime).all():
temp = str(item.load_area_id), str(item.unload_area_id), item.to_load_distance, item.to_unload_distance
df = pd.concat([df, pd.DataFrame([temp])], axis=0, ignore_index=True)
for team_id in list(cls.group_dump_dict.keys()):
unload_nums = list(set(cls.group_dump_dict[team_id])) # 获取同一个team_id对应的卸载区列表
exactor_nums = list(set(cls.group_excavator_dict[team_id])) # 获取同一个team_id对应的电铲列表
unload_exactor_matrix = np.zeros(
(len(unload_nums), len(exactor_nums))) # 初始化距离矩阵,记录从卸载区-->>电铲的距离,即to_load_distance,空车模式
load_exactor_matrix = np.array(
......@@ -170,3 +172,200 @@ class DispatchInfo:
except Exception as es:
logger.error("路网数据更新异常")
logger.error(es)
@classmethod
def get_group_mode(cls, group_id):
return cls.group_mode[group_id]
@classmethod
def get_excavator_dict(cls, group_id):
return cls.group_excavator_dict[group_id]
@classmethod
def get_dump_dict(cls, group_id):
return cls.group_dump_dict[group_id]
@classmethod
def get_truck_set(cls, group_id):
return cls.group_truck_dict[group_id]
@classmethod
def get_to_excavator_distance(cls, group_id):
return cls.load_distance[group_id]
@classmethod
def get_to_dump_distance(cls, group_id):
return cls.unload_distance[group_id]
@classmethod
def get_park_to_excavator_distance(cls, group_id):
return cls.park_distance[group_id]
@classmethod
def get_park_to_excavator_distance(cls, group_id):
excavators = cls.group_excavator_dict[group_id]
park_matrix = np.zeros((1, len(excavators)))
for i in range(excavators):
load_area_id = cls.exactor_load_dict[excavators[i]]
distance = session_postgre.query(WalkTimePark).filter_by(load_area_id=load_area_id).first()
park_matrix[0][i] = distance
return park_matrix
# #!E:\Pycharm Projects\Waytous
# # -*- coding: utf-8 -*-
# # @Time : 2022/5/30 14:45
# # @Author : Opfer
# # @Site :
# # @File : dispatchInfo.py
# # @Software: PyCharm
# from settings import *
#
# logger = get_logger("mqc.dispatchInfo")
#
#
# class DispatchInfo:
# """
# class for dispatch group info.
# """
#
# # dispatch groups
# group_set = set()
#
# # device group structure
# group_dump_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
# # {group_id:unload_area_id,...}
# group_excavator_dict = {} # team_id -> dict {[excavator_id, load_area_id], ...}
# # {group_id: [excavator_id, unload_area_id], ...}
# group_truck_dict = {} # team_id -> dict {truck_id, ...}
# # {group_id:[truck_id,truck_id],...}
#
# dump_group_dict = {} # unload_area_id -> team_id
# excavator_group_dict = {} # excavator_id -> team_id
# truck_group_dict = {} # truck_id -> team_id
#
# # group feature
# group_mode = {} # 四种模式:全智能、空车智能、定铲定铲和分流配比模式
# # {mode_name:mode_code}
#
# # route_distance(路网距离)
# load_excavator_distance = {} # 装载区-挖机(电铲)的距离 数据格式 -->> {load_area_id:[excavator_uuid, to_load_distance],}
# unload_excavator_distance = {} # 卸载区-挖机(电铲)的距离 数据格式 -->> {unload_area_id:[excavator_uuid, to_unload_distance],}
#
# @classmethod
# def renew_set(cls):
# """
# @date:2022/6/2 19:50
# @author:maqc
# @desc:实例化对象,可直接访问
# """
# cls.group_dump_dict = {}
# cls.dump_group_dict = {}
#
# cls.group_excavator_dict = {}
# cls.excavator_group_dict = {}
#
# cls.group_truck_dict = {}
# cls.truck_group_dict = {}
#
# cls.group_mode = {}
# cls.load_excavator_distance = {}
# cls.unload_excavator_distance = {}
#
# @classmethod
# def update_device_group_structure(cls):
# """
# @date:2022/6/2 19:49
# @author:maqc
# @desc:分组与卸载区、挖机、矿卡的映射和反映射
# """
# logger = get_logger("mqc.update_device_group_structure")
# try:
# # group_dump_dict = {} -->> {group_id:unload_area_id,...}
# # dump_group_dict = {} # unload_area_id -> team_id
# group_code_dict = {} # group_code-->>team_id的映射
# for valve in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
# group_code_dict[valve.group_code] = valve.team_id
# if valve.team_id not in cls.group_dump_dict:
# cls.group_dump_dict[valve.team_id] = [valve.unload_area_id] # 注意:一个team_id可能对应多个unload_area_id
# else:
# cls.group_dump_dict[valve.team_id].append(valve.unload_area_id)
# cls.dump_group_dict[valve.unload_area_id] = valve.team_id # 一个unload_area_id只对应一个team_id
# # group_excavator_dict = {} -->> {group_id: [excavator_id, unload_area_id], ...} # 一个team_id对应一组excavator_id, unload_area_id
# # excavator_group_dict = {} -->> excavator_id -> team_id 一个excavator_id只对应一个team_id
# for item in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
# # cls.group_excavator_dict[item.team_id] = [item.exactor_id, item.unload_area_id]
# cls.group_excavator_dict[item.team_id] = item.exactor_id
# cls.excavator_group_dict[item.exactor_id] = item.team_id
# # group_truck_dict = {} -->> {group_id:[truck_id,truck_id],...}
# # truck_group_dict = {} -->> truck_id -> team_id
# for key in session_mysql.query(DispatchEquipment).filter_by(group_type=1).all():
# if key.group_code in group_code_dict:
# if key.group_code not in cls.group_truck_dict:
# cls.group_truck_dict[key.group_code] = [key.equipment_id]
# else:
# cls.group_truck_dict[key.group_code].append(key.equipment_id)
# cls.truck_group_dict[key.equipment_id] = group_code_dict[key.group_code]
# except Exception as es:
# logger.error("分组到卸载区的数据更新异常")
# logger.error(es)
#
# @classmethod
# def update_group_mode(cls):
# """
# @date:2022/6/2 19:49
# @author:maqc
# @desc:处理其它类型的数据
# """
# logger = get_logger("mqc.update_group_mode")
# try:
# for value in session_mysql.query(DispatchMode).all():
# cls.group_mode[value.mode_name] = value.mode_code
# except Exception as es:
# logger.error("派车模式数据更新异常")
# logger.error(es)
#
# @classmethod
# def dispatch_group_init(cls):
# """
# update basic paras (group_set, dict, num ...)
# :return:
# """
# pass
#
#
# @classmethod
# def get_group_road_info(cls,group_id, truck_info):
# if truck_info == 1:
# for i in group_excavator():
# pass
# for j in group_dump():
# pass
# if truck_info == 2:
# pass
# @classmethod
# # 距离-->>数据格式:矩阵-->>to_load_distance
# def update_route_distance(cls):
# """
# @date:2022/6/2 19:50
# @author:maqc
# @desc:更新路网距离,返回矩阵格式数据
# """
# load_exactor_dict = {} # 装载区id-->>电铲编号的映射
# logger = get_logger("mqc.update_route_distance")
# try:
# for value in session_postgre.query(DiggingWorkArea).all():
# load_exactor_dict[value.Id] = value.Exactorld
# for value in session_postgre.query(WalkTime).all():
# if value.load_area_id in load_exactor_dict:
# cls.load_excavator_distance[value.load_area_id] = [load_exactor_dict[value.load_area_id],
# value.to_load_distance]
# cls.unload_excavator_distance[value.unload_area_id] = [load_exactor_dict[value.load_area_id],
# value.to_unload_distance]
# except Exception as es:
# logger.error("路网数据更新异常")
# logger.error(es)
#
#
......@@ -14,7 +14,9 @@ from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
import sched
import time
from dispatcher import Dispatcher, PreSchedule
from core.dispatcher import Dispatcher
from core.schedule import PreSchedule
from data.dispatchInfo import DispatchInfo
def process(dispatcher):
......@@ -24,39 +26,52 @@ def process(dispatcher):
:return: None
"""
try:
# 更新周期参数
logger.info("#####################################周期更新开始#####################################")
# try:
# 更新周期参数
logger.info("#####################################周期更新开始#####################################")
global_period_para_update()
global_period_para_update()
if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
raise Exception("无动态派车计划可用")
return
if get_value("dynamic_truck_num") == 0:
raise Exception("无动态派车可用矿卡")
return
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
global_period_para_update()
# 更新数据
DispatchInfo.renew_set()
if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
raise Exception("无动态派车计划可用")
return
if get_value("dynamic_truck_num") == 0:
raise Exception("无动态派车可用矿卡")
return
DispatchInfo.dispatch_group_init()
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
DispatchInfo.update_device_group_structure()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
DispatchInfo.update_route_distance()
# 周期更新
dispatcher.dispatcher_period_update()
DispatchInfo.update_group_mode()
# 调度计算
dispatcher.schedule_construct()
# 调度生成
dispatcher.period_update()
dispatcher.group_generate()
logger.info("#####################################周期更新结束#####################################")
dispatcher.group_dispatch()
except Exception as es:
logger.error("最外层异常捕获")
logger.error(es)
# logger.info("#####################################周期更新结束#####################################")
#
# except Exception as es:
# logger.error("最外层异常捕获")
# logger.error(es)
def perform(inc, dispatcher):
......@@ -103,7 +118,7 @@ if __name__ == "__main__":
pre_sch = PreSchedule(truck, excavator, dump)
# 实例化矿卡调度器
dispatcher = Dispatcher(dump, excavator, truck, pre_sch, False)
dispatcher = Dispatcher(truck, dump, excavator, pre_sch, False)
logger.info(" ")
logger.info("调度系统启动")
......
......@@ -60,15 +60,15 @@ def set_log():
# 创建日志目录
if not os.path.exists(log_path):
os.mkdir(log_path)
# if not os.path.exists(log_path):
# os.mkdir(log_path)
# logging初始化工作
logging.basicConfig()
# timefilehandler = logging.handlers.TimedRotatingFileHandler(log_path + "/dispatch.log", when='M', interval=1, backupCount=60)
filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=3*1024*1024, backupCount=10, encoding="utf-8")
# filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10, encoding="utf-8")
# filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=3*1024*1024, backupCount=10, encoding="utf-8")
filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10, encoding="utf-8")
# 设置后缀名称,跟strftime的格式一样
filehandler.suffix = "%Y-%m-%d_%H-%M.log"
......
......@@ -472,16 +472,16 @@ class DumpArea(Base):
Disabled = Column(Integer)
Materials = Column(VARCHAR(36))
Priority = Column(Integer)
DumpEquipmentld = Column(VARCHAR(36))
DumpEquipmentId = Column(VARCHAR(36))
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentld):
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentId):
self.Id = Id
self.BindList = BindList
self.UnloadAbililty = UnloadAbililty
self.Disabled = Disabled
self.Materials = Materials
self.Priority = Priority
self.DumpEquipmentld = DumpEquipmentld
self.DumpEquipmentId = DumpEquipmentId
class DiggingWorkArea(Base):
......@@ -489,12 +489,12 @@ class DiggingWorkArea(Base):
Id = Column(VARCHAR(50), primary_key=True)
Material = Column(VARCHAR(36))
Exactorld = Column(VARCHAR(36))
ExactorId = Column(VARCHAR(36))
def __init__(self, Id, Material, Exactorld):
def __init__(self, Id, Material, ExactorId):
self.Id = Id
self.Material = Material
self.Exactorld = Exactorld
self.ExactorId = ExactorId
class DispatchRule(Base):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment