Unverified Commit f6a1750a authored by Allvey's avatar Allvey Committed by GitHub

Merge pull request #2 from Allvey/github

GitHub
parents bbbfd63c 742b6428
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 16:32
# @Author : Opfer
# @Site :
# @File : alg.py
# @Software: PyCharm
from para_config import *
from equipment import ExcavatorInfo, DumpInfo, TruckInfo
# from core.group import Group
from core.schedule import PreSchedule
class AlgorithmBase:
"""
Base class for dispatch alg.
"""
def __init__(self):
pass
def solve(self, *args, **kwargs):
"""
Dispatching calculation for subgroups.
"""
raise NotImplementedError
class Congestion(AlgorithmBase):
"""
class for congestion alg.
"""
def __init__(self, group):
super().__init__()
self.group = group
self.logger = get_logger("zxt.algorithm.congestion")
def solve(self, truck_id):
"""
Receive a truck_id and calculate the associated route congestion.
:param truck_id: (uuid)
:return: congestion_value
"""
try:
truck_index = truck.truck_uuid_to_index_dict[truck_id]
trip = truck.get_truck_current_trip()[truck_index]
task = truck.get_truck_current_task()[truck_id]
group_dynamic_excavator_num = len(self.group.dump_dict)
group_dynamic_dump_num = len(self.group.excavator_dict)
except Exception as es:
self.logger.error("车辆调度信息读取异常")
self.logger.error(es)
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
transport_value = self.group.park_to_excavator_congestion
except Exception as es:
transport_value = np.zeros(group_dynamic_excavator_num)
self.logger.info(es)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DumpInfo.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 车辆所在挖机 uuid
excavator_id = DeviceMap.excavator_index_to_uuid_dict[int(trip[1])]
# 挖机所在分组序号 index
excavator_group_index = self.group.excavator_uuid_index_dict[excavator_id]
transport_value = self.group.to_dump_congestion[excavator_group_index, :]
except Exception as es:
self.logger.error("矿卡空载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_dump_num)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 车辆所在卸点
dump_id = DeviceMap.dump_index_to_uuid_dict[int(trip[1])]
# 卸点对应分组编号
dump_group_index = self.group.dump_uuid_index_dict[dump_id]
transport_value = self.group.to_excavator_congestion[dump_group_index, :]
except Exception as es:
self.logger.error("矿卡重载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_excavator_num)
return transport_value
class ExpectedTime(AlgorithmBase):
"""
class for expected traveling time alg.
"""
def __init__(self, group):
super().__init__()
self.group = group
self.logger = get_logger("zxt.algorithm.expected")
def solve(self, truck_id):
"""
Receive a truck_id and calculate the associated route travelling time.
:param truck_id: (uuid)
:return: travel_time_value
"""
try:
truck_index = truck.truck_uuid_to_index_dict[truck_id]
trip = truck.get_truck_current_trip()[truck_index]
task = truck.get_truck_current_task()[truck_id]
truck_avl_time = pre_sch.get_truck_avl_time(truck_id=truck_id)
group_dynamic_excavator_num = len(self.group.dump_dict)
group_dynamic_dump_num = len(self.group.excavator_dict)
except Exception as es:
self.logger.error("车辆调度信息读取异常")
self.logger.error(es)
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 挖机可用时间
excavator_val_time_global = pre_sch.get_excavator_avl_time()
excavator_val_time = np.full(len(self.group.excavator_dict), 0)
for excavator_id, excavator_index in self.group.excavator_uuid_index_dict.items():
excavator_val_time[excavator_index] = excavator_val_time_global[excavator_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.park_to_excavator_distance[0, :] / 1000 / \
truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-excavator_val_time")
self.logger.info(excavator_val_time)
except Exception as es:
self.logger.error("矿卡启动调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_excavator_num)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DeviceMap.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 全局卸点可用时间 dict
dump_val_time_global = pre_sch.get_dump_avl_time()
# 局部卸点可用时间 list
dump_val_time = np.full(len(self.group.dump_dict), 0)
for dump_id, dump_index in self.group.dump_uuid_index_dict.items():
dump_val_time[dump_index] = dump_val_time_global[dump_id]
# 车辆所在挖机 uuid
excavator_id = DeviceMap.excavator_index_to_uuid_dict[int(trip[1])]
# 挖机所在分组序号 index
excavator_group_index = self.group.excavator_uuid_index_dict[excavator_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.to_dump_distance[excavator_group_index, :] \
/ 1000 / truck.heavy_speed[truck_id] + truck_avl_time
# 车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, dump_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-dump_val_time")
self.logger.info(dump_val_time)
except Exception as es:
self.logger.error("矿卡空载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_dump_num)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 挖机可用时间
excavator_val_time_global = pre_sch.get_excavator_avl_time()
excavator_val_time = np.full(len(self.group.excavator_dict), 0)
for excavator_id, excavator_index in self.group.excavator_uuid_index_dict.items():
excavator_val_time[excavator_index] = excavator_val_time_global[excavator_id]
# 车辆所在卸点
dump_id = DeviceMap.dump_index_to_uuid_dict[int(trip[1])]
# 卸点对应分组编号
dump_group_index = self.group.dump_uuid_index_dict[dump_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.to_excavator_distance[dump_group_index, :] \
/ 1000 / truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
except Exception as es:
self.logger.error("矿卡重载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_dump_num)
return transport_value
......@@ -3,7 +3,7 @@
# @Time : 2022/1/5 14:14
# @Author : Opfer
# @Site :
# @File : algorithm.py
# @File : alg.py
# @Software: PyCharm
......@@ -13,7 +13,7 @@ from equipment.dump import DumpInfo
from equipment.excavator import ExcavatorInfo
class ScheduleAlg(WalkManage):
""" class for the schedule algorithm.
""" class for the schedule alg.
Description:
根据设备状态计算调度价值
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/6/1 16:35
# @Author : Opfer
# @Site :
# @File : dispatcher.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
from core.schedule import PreSchedule
import json
import numpy as np
from datetime import datetime, timedelta
class Dispatcher:
"""
class for group dispatch program.
"""
def __init__(self, truck: TruckInfo, dump: DumpInfo, excavator: ExcavatorInfo, pre_sch: PreSchedule, request_mode=False):
self.group_list = []
self.truck = truck
self.dump = dump
self.excavator = excavator
self.submission = DispatchSubmission(dump, excavator, truck)
def period_update(self):
"""
Update global parameter and equipment information.
:return: None
"""
# global_period_para_update()
self.dump.dump_para_period_update()
self.excavator.excavator_para_period_update()
self.truck.truck_para_period_update(self.dump, self.excavator)
self.truck.state_period_update()
def group_generate(self):
"""
Generate and initialize dispatch groups.
:return: None
"""
for group_id in DispatchInfo.group_dump_dict.keys():
group = Group(group_id, self.truck)
self.group_list.append(group)
def group_dispatch(self):
"""
Group dispatching logic.
:return:
"""
for group in self.group_list:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
self.submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
class DispatchSubmission:
""" class for the submission calculated dispatch.
Description:
将调度结果按照指定格式传递到云端机群
Attribute:
"""
def __init__(self, dump, excavator, truck):
self.logger = self.logger = get_logger("zxt.submission")
self.dump = dump
self.excavator = excavator
self.truck = truck
def truck_dispatch_to_redis(self, truck_id, dispatch_seq):
"""
将truck_id对应矿卡派车计划写入redis
:param truck_id: (uuid) 矿卡uuid
:param dispatch_seq: (List[int]) 矿卡派车计划
:return: None
"""
try:
try:
group_id = self.group.dispatch_truck_group[truck_id]
record = {"truckId": truck_id}
task = self.truck.get_truck_current_task()[truck_id]
except Exception as es:
self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
self.logger.error(es)
if task in [0, 1, 2]: # 卡车空载或在装载区出场前, 可变更卸载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[1]],
exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡空载")
elif task in [3, 4, 5]: # 卡车重载或在卸载区出场前, 可变更装载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = self.excavator.excavator_index_to_uuid_dict[dispatch_seq[1]]
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡重载")
elif task == -2:
try:
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
self.logger.info(dispatch_seq)
self.logger.info(dispatch_seq[1])
self.logger.info(DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]])
self.logger.info("item")
print(item.id, item.truck_id, item.exactor_id, item.dump_id)
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
self.logger.error(es)
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区")
self.logger.error(es)
else:
pass
except Exception as es:
self.logger.error("调度结果写入异常")
self.logger.error(f"调度结果:{dispatch_seq}")
self.logger.error(es)
def group_dispatch_to_redis(self, group: Group, dispatch_plan_dict):
"""
Update the dispatch plan in the group to redis
:param group: (Group)
:param dispatch_plan_dict: (Dict)
:return: None
"""
for truck_id, dispatch_plan in dispatch_plan_dict:
self.truck_dispatch_to_redis(truck_id, dispatch_plan)
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @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
class Group:
"""
class for group instance.
"""
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 -> 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_group_mode(self):
"""
update group mode.
:param group_mode:
:return:
"""
# DispatchInfo.update_group_mode()
self.group_mode = DispatchInfo.get_group_mode(self.group_id)
def update_group_device(self):
"""
update group devices.
:return:
"""
# 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_group_road_network(self):
"""
update group road network.
: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 update_group_device_map(self):
"""
update group device map.
:return:
"""
# update device map
excavator_index = 0
for i in self.excavator_dict.keys():
self.excavator_uuid_index_dict[i] = excavator_index + 1
dump_index = 0
for i in self.dump_dict.keys():
self.dump_uuid_index_dict[i] = dump_index + 1
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_excavator_dict = {group_1: {excavator_1: load_area_1}, group_2: {excavator_2: load_area_2}}
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
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 14:45
# @Author : Opfer
# @Site :
# @File : dispatchInfo.py
# @Software: PyCharm
import numpy as np
from settings import *
import pandas as pd
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_excavator_dict = {} # team_id -> dict {[excavator_id, excavator_id], ...}
load_exactor_dict = {} # 装载区id-->>电铲编号的映射
exactor_load_dict = {} # 电铲编号->>装载区id的映射
group_truck_dict = {} # team_id -> dict # {group_id:[truck_id,truck_id],...}
dump_group_dict = {} # unload_area_id -> team_id
excavator_group_dict = {} # excavator_id -> team_id 问题:多个key值对应一个value值
truck_group_dict = {} # truck_id -> team_id
# group feature
group_mode = {} # 数据格式: {team_id:mode_code}
# route_distance(路网距离)
load_distance = {} # 装载区-挖机(电铲)的距离 数据格式 -->>{team_id:np.array}
unload_distance = {} # 卸载区-挖机(电铲)的距离 数据格式 -->>{team_id:np.array}
@classmethod
def renew_set(cls):
"""
@date:2022/6/2 19:50
@author:maqc
@desc:实例化对象,可直接访问
"""
cls.group_dump_dict = {} # cls.group_dump_dict.keys() 相当于所有的team_id
cls.dump_group_dict = {} # cls.dump_group_dict.keys() 相当于所有的卸载区 unload_area_id
cls.group_excavator_dict = {}
cls.excavator_group_dict = {}
cls.load_exactor_dict = {} # cls.load_exactor_dict.keys() 相当于所有的装载区 load_area_id
cls.exactor_load_dict = {}
cls.group_truck_dict = {}
cls.truck_group_dict = {}
cls.group_mode = {}
cls.load_distance = {} # to_load_diatance-->>空车模式
cls.unload_distance = {} # to_unload_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 = {} -->> {team_id:[unload_area_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 = {} -->> {team_id: [excavator_id, excavator_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():
if item.team_id in cls.group_excavator_dict:
cls.group_excavator_dict[item.team_id].append(item.exactor_id)
else:
cls.group_excavator_dict[item.team_id] = [item.exactor_id]
cls.excavator_group_dict[item.exactor_id] = item.team_id
# group_truck_dict = {} -->> {team_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:处理其它类型的数据
"""
# 新增:team_id-->>group_code;group_code-->>mode_code.结果:team_id-->>mode_code
logger = get_logger("mqc.update_group_mode")
team_group_dict = {} # team_id-->>group_code的一个映射,格式:{team_id:group_code}
group_mode_dict = {} # group-->>mode_code的一个映射,格式:{group_code:mode_code}
try:
for pos in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
team_group_dict[pos.team_id] = pos.group_code
for item in session_mysql.query(DispatchGroup).filter_by(group_type=1).all():
group_mode_dict[item.group_code] = item.mode_code
for key, value in team_group_dict.items():
if value in group_mode_dict:
cls.group_mode[key] = group_mode_dict[value]
except Exception as es:
logger.error("派车模式数据更新异常")
logger.error(es)
@classmethod
def dispatch_group_init(cls):
"""
update basic paras (group_set, dict, num ...)
:return:
"""
try:
for value in session_postgre.query(DiggingWorkArea).all():
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)
@classmethod
# 距离-->>数据格式:矩阵-->>to_load_distance
def update_route_distance(cls):
"""
@date:2022/6/2 19:50
@author:maqc
@desc:更新路网距离,返回矩阵格式数据
"""
logger = get_logger("mqc.update_route_distance")
try:
df = pd.DataFrame() # 记录装载区与卸载区之间的距离
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(
unload_exactor_matrix).T # 初始化距离矩阵,记录从装载区-->>电铲的距离,即to_unload_distance,重车模式
for i in range(len(unload_nums)):
for j in range(len(exactor_nums)):
id = set(df.loc[df[1] == str(unload_nums[i])].index.to_list()) & set(
df.loc[df[0] == str(cls.exactor_load_dict[j])].index.to_list()) # 集合属性
unload_exactor_matrix[i][j] = df.iloc[list(id)[0]][2]
for m in range(len(exactor_nums)):
for n in range(len(unload_nums)):
id = set(df.loc[df[0] == str(cls.exactor_load_dict[m])].index.to_list()) & set(
df.loc[df[1] == str(unload_nums[n])].index.to_list())
load_exactor_matrix[m][n] = df.iloc[list(id)[0]][3]
cls.load_distance[team_id] = unload_exactor_matrix
cls.unload_distance[team_id] = load_exactor_matrix
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)
#
#
......@@ -855,9 +855,12 @@ class PreSchedule:
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):
......@@ -925,6 +928,10 @@ class PreSchedule:
/ 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()
......@@ -943,14 +950,19 @@ class PreSchedule:
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.truck_avl_time[
int(tmp[i][1])
] = self.excavator_avl_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:
......@@ -961,7 +973,7 @@ class PreSchedule:
self.logger.error("挖机可用时间计算异常")
self.logger.error(es)
return self.excavator_avl_time
return self.excavator_avl_time_dict
def update_dump_avl_time(self, dump_avl_ls):
"""
......@@ -981,6 +993,10 @@ class PreSchedule:
/ 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()
......@@ -997,14 +1013,19 @@ class PreSchedule:
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.truck_avl_time[
int(tmp[i][1])
] = self.dump_avl_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:
......@@ -1015,7 +1036,7 @@ class PreSchedule:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
return self.dump_avl_time
return self.dump_avl_time_dict
def _reset(self):
"""
......@@ -1027,9 +1048,12 @@ class PreSchedule:
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):
"""
获取卸载点最早可用时间
......
......@@ -4,4 +4,8 @@
# @Author : Opfer
# @Site :
# @File : __init__.py
# @Software: PyCharm
\ No newline at end of file
# @Software: PyCharm
from .excavator import ExcavatorInfo
from .dump import DumpInfo
from .truck import TruckInfo
......@@ -421,7 +421,6 @@ def get_global_para_from_cache(cache):
global_dict = cache.get("global_dict")
if global_dict is None:
print("here2")
global_period_para_update()
cache.set("global_dict", global_dict, timeout=5 * 60)
......
......@@ -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"
......
......@@ -15,9 +15,11 @@ from sqlalchemy import VARCHAR, DateTime, Float, Integer, BOOLEAN
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from urllib.parse import quote
import json
import json, os
json_file = "config.json"
relative_path = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件夹的绝对路径
json_file = os.path.join(relative_path, "config.json")
# json_file = "config.json"
with open(json_file) as f:
mysql_config = json.load(f)["mysql"]
......@@ -207,6 +209,7 @@ class WalkTime(Base):
# self.walktime_load = walktime_load
# self.walktime_unload = walktime_unload
# class Truck(Base):
# __tablename__ = 'truck_status'
#
......@@ -262,7 +265,8 @@ class EquipmentPair(Base):
isdeleted = Column(BOOLEAN)
createtime = Column(DateTime)
def __init__(self, id, truck_id, exactor_id, dump_id, load_area_id, unload_area_id, dispatch_id, isdeleted, createtime):
def __init__(self, id, truck_id, exactor_id, dump_id, load_area_id, unload_area_id, dispatch_id, isdeleted,
createtime):
self.id = id
self.truck_id = truck_id
self.exactor_id = exactor_id
......@@ -273,6 +277,7 @@ class EquipmentPair(Base):
self.isdeleted = isdeleted
self.createtime = createtime
# class Lane(Base):
# # 表的名字
# __tablename__ = 'Geo_Node'
......@@ -295,6 +300,7 @@ class Lane(Base):
self.Length = Length
self.MaxSpeed = MaxSpeed
class Dispatch(Base):
# 表的名字:
__tablename__ = 'sys_dispatch_setting'
......@@ -317,7 +323,8 @@ class Dispatch(Base):
deletor = Column(VARCHAR(36))
deletetime = Column(DateTime)
def __init__(self, id, load_area_id, exactor_id, unload_area_id, dump_id, isauto, truck_id, group_id, remark, proportion_id,
def __init__(self, id, load_area_id, exactor_id, unload_area_id, dump_id, isauto, truck_id, group_id, remark,
proportion_id,
isdeleted, creator, createtime, updator, updatetime, deletor, deletetime):
self.id = id
self.load_area_id = load_area_id
......@@ -337,6 +344,7 @@ class Dispatch(Base):
self.deletor = deletor
self.deletetime = deletetime
class WalkTimePark(Base):
__tablename__ = 'park_load_distance'
......@@ -355,6 +363,7 @@ class WalkTimePark(Base):
self.park_load_distance = park_load_distance
self.park_load_lanes = park_load_lanes
class Equipment(Base):
__tablename__ = 'sys_equipment'
......@@ -384,6 +393,7 @@ class Equipment(Base):
self.only_allowed = only_allowed
self.priority = priority
class EquipmentSpec(Base):
__tablename__ = 'sys_equipment_spec'
......@@ -402,6 +412,7 @@ class EquipmentSpec(Base):
self.width = width
self.max_speed = max_speed
class LoadInfo(Base):
__tablename__ = 'sys_loadinfo'
......@@ -414,6 +425,7 @@ class LoadInfo(Base):
self.dump_id = dump_id
self.load_weght = load_weight
class JobRecord(Base):
__tablename__ = 'statistic_job_record'
......@@ -430,6 +442,7 @@ class JobRecord(Base):
self.end_time = end_time
self.work_type = work_type
class WorkRecord(Base):
__tablename__ = 'statistic_work_record'
......@@ -440,7 +453,8 @@ class WorkRecord(Base):
load_exit_time = Column(DateTime)
load_exit_count = Column(Integer)
def __init__(self, equipment_id, work_day, load_entrance_time, load_entrance_count, load_exit_time, load_exit_count):
def __init__(self, equipment_id, work_day, load_entrance_time, load_entrance_count, load_exit_time,
load_exit_count):
self.equipment_id = equipment_id
self.work_day = work_day
self.load_entrance_time = load_entrance_time
......@@ -456,16 +470,18 @@ class DumpArea(Base):
BindList = Column(VARCHAR(1000))
UnloadAbililty = Column(Float)
Disabled = Column(Integer)
Material = Column(VARCHAR(36))
Materials = Column(VARCHAR(36))
Priority = Column(Integer)
DumpEquipmentId = Column(VARCHAR(36))
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Material, Priority):
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentId):
self.Id = Id
self.BindList = BindList
self.UnloadAbililty = UnloadAbililty
self.Disabled = Disabled
self.Material = Material
self.Materials = Materials
self.Priority = Priority
self.DumpEquipmentId = DumpEquipmentId
class DiggingWorkArea(Base):
......@@ -473,10 +489,12 @@ class DiggingWorkArea(Base):
Id = Column(VARCHAR(50), primary_key=True)
Material = Column(VARCHAR(36))
ExactorId = Column(VARCHAR(36))
def __init__(self, Id, Material):
def __init__(self, Id, Material, ExactorId):
self.Id = Id
self.Material = Material
self.ExactorId = ExactorId
class DispatchRule(Base):
......@@ -501,3 +519,71 @@ class Material(Base):
self.id = id
self.name = name
class DispatchMode(Base):
__tablename__ = 'sys_dispatch_mode'
id = Column(VARCHAR(36), primary_key=True)
mode_name = Column(VARCHAR(30))
mode_desc = Column(VARCHAR(50))
mode_code = Column(Integer)
def __init__(self, id, mode_name, mode_desc, mode_code):
self.id = id
self.mode_name = mode_name
self.mode_desc = mode_desc
self.mode_code = mode_code
class DispatchGroup(Base):
__tablename__ = 'sys_dispatch_group'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
mode_id = Column(VARCHAR(36))
mode_code = Column(Integer)
def __init__(self, id, group_type, group_code, mode_id, mode_code):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.mode_id = mode_id
self.mode_code = mode_code
class DispatchMatch(Base):
__tablename__ = 'sys_dispatch_match'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
match_code = Column(VARCHAR(36))
team_id = Column(VARCHAR(36))
unload_area_id = Column(VARCHAR(36))
exactor_id = Column(VARCHAR(36))
def __init__(self, id, group_type, group_code, match_code, team_id, unload_area_id, exactor_id):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.match_code = match_code
self.team_id = team_id
self.unload_area_id = unload_area_id
self.exactor_id = exactor_id
class DispatchEquipment(Base):
__tablename__ = 'sys_dispatch_equipment'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
match_code = Column(VARCHAR(36))
isdeleted = Column(Integer)
equipment_id = Column(VARCHAR(36))
def __init__(self, id, group_type, group_code, match_code, isdeleted, equipment_id):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.match_code = match_code
self.isdeleted = isdeleted
self.equipment_id = equipment_id
File added
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 16:32
# @Author : Opfer
# @Site :
# @File : alg.py
# @Software: PyCharm
class AlgorithmBase:
"""
Base class for dispatch alg.
"""
def __init__(self):
pass
class Congestion(AlgorithmBase):
"""
class for congestion alg.
"""
def __init__(self, group):
super().__init__()
self.group = group
def solve(self):
pass
class ExpectedTime(AlgorithmBase):
"""
class for expected traveling time alg.
"""
def __init__(self, group):
super().__init__()
self.group = group
def solve(self):
pass
#!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
class Group:
"""
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/5/30 14:45
# @Author : Opfer
# @Site :
# @File : dispatchInfo.py
# @Software: PyCharm
class DispatchInfo:
"""
class for dispatch group info.
"""
# dispatch groups
group_num = 1
group_set = set()
# device group structure
group_dump_dict = {} # team_id -> dict {[dump_id, unload_area_id], [dump_id, unload_area_id], ...}
group_excavator_dict = {} # team_id -> dict {[excavator_id, load_area_id], ...}
group_truck_dict = {} # team_id -> dict {truck_id, ...}
dump_group_dict = {} # dump_id -> team_id
excavator_group_dict = {} # excavator_id -> team_id
truck_group_dict = {} # truck_id -> team_id
# group feature
group_mode = {}
@classmethod
def update_device_group_structure(cls):
pass
@classmethod
def update_group_mode(cls):
pass
@classmethod
def dispatch_group_init(cls):
"""
update basic paras (group_set, dict, num ...)
:return:
"""
pass
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