Commit c4e5134f authored by 张晓彤's avatar 张晓彤

代码优化v3

parent 8edf3046
...@@ -223,7 +223,7 @@ class ExpectedTime(AlgorithmBase): ...@@ -223,7 +223,7 @@ class ExpectedTime(AlgorithmBase):
self.logger.error(es) self.logger.error(es)
transport_value = np.zeros(group_dynamic_excavator_num) transport_value = np.zeros(group_dynamic_excavator_num)
if task in [1, 2]: if task in [0, 1, 2]:
################################################ 矿卡空载 ############################################### ################################################ 矿卡空载 ###############################################
# try: # try:
...@@ -290,7 +290,7 @@ class ExpectedTime(AlgorithmBase): ...@@ -290,7 +290,7 @@ class ExpectedTime(AlgorithmBase):
self.logger.error(es) self.logger.error(es)
transport_value = np.zeros(group_dynamic_unload_area_num) transport_value = np.zeros(group_dynamic_unload_area_num)
elif task in [4, 5]: elif task in [3, 4, 5]:
################################################ 矿卡重载 ############################################### ################################################ 矿卡重载 ###############################################
# try: # try:
...@@ -369,6 +369,9 @@ class DistributionRatio(object): ...@@ -369,6 +369,9 @@ class DistributionRatio(object):
@desc:计算分流配比模式下,卡车与卸载区的对应关系 @desc:计算分流配比模式下,卡车与卸载区的对应关系
""" """
# TODO:
# 统一与预期等待时间的接口
def __init__(self, exactor_id, truck): def __init__(self, exactor_id, truck):
self.truck = truck self.truck = truck
self.exactor_id = exactor_id self.exactor_id = exactor_id
......
...@@ -10,6 +10,8 @@ from flask_caching import Cache ...@@ -10,6 +10,8 @@ from flask_caching import Cache
from alg.algorithm import ExpectedTime from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo from data.dispatchInfo import DispatchInfo
from core.submit import DispatchSubmission from core.submit import DispatchSubmission
from core.group import GroupDispatcher
from realtime_dispatch import group_direct2redis
config = { config = {
"DEBUG": True, # some Flask specific configs "DEBUG": True, # some Flask specific configs
...@@ -140,9 +142,29 @@ def dispatch_request(): ...@@ -140,9 +142,29 @@ def dispatch_request():
try: try:
# # 调度分组派车计划计算
# try:
# truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度计算异常')
#
# try:
#
# logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
# submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度写入异常')
# 调度分组派车计划计算 # 调度分组派车计划计算
try: try:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime) group_dispatcher = GroupDispatcher(group)
truck_dispatch_plan_dict = group_dispatcher.group_dispatch(ExpectedTime)
if truck_dispatch_plan_dict is None:
logger.error(f'分组 {group.group_id} 调度异常')
except Exception as es: except Exception as es:
logger.error(es) logger.error(es)
logger.error(f'分组{group.group_id} 调度计算异常') logger.error(f'分组{group.group_id} 调度计算异常')
...@@ -152,9 +174,11 @@ def dispatch_request(): ...@@ -152,9 +174,11 @@ def dispatch_request():
logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}') logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict) submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
except Exception as es: except Exception as es:
group_direct2redis(group)
logger.error(es) logger.error(es)
logger.error(f'分组{group.group_id} 调度写入异常') logger.error(f'分组{group.group_id} 调度写入异常')
except Exception as es: except Exception as es:
logger.error("最外层异常捕获") logger.error("最外层异常捕获")
logger.error(es) logger.error(es)
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/10/29 22:07
# @Author : Opfer
# @Site :
# @File : __init__.py
# @Software: PyCharm
\ No newline at end of file
...@@ -131,12 +131,12 @@ class Group: ...@@ -131,12 +131,12 @@ class Group:
update group devices. update group devices.
:return: :return:
""" """
# update group devices # init group devices
# DispatchInfo.update_device_group_structure()
self.group_excavators = {} self.group_excavators = {}
self.group_unload_areas = {} self.group_unload_areas = {}
self.group_dumps = {} self.group_dumps = {}
self.group_trucks = set() self.group_trucks = set()
# update group devices
self.group_excavators = DispatchInfo.get_excavator(self.group_id) self.group_excavators = DispatchInfo.get_excavator(self.group_id)
self.group_unload_areas = DispatchInfo.get_unload_area(self.group_id) self.group_unload_areas = DispatchInfo.get_unload_area(self.group_id)
self.group_dumps = DispatchInfo.get_dump(self.group_id) self.group_dumps = DispatchInfo.get_dump(self.group_id)
...@@ -147,10 +147,11 @@ class Group: ...@@ -147,10 +147,11 @@ class Group:
update group road network. update group road network.
:return: :return:
""" """
# DispatchInfo.update_route_distance() # init group road network
self.to_excavator_distance = None self.to_excavator_distance = None
self.to_unload_area_distance = None self.to_unload_area_distance = None
self.park_to_excavator_distance = None self.park_to_excavator_distance = None
# update group road network
self.to_excavator_distance = DispatchInfo.get_to_excavator_distance(self.group_id) self.to_excavator_distance = DispatchInfo.get_to_excavator_distance(self.group_id)
self.to_unload_area_distance = DispatchInfo.get_to_unload_area_distance(self.group_id) self.to_unload_area_distance = DispatchInfo.get_to_unload_area_distance(self.group_id)
self.park_to_excavator_distance = DispatchInfo.get_park_to_excavator_distance(self.group_id) self.park_to_excavator_distance = DispatchInfo.get_park_to_excavator_distance(self.group_id)
...@@ -160,11 +161,9 @@ class Group: ...@@ -160,11 +161,9 @@ class Group:
update group device map. update group device map.
:return: :return:
""" """
# excavator_index = 0 # update devices(excavators, unload_areas, dumps) bidirectional map within a group
self.excavator_uuid_index_dict = DispatchInfo.get_group_excavator_dict(self.group_id) self.excavator_uuid_index_dict = DispatchInfo.get_group_excavator_dict(self.group_id)
self.unload_area_uuid_index_dict = DispatchInfo.get_group_unload_area_dict(self.group_id) self.unload_area_uuid_index_dict = DispatchInfo.get_group_unload_area_dict(self.group_id)
# self.truck_uuid_index_dict = DispatchInfo.get_group_truck_dict(self.group_id)
self.dump_uuid_index_dict = DispatchInfo.get_group_dump_dict(self.group_id) self.dump_uuid_index_dict = DispatchInfo.get_group_dump_dict(self.group_id)
def update_device_material(self): def update_device_material(self):
...@@ -236,19 +235,31 @@ class Group: ...@@ -236,19 +235,31 @@ class Group:
class GroupDispatcher: class GroupDispatcher:
"""
Group controller responsible for group dispatching.
"""
def __init__(self, group: Group): def __init__(self, group: Group):
"""
Receive a group obj.
:param group:
"""
self.logger = logging.getLogger("zxt.GroupDispatcher") self.logger = logging.getLogger("zxt.GroupDispatcher")
self.group = group self.group = group
self.redispatcher = ReDispatcher(self.group)
def group_dispatch(self, Solver) -> Mapping[str, List[str]]: def group_dispatch(self, Solver) -> Mapping[str, List[str]]:
""" """
Receive a Alg obj. and output dispatch plan for trucks in this group. Receive a Alg obj. and output dispatch plan for all trucks within this group.
:param Solver: :param Solver:
:return: :return:
dispatch plan: Dict({truck_id: match_id}) dispatch plan: Dict({truck_id: match_id})
""" """
# init truck dispatch plan dictionary.
truck_dispatch = {} truck_dispatch = {}
# init dictionary including all truck obj. within this group.
self.group.truck_info_list = {} self.group.truck_info_list = {}
assert issubclass(Solver, AlgorithmBase) assert issubclass(Solver, AlgorithmBase)
...@@ -262,44 +273,31 @@ class GroupDispatcher: ...@@ -262,44 +273,31 @@ class GroupDispatcher:
# try: # try:
# get truck index from mapping # get truck index from mapping
try:
if truck_id not in self.group.truck.truck_uuid_to_index_dict: if truck_id not in self.group.truck.truck_uuid_to_index_dict:
raise CoreException(102, f'truck.truck dict 中不存在 {truck_id}') self.logger.error(f'truck.truck dict 中不存在 {truck_id}')
truck_idx = self.group.truck.truck_uuid_to_index_dict[truck_id]
except CoreException as es:
es.with_traceback_info()
self.logger.error(es)
continue continue
else:
truck_idx = self.group.truck.truck_uuid_to_index_dict[truck_id]
# get truck trip from truck obj. # get truck trip from truck obj.
try:
truck_trip_info_list = self.group.truck.get_truck_current_trip() truck_trip_info_list = self.group.truck.get_truck_current_trip()
if truck_idx >= len(truck_trip_info_list): if truck_idx >= len(truck_trip_info_list):
raise CoreException(103, f'truck.truck trip 中不存在 {truck_idx} 号矿卡 {truck_id}') self.logger.error(f'truck.truck trip 中不存在 {truck_idx} 号矿卡 {truck_id}')
truck_trip = self.group.truck.get_truck_current_trip()[truck_idx]
except CoreException as es:
es.with_traceback_info()
self.logger.error(es)
continue continue
else:
truck_trip = self.group.truck.get_truck_current_trip()[truck_idx]
# get truck task from truck obj. # get truck task from truck obj.
try:
truck_task_list = self.group.truck.get_truck_current_task() truck_task_list = self.group.truck.get_truck_current_task()
if truck_id not in truck_task_list: if truck_id not in truck_task_list:
raise CoreException(102, f'truck.truck task 中不存在矿卡 {truck_id}') self.logger.error(f'truck.truck task 中不存在矿卡 {truck_id}')
truck_task = truck_task_list[truck_id]
except CoreException as es:
es.with_traceback_info()
self.logger.error(es)
continue continue
else:
truck_task = truck_task_list[truck_id]
# Construct a truck obj. # Construct a truck obj. and add it to group truck dictionary.
truck_info = CurrentTruck(truck_id, self.group.group_id, truck_trip, truck_task, truck_info = CurrentTruck(truck_id, self.group.group_id, truck_trip, truck_task,
self.group.truck.get_truck_current_state()[truck_id]) self.group.truck.get_truck_current_state()[truck_id])
...@@ -320,7 +318,7 @@ class GroupDispatcher: ...@@ -320,7 +318,7 @@ class GroupDispatcher:
# 全智能模式 # 全智能模式
if self.group.group_mode == 1: if self.group.group_mode == 1:
self.logger.info("全智能模式调度") self.logger.info("全智能模式调度")
self.full_dynamic_mode(truck_id, solver, truck_dispatch, truck_info, truck_task, truck_trip) self.full_dynamicWW_mode(truck_id, solver, truck_dispatch, truck_info, truck_task, truck_trip)
# 空车智能模式 # 空车智能模式
elif self.group.group_mode == 2: elif self.group.group_mode == 2:
...@@ -341,6 +339,7 @@ class GroupDispatcher: ...@@ -341,6 +339,7 @@ class GroupDispatcher:
self.ratio_mode(truck_id, truck_dispatch, truck_task) self.ratio_mode(truck_id, truck_dispatch, truck_task)
except Exception as es: except Exception as es:
self.logger.error("调度调用异常")
self.logger.error(es) self.logger.error(es)
# return dispatch plan # return dispatch plan
...@@ -356,7 +355,6 @@ class GroupDispatcher: ...@@ -356,7 +355,6 @@ class GroupDispatcher:
next_unload_area_id = "Park" next_unload_area_id = "Park"
# 空载模式下,计算下一次卸载区的位置,按照分流配比的模式进行计算 # 空载模式下,计算下一次卸载区的位置,按照分流配比的模式进行计算
elif truck_task in [0, 1, 2]: elif truck_task in [0, 1, 2]:
try: try:
...@@ -375,7 +373,6 @@ class GroupDispatcher: ...@@ -375,7 +373,6 @@ class GroupDispatcher:
self.logger.error(es) self.logger.error(es)
# 重载模式下,按照固定派车进行计算 # 重载模式下,按照固定派车进行计算
elif truck_task in [3, 4, 5]: elif truck_task in [3, 4, 5]:
try: try:
...@@ -390,6 +387,10 @@ class GroupDispatcher: ...@@ -390,6 +387,10 @@ class GroupDispatcher:
truck_dispatch[i] = [next_exactor_id, next_unload_area_id] truck_dispatch[i] = [next_exactor_id, next_unload_area_id]
def semi_dynamic_mode(self, i, s, truck_dispatch, truck_info, truck_task, truck_trip): def semi_dynamic_mode(self, i, s, truck_dispatch, truck_info, truck_task, truck_trip):
# TODO:
# 和全智能调度很像,是否可以合并合;
# 加入二次调度;
if truck_task in [-2, 3, 4, 5]: if truck_task in [-2, 3, 4, 5]:
try: try:
...@@ -516,7 +517,8 @@ class GroupDispatcher: ...@@ -516,7 +517,8 @@ class GroupDispatcher:
if (truck_locate in self.group.topo.cross_bf_lanes) and (self.group.truck.truck_current_state[i] == 2): if (truck_locate in self.group.topo.cross_bf_lanes) and (self.group.truck.truck_current_state[i] == 2):
self.logger.info("触发二次调度") self.logger.info("触发二次调度")
self.redispatch_to_excavator(i, truck_dispatch, truck_locate) # self.redispatch_to_excavator(i, truck_dispatch, truck_locate)
self.redispatcher.redispatch_to_excavator(i, truck_dispatch, truck_locate)
elif truck_task == 3: elif truck_task == 3:
try: try:
...@@ -537,71 +539,185 @@ class GroupDispatcher: ...@@ -537,71 +539,185 @@ class GroupDispatcher:
if (truck_locate in self.group.topo.cross_bf_lanes) and (self.group.truck.truck_current_state[i] == 2) \ if (truck_locate in self.group.topo.cross_bf_lanes) and (self.group.truck.truck_current_state[i] == 2) \
and (not truck_is_temp): and (not truck_is_temp):
self.redispatch_to_dump(i, truck_dispatch, truck_locate, truck_trip) # self.redispatch_to_dump(i, truck_dispatch, truck_locate, truck_trip)
self.redispatcher.redispatch_to_dump(i, truck_dispatch, truck_locate, truck_trip)
# def redispatch_to_dump(self, truck_id: str, truck_dispatch: Mapping[str, List[str]], truck_locate: str, truck_trip: List[int]):
# """
# redispatch truck to dumps.
# :param truck_id:
# :param truck_dispatch:
# :param truck_locate:
# :param truck_trip:
# :return:
# """
# # 当前绑定装载区
# if truck_trip[0] == -1:
# next_excavator_id = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id,
# isdeleted=0).first().exactor_id
# else:
# next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[0]]
# # 当前绑定卸载区
# if truck_trip[-1] == -1:
# item = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, isdeleted=0).first()
# current_dump_id = item.dump_id
# current_unload_area_id = item.unload_area_id
# else:
# current_dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
# current_unload_area_id = DispatchInfo.dump_unload_area_dict[current_dump_id]
# unload_area_dict, unload_area_lane_dict = self.group.topo.get_unload_target_node_real(truck_locate,
# current_unload_area_id,
# True)
# # 获取拥堵路段
# congestion_lane_dict = self.get_congestion_lanes()
# # 获取当前交叉口下一路段集合
# next_lane_list = get_cross_next_lanes(truck_locate)
# # 交叉口下一路段可达的装载区
# next_lane_load_area_dict = get_lane_reach_load_areas(unload_area_lane_dict,
# next_lane_list)
# # 排除下一个路段阻塞的装载区
# delete_congestion_load_area(congestion_lane_dict, unload_area_dict,
# next_lane_load_area_dict)
# min_trip_time = 10000000
# best_dump_id = current_dump_id
# for unload_area, value in unload_area_dict.items():
# # 车辆不需要掉头
# if value[-1] == 1 and unload_area in DispatchInfo.unload_area_dump_dict:
# dump_id = DispatchInfo.unload_area_dump_dict[unload_area]
#
# traveling_time = value[0] / heavy_speed
#
# now = float(
# (datetime.now() - self.group.pre_sch.start_time) / timedelta(hours=0, minutes=1,
# seconds=0))
# reach_time = now + traveling_time
#
# trip_time = max(reach_time,
# self.group.pre_sch.get_dump_avl_time()[dump_id]) - now
#
# if min_trip_time > trip_time:
# best_dump_id = dump_id
# next_unload_area_id = DispatchInfo.dump_unload_area_dict[best_dump_id]
# truck_dispatch[truck_id] = [next_excavator_id, next_unload_area_id]
# # res = redispatch_request(truck_id, next_excavator_id, next_unload_area_id)
# # self.logger.info(res)
# self.logger.info(f'二次调度结果 {truck_id}')
# self.logger.info(truck_dispatch[truck_id])
#
# def redispatch_to_excavator(self, truck_id, truck_dispatch, truck_locate):
# """
# redispatch truck to excavators.
# :param truck_id:
# :param truck_dispatch:
# :param truck_locate:
# :return:
# """
# # 当前绑定卸载区
# # if truck_trip[0] == -1:
# next_unload_area_id = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id,
# isdeleted=0).first().unload_area_id
# # else:
# # dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[0]]
# # next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
# # 当前绑定装载区
# # if truck_trip[-1] == -1:
# item = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, isdeleted=0).first()
# current_excavator_id = item.exactor_id
# current_load_area_id = item.load_area_id
# self.logger.info(f'truck_id {truck_id}')
# self.logger.info(f'current_load_area_id {current_load_area_id}')
# # else:
# # current_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[-1]]
# # current_load_area_id = DispatchInfo.excavator_load_dict[current_excavator_id]
# load_area_dict, load_area_lane_dict = self.group.topo.get_load_target_node_real(truck_locate,
# current_load_area_id, True)
# self.logger.info("所有可达装载区")
# self.logger.info(load_area_dict)
# # 获取拥堵路段
# congestion_lane_dict = self.get_congestion_lanes()
# # 获取当前交叉口下一路段集合
# next_lane_list = get_cross_next_lanes(truck_locate)
# # 交叉口下一路段可达的装载区
# next_lane_load_area_dict = get_lane_reach_load_areas(load_area_lane_dict, next_lane_list)
# # 排除下一个路段阻塞的装载区
# delete_congestion_load_area(congestion_lane_dict, load_area_dict,
# next_lane_load_area_dict)
# self.logger.info("剔除堵塞装载区")
# self.logger.info(load_area_dict)
# # 获取最佳挖机
# best_excavator_id = self.get_best_excavator(current_excavator_id, truck_id, load_area_dict)
# next_excavator_id = best_excavator_id
# truck_dispatch[truck_id] = [next_excavator_id, next_unload_area_id]
# self.logger.info(f'二次调度结果 {truck_id}')
# self.logger.info(truck_dispatch[truck_id])
#
# def get_best_excavator(self, current_excavator_id, truck_id, load_area_dict):
# """
# get best group_excavators
# :param current_excavator_id: 当前车辆配对挖机
# :param truck_id:
# :param load_area_dict: 备选装载区
# :return:
# """
# min_trip_time = 10000000
# best_excavator_id = current_excavator_id
# try:
# for load_area, value in load_area_dict.items():
# # 车辆不需要掉头
# if load_area in DispatchInfo.load_excavator_dict:
# excavator_id = DispatchInfo.load_excavator_dict[load_area]
# else:
# continue
# if value[-1] == 1 and excavator_id in self.group.group_excavators:
# traveling_time = 60 * (value[0] / 1000) / empty_speed
#
# self.logger.info(f'load_area {load_area}')
# self.logger.info(f'traveling_time {traveling_time}')
#
# now = float(
# (datetime.now() - self.group.pre_sch.start_time) / timedelta(hours=0, minutes=1, seconds=0))
#
# reach_time = now + traveling_time
#
# self.logger.info(f'reach_time {reach_time}')
#
# trip_time = max(reach_time,
# self.group.pre_sch.get_excavator_avl_time(truck_id=truck_id)[excavator_id]) - now
#
# self.logger.info(f'trip_time {trip_time}')
#
# if min_trip_time > trip_time:
# best_excavator_id = excavator_id
# min_trip_time = trip_time
#
# except Exception as es:
# self.logger.error("寻找最佳装载区异常")
# self.logger.error(f'exception {es}')
# self.logger.error(f'in line {es.__traceback__.tb_lineno}')
# return best_excavator_id
#
# def get_congestion_lanes(self):
# # 存在车辆拥堵的路段
# truck_locate_dict = self.group.truck.get_truck_locate_dict()
# congestion_lane_list = []
# for key, value in truck_locate_dict.items():
# if self.group.truck.truck_current_state[key] == 2:
# congestion_lane_list.append(value)
#
# print("congestion_lane_list")
# print(list(set(congestion_lane_list)))
# return list(set(congestion_lane_list))
def redispatch_to_dump(self, truck_id, truck_dispatch, truck_locate, truck_trip): class ReDispatcher:
""" """
redispatch truck to dumps. redispatch controller
:param truck_id:
:param truck_dispatch:
:param truck_locate:
:param truck_trip:
:return:
""" """
# 当前绑定装载区 def __init__(self, group: Group):
if truck_trip[0] == -1: self.logger = get_logger("zxt.ReDispatcher")
next_excavator_id = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, self.group = group
isdeleted=0).first().exactor_id
else:
next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[0]]
# 当前绑定卸载区
if truck_trip[-1] == -1:
item = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, isdeleted=0).first()
current_dump_id = item.dump_id
current_unload_area_id = item.unload_area_id
else:
current_dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
current_unload_area_id = DispatchInfo.dump_unload_area_dict[current_dump_id]
unload_area_dict, unload_area_lane_dict = self.group.topo.get_unload_target_node_real(truck_locate,
current_unload_area_id,
True)
# 获取拥堵路段
congestion_lane_dict = self.get_congestion_lanes()
# 获取当前交叉口下一路段集合
next_lane_list = get_cross_next_lanes(truck_locate)
# 交叉口下一路段可达的装载区
next_lane_load_area_dict = get_lane_reach_load_areas(unload_area_lane_dict,
next_lane_list)
# 排除下一个路段阻塞的装载区
delete_congestion_load_area(congestion_lane_dict, unload_area_dict,
next_lane_load_area_dict)
min_trip_time = 10000000
best_dump_id = current_dump_id
for unload_area, value in unload_area_dict.items():
# 车辆不需要掉头
if value[-1] == 1 and unload_area in DispatchInfo.unload_area_dump_dict:
dump_id = DispatchInfo.unload_area_dump_dict[unload_area]
traveling_time = value[0] / heavy_speed
now = float(
(datetime.now() - self.group.pre_sch.start_time) / timedelta(hours=0, minutes=1,
seconds=0))
reach_time = now + traveling_time
trip_time = max(reach_time,
self.group.pre_sch.get_dump_avl_time()[dump_id]) - now
if min_trip_time > trip_time:
best_dump_id = dump_id
next_unload_area_id = DispatchInfo.dump_unload_area_dict[best_dump_id]
truck_dispatch[truck_id] = [next_excavator_id, next_unload_area_id]
# res = redispatch_request(truck_id, next_excavator_id, next_unload_area_id)
# self.logger.info(res)
self.logger.info(f'二次调度结果 {truck_id}')
self.logger.info(truck_dispatch[truck_id])
def redispatch_to_excavator(self, truck_id, truck_dispatch, truck_locate): def redispatch_to_excavator(self, truck_id: str, truck_dispatch: Mapping[str, List[str]], truck_locate: str):
""" """
redispatch truck to excavators. redispatch truck to excavators.
:param truck_id: :param truck_id:
...@@ -628,6 +744,9 @@ class GroupDispatcher: ...@@ -628,6 +744,9 @@ class GroupDispatcher:
# current_load_area_id = DispatchInfo.excavator_load_dict[current_excavator_id] # current_load_area_id = DispatchInfo.excavator_load_dict[current_excavator_id]
load_area_dict, load_area_lane_dict = self.group.topo.get_load_target_node_real(truck_locate, load_area_dict, load_area_lane_dict = self.group.topo.get_load_target_node_real(truck_locate,
current_load_area_id, True) current_load_area_id, True)
# TODO
# topo 放到 group 里面不太合理
self.logger.info("所有可达装载区") self.logger.info("所有可达装载区")
self.logger.info(load_area_dict) self.logger.info(load_area_dict)
# 获取拥堵路段 # 获取拥堵路段
...@@ -648,120 +767,69 @@ class GroupDispatcher: ...@@ -648,120 +767,69 @@ class GroupDispatcher:
self.logger.info(f'二次调度结果 {truck_id}') self.logger.info(f'二次调度结果 {truck_id}')
self.logger.info(truck_dispatch[truck_id]) self.logger.info(truck_dispatch[truck_id])
def get_best_excavator(self, current_excavator_id, truck_id, load_area_dict): def redispatch_to_dump(self, truck_id: str, truck_dispatch: Mapping[str, List[str]], truck_locate: str, truck_trip: List[int]):
"""
get best group_excavators
:param current_excavator_id: 当前车辆配对挖机
:param truck_id:
:param load_area_dict: 备选装载区
:return:
"""
min_trip_time = 10000000
best_excavator_id = current_excavator_id
try:
for load_area, value in load_area_dict.items():
# 车辆不需要掉头
if load_area in DispatchInfo.load_excavator_dict:
excavator_id = DispatchInfo.load_excavator_dict[load_area]
else:
continue
if value[-1] == 1 and excavator_id in self.group.group_excavators:
traveling_time = 60 * (value[0] / 1000) / empty_speed
self.logger.info(f'load_area {load_area}')
self.logger.info(f'traveling_time {traveling_time}')
now = float(
(datetime.now() - self.group.pre_sch.start_time) / timedelta(hours=0, minutes=1, seconds=0))
reach_time = now + traveling_time
self.logger.info(f'reach_time {reach_time}')
trip_time = max(reach_time,
self.group.pre_sch.get_excavator_avl_time(truck_id=truck_id)[excavator_id]) - now
self.logger.info(f'trip_time {trip_time}')
if min_trip_time > trip_time:
best_excavator_id = excavator_id
min_trip_time = trip_time
except Exception as es:
self.logger.error("寻找最佳装载区异常")
self.logger.error(f'exception {es}')
self.logger.error(f'in line {es.__traceback__.tb_lineno}')
return best_excavator_id
def get_congestion_lanes(self):
# 存在车辆拥堵的路段
truck_locate_dict = self.group.truck.get_truck_locate_dict()
congestion_lane_list = []
for key, value in truck_locate_dict.items():
if self.group.truck.truck_current_state[key] == 2:
congestion_lane_list.append(value)
print("congestion_lane_list")
print(list(set(congestion_lane_list)))
return list(set(congestion_lane_list))
class ReDispatcher:
"""
redispatch controller
"""
def __init__(self, group: Group):
self.logger = get_logger("zxt.ReDispatcher")
self.group = group
def redispatch_to_excavator(self, truck_id, truck_dispatch, truck_locate):
""" """
redispatch truck to excavators. redispatch truck to dumps.
:param truck_id: :param truck_id:
:param truck_dispatch: :param truck_dispatch:
:param truck_locate: :param truck_locate:
:param truck_trip:
:return: :return:
""" """
# 当前绑定卸载区
# if truck_trip[0] == -1:
next_unload_area_id = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id,
isdeleted=0).first().unload_area_id
# else:
# dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[0]]
# next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
# 当前绑定装载区 # 当前绑定装载区
# if truck_trip[-1] == -1: if truck_trip[0] == -1:
next_excavator_id = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id,
isdeleted=0).first().exactor_id
else:
next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[0]]
# 当前绑定卸载区
if truck_trip[-1] == -1:
item = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, isdeleted=0).first() item = session_mysql.query(EquipmentPair).filter_by(truck_id=truck_id, isdeleted=0).first()
current_excavator_id = item.exactor_id current_dump_id = item.dump_id
current_load_area_id = item.load_area_id current_unload_area_id = item.unload_area_id
self.logger.info(f'truck_id {truck_id}') else:
self.logger.info(f'current_load_area_id {current_load_area_id}') current_dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
# else: current_unload_area_id = DispatchInfo.dump_unload_area_dict[current_dump_id]
# current_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[-1]] unload_area_dict, unload_area_lane_dict = self.group.topo.get_unload_target_node_real(truck_locate,
# current_load_area_id = DispatchInfo.excavator_load_dict[current_excavator_id] current_unload_area_id,
load_area_dict, load_area_lane_dict = self.group.topo.get_load_target_node_real(truck_locate, True)
current_load_area_id, True)
self.logger.info("所有可达装载区")
self.logger.info(load_area_dict)
# 获取拥堵路段 # 获取拥堵路段
congestion_lane_dict = self.get_congestion_lanes() congestion_lane_dict = self.get_congestion_lanes()
# 获取当前交叉口下一路段集合 # 获取当前交叉口下一路段集合
next_lane_list = get_cross_next_lanes(truck_locate) next_lane_list = get_cross_next_lanes(truck_locate)
# 交叉口下一路段可达的装载区 # 交叉口下一路段可达的装载区
next_lane_load_area_dict = get_lane_reach_load_areas(load_area_lane_dict, next_lane_list) next_lane_load_area_dict = get_lane_reach_load_areas(unload_area_lane_dict,
next_lane_list)
# 排除下一个路段阻塞的装载区 # 排除下一个路段阻塞的装载区
delete_congestion_load_area(congestion_lane_dict, load_area_dict, delete_congestion_load_area(congestion_lane_dict, unload_area_dict,
next_lane_load_area_dict) next_lane_load_area_dict)
self.logger.info("剔除堵塞装载区") min_trip_time = 10000000
self.logger.info(load_area_dict) best_dump_id = current_dump_id
# 获取最佳挖机 for unload_area, value in unload_area_dict.items():
best_excavator_id = self.get_best_excavator(current_excavator_id, truck_id, load_area_dict) # 车辆不需要掉头
next_excavator_id = best_excavator_id if value[-1] == 1 and unload_area in DispatchInfo.unload_area_dump_dict:
dump_id = DispatchInfo.unload_area_dump_dict[unload_area]
traveling_time = value[0] / heavy_speed
now = float(
(datetime.now() - self.group.pre_sch.start_time) / timedelta(hours=0, minutes=1,
seconds=0))
reach_time = now + traveling_time
trip_time = max(reach_time,
self.group.pre_sch.get_dump_avl_time()[dump_id]) - now
if min_trip_time > trip_time:
best_dump_id = dump_id
next_unload_area_id = DispatchInfo.dump_unload_area_dict[best_dump_id]
truck_dispatch[truck_id] = [next_excavator_id, next_unload_area_id] truck_dispatch[truck_id] = [next_excavator_id, next_unload_area_id]
# res = redispatch_request(truck_id, next_excavator_id, next_unload_area_id)
# self.logger.info(res)
self.logger.info(f'二次调度结果 {truck_id}') self.logger.info(f'二次调度结果 {truck_id}')
self.logger.info(truck_dispatch[truck_id]) self.logger.info(truck_dispatch[truck_id])
def get_best_excavator(self, current_excavator_id, truck_id, load_area_dict): def get_best_excavator(self, current_excavator_id: str, truck_id: str, load_area_dict):
""" """
get best group_excavators get best group_excavators
:param current_excavator_id: 当前车辆配对挖机 :param current_excavator_id: 当前车辆配对挖机
......
...@@ -120,6 +120,9 @@ class DispatchSubmission: ...@@ -120,6 +120,9 @@ class DispatchSubmission:
record = redis_format(truck_id, group_id, str(uuid.uuid1()), item) record = redis_format(truck_id, group_id, str(uuid.uuid1()), item)
# TODO:
# 判断了两次是否拥堵,需要改善
# 车辆重载等待,且前方道路阻塞 # 车辆重载等待,且前方道路阻塞
if task == 3 and state == 2 and truck_id in self.truck.get_truck_locate_dict() and \ if task == 3 and state == 2 and truck_id in self.truck.get_truck_locate_dict() and \
self.truck.get_truck_locate_dict()[truck_id] in self.topo.cross_bf_lanes: self.truck.get_truck_locate_dict()[truck_id] in self.topo.cross_bf_lanes:
......
...@@ -18,6 +18,7 @@ from core.dispatcher import Dispatcher ...@@ -18,6 +18,7 @@ from core.dispatcher import Dispatcher
from core.schedule import PreSchedule from core.schedule import PreSchedule
from data.dispatchInfo import DispatchInfo from data.dispatchInfo import DispatchInfo
from util import CoreException from util import CoreException
from core.group import Group
def direct2redis(): def direct2redis():
...@@ -35,7 +36,7 @@ def direct2redis(): ...@@ -35,7 +36,7 @@ def direct2redis():
try: try:
truck_disp = {} truck_disp = []
for item in session_mysql.query(DispatchSetting).filter_by(isdeleted=0, ).all(): for item in session_mysql.query(DispatchSetting).filter_by(isdeleted=0, ).all():
if item is None: if item is None:
raise CoreException(101, "无可用派车计划") raise CoreException(101, "无可用派车计划")
...@@ -49,6 +50,41 @@ def direct2redis(): ...@@ -49,6 +50,41 @@ def direct2redis():
# 写入redis # 写入redis
redis5.set(item.truck_id, str(json.dumps(record))) redis5.set(item.truck_id, str(json.dumps(record)))
truck_disp.append(item.truck_id)
except CoreException as ce:
logger.error(ce)
session_postgre.rollback()
session_mysql.rollback()
def group_direct2redis(group: Group):
"""
根据分组车辆直接读取数据库写入redis
:return: None
"""
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
try:
for truck_id in group.group_trucks:
item = session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first()
if item is None:
raise CoreException(101, "无可用派车计划")
record = {"truckId": item.truck_id, "dispatchId": item.id, "exactorId": item.exactor_id,
"dumpId": item.dump_id, "loadAreaId": item.load_area_id, "unloadAreaId": item.unload_area_id,
"groupId": item.group_id, "isdeleted": False, "isTemp": False, "haulFlag": -1,
"groupName": DispatchInfo.group_name[item.group_id]}
logger.info(f'写入redis调度结果: {record}')
# 写入redis
redis5.set(item.truck_id, str(json.dumps(record)))
except CoreException as ce: except CoreException as ce:
logger.error(ce) logger.error(ce)
session_postgre.rollback() session_postgre.rollback()
......
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