Commit 3e2448fe authored by 张晓彤's avatar 张晓彤

Initial commit

parents
^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package Dispatch
^^^^^^^^^^^^^^^^^^^^^^^^^^
--------------------
[version]: 1.0.1
[message]: add
[feather]:
[fix ]:
[TODO ]:
[info ]: author: zxt ; time: 2021-07-07 15:46:00 ; email: ; tel: ;
--------------------
--------------------
[version]: 1.1.1
[message]: refactor real-time dispatch function
[feather]:
[fix ]:
[TODO ]:
[info ]: author: zxt ; time: 2021-07-23 16:59:00 ; email: ; tel: ;
--------------------
--------------------
[version]: 1.2.1
[message]: add traffic flow planning
[feather]:
[fix ]:
[TODO ]:
[info ]: author: zxt ; time: 2021-07-23 16:59:00 ; email: ; tel: ;
--------------------
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 11:31
# @Author : Opfer
# @Site :
# @File : __init__.py
# @Software: PyCharm
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 11:28
# @Author : Opfer
# @Site :
# @File : dump.py
# @Software: PyCharm
from para_config import *
from settings import *
# 卸载设备类
class DumpInfo(WalkManage):
def __init__(self):
# 卸载设备数量
self.dynamic_dump_num = get_value("dynamic_dump_num")
# 用于动态调度的卸载设备集合
self.dynamic_dump_set = get_value("dynamic_dump_set")
# 开始时间
self.start_time = datetime.now()
# 卸载时间
self.unloading_time = np.zeros(self.dynamic_dump_num)
# 入场时间
self.entrance_time = np.zeros(self.dynamic_dump_num)
# 出场时间
self.exit_time = np.zeros(self.dynamic_dump_num)
# 卸载点物料类型
self.dump_material = {}
# 卸点优先级
self.dump_priority_coefficient = np.ones(self.dynamic_dump_num)
# 初始化读取映射及路网
self.period_map_para_load()
self.period_walk_para_load()
# 参数初始化
self.para_period_update()
def get_unloading_time(self):
return self.unloading_time
def get_dump_num(self):
return self.dynamic_dump_num
def get_dynamic_dump_set(self):
return self.dynamic_dump_set
def get_unloading_task_time(self):
unloading_time = self.unloading_time
dump_entrance_time = self.entrance_time
dump_exit_time = self.exit_time
unloading_task_time = unloading_time + dump_entrance_time + dump_exit_time
return unloading_task_time
# 更新卸载设备卸载时间
def update_dump_unloadtime(self):
self.unloading_time = np.zeros(self.dynamic_dump_num)
for dump_id in self.dump_uuid_to_index_dict.keys():
ave_unload_time = 0
unload_count = 0
# try:
# for query in (
# session_mysql.query(JobRecord.start_time, JobRecord.end_time)
# .join(Equipment, JobRecord.equipment_id == Equipment.equipment_id)
# .filter(Equipment.id == dump_id, JobRecord.end_time != None)
# .order_by(JobRecord.start_time.desc())
# .limit(10)
# ):
# ave_unload_time = ave_unload_time + float(
# (query.end_time - query.start_time)
# / timedelta(hours=0, minutes=1, seconds=0)
# )
# unload_count = unload_count + 1
# self.unloading_time[self.dump_uuid_to_index_dict[dump_id]] = (
# ave_unload_time / unload_count
# )
# except Exception as es:
# logger.error(f"卸载设备 {dump_id} 卸载时间信息缺失, 已设为默认值(1min)")
# logger.error(es)
self.unloading_time[self.dump_uuid_to_index_dict[dump_id]] = 5.00
# print("average_unload_time: ", self.unloading_time[self.dump_uuid_to_index_dict[dump_id]])
# 更新卸载设备出入时间
def update_dump_entrance_exit_time(self):
self.entrance_time = np.zeros(self.dynamic_dump_num)
self.exit_time = np.zeros(self.dynamic_dump_num)
now = datetime.now().strftime("%Y-%m-%d")
for dump_id in self.dump_uuid_to_index_dict.keys():
# try:
# for query in (
# session_mysql.query(WorkRecord)
# .filter(
# WorkRecord.equipment_id == dump_id, WorkRecord.work_day >= now
# )
# .first()
# ):
# self.entrance_time[self.dump_uuid_to_index_dict[dump_id]] = float(
# query.load_entrance_time / query.load_entrance_count
# )
# self.exit_time[self.dump_uuid_to_index_dict[dump_id]] = float(
# query.exit_entrance_time / query.exit_entrance_count
# )
# except Exception as es:
# logger.error(f"卸载设备 {dump_id} 出入场时间信息缺失, 已设为默认值(1min)")
# logger.error(es)
self.entrance_time[self.dump_uuid_to_index_dict[dump_id]] = 0.50
self.exit_time[self.dump_uuid_to_index_dict[dump_id]] = 0.50
def update_dump_material(self):
self.dump_material = {}
for dump_id in get_value("dynamic_dump_set"):
try:
unload_area_id = session_mysql.query(Dispatch).filter_by(dump_id=dump_id, isauto=1, isdeleted=0).first().unload_area_id
dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Material
self.dump_material[dump_id] = dump_material_id
except Exception as es:
logger.error("无动态派车计划可用")
logger.error(es)
def update_dump_priority(self):
self.dump_priority_coefficient = np.ones(self.dynamic_dump_num)
for dump_id in self.dynamic_dump_set:
try:
unload_area_index = self.dump_index_to_unload_area_index_dict[self.dump_uuid_to_index_dict[dump_id]]
unload_area_id = unload_area_index_to_uuid_dict[unload_area_index]
item = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first()
self.dump_priority_coefficient[self.dump_uuid_to_index_dict[dump_id]] += item.Priority
except Exception as es:
logger.error("无动态派车计划可用")
logger.error(es)
def reset(self):
# 卸载设备数量
self.dynamic_dump_num = get_value("dynamic_dump_num")
# 用于动态调度的卸载设备集合
self.dynamic_dump_set = get_value("dynamic_dump_set")
# 卸载时间
self.unloading_time = np.zeros(self.dynamic_dump_num)
# 入场时间
self.entrance_time = np.zeros(self.dynamic_dump_num)
# 出场时间
self.exit_time = np.zeros(self.dynamic_dump_num)
# 卸载点物料类型
self.dump_material = {}
# 卸点优先级
self.dump_priority_coefficient = np.ones(self.dynamic_dump_num)
def para_period_update(self):
self.reset()
# print("Dump update!")
logger.info("Dump update!")
# 装载周期参数
self.period_map_para_load()
self.period_walk_para_load()
# 计算平均卸载时间
self.update_dump_unloadtime()
# 计算平均进出场时间
self.update_dump_entrance_exit_time()
# 更新卸点物料
self.update_dump_material()
# 更新设备优先级
self.update_dump_priority()
# 卸载目标产量
self.dump_target_mass = np.full(self.dynamic_dump_num, dump_target_mass)
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 11:28
# @Author : Opfer
# @Site :
# @File : excavator.py
# @Software: PyCharm
from para_config import *
from settings import *
# 挖机设备类
class ExcavatorInfo(WalkManage):
def __init__(self):
# # 挖机集合
# self.dynamic_excavator_set = set(update_autodisp_excavator())
# 装载设备数量
self.dynamic_excavator_num = len(dynamic_excavator_set)
# 用于动态调度的卸载设备集合
self.dynamic_excavator_set = []
# 开始时间
self.start_time = datetime.now()
# 装载时间
self.loading_time = np.zeros(self.dynamic_excavator_num)
# 入场时间
self.entrance_time = np.zeros(self.dynamic_excavator_num)
# 出场时间
self.exit_time = np.zeros(self.dynamic_excavator_num)
# 挖机对应物料类型
self.excavator_material = {}
# 挖机设备优先级
self.excavator_priority_coefficient = np.ones(self.dynamic_excavator_num)
# 挖机物料优先级
self.excavator_material_priority = np.ones(self.dynamic_excavator_num)
# 初始化读取映射及路网
self.period_map_para_load()
self.period_walk_para_load()
# 参数初始化
self.para_period_update()
def get_loading_time(self):
return self.loading_time
def get_excavator_num(self):
return self.dynamic_excavator_num
def get_dynamic_excavator_set(self):
return self.dynamic_excavator_set
# 更新挖机装载时间
def update_excavator_loadtime(self):
self.loading_time = np.zeros(self.dynamic_excavator_num)
for excavator_id in self.excavator_uuid_to_index_dict.keys():
ave_load_time = 0
load_count = 0
# try:
# for query in (
# session_mysql.query(JobRecord.start_time, JobRecord.end_time)
# .join(Equipment, JobRecord.equipment_id == Equipment.equipment_id)
# .filter(Equipment.id == excavator_id, JobRecord.end_time != None)
# .order_by(JobRecord.start_time.desc())
# .limit(10)
# ):
# ave_load_time = ave_load_time + float(
# (query.end_time - query.start_time)
# / timedelta(hours=0, minutes=1, seconds=0)
# )
# load_count = load_count + 1
# self.loading_time[self.excavator_uuid_to_index_dict[excavator_id]] = (
# ave_load_time / load_count
# )
# except Exception as es:
# logger.error(f"挖机 {excavator_id} 装载时间信息缺失, 已设为默认值(1min)")
# logger.error(es)
logger.info("loading_time")
logger.info(self.loading_time)
logger.info("excavator_uuid_to_index_dict")
logger.info(self.excavator_uuid_to_index_dict)
self.loading_time[self.excavator_uuid_to_index_dict[excavator_id]] = 5.00
# 更新挖机设备出入时间
def update_excavator_entrance_exit_time(self):
self.entrance_time = np.zeros(self.dynamic_excavator_num)
self.exit_time = np.zeros(self.dynamic_excavator_num)
now = datetime.now().strftime("%Y-%m-%d")
for excavator_id in self.excavator_uuid_to_index_dict.keys():
# try:
# for query in (
# session_mysql.query(WorkRecord)
# .filter(
# WorkRecord.equipment_id == excavator_id,
# WorkRecord.work_day >= now,
# )
# .first()
# ):
# self.entrance_time[
# self.excavator_uuid_to_index_dict[excavator_id]
# ] = float(query.load_entrance_time / query.load_entrance_count)
# self.exit_time[
# self.excavator_uuid_to_index_dict[excavator_id]
# ] = float(query.exit_entrance_time / query.exit_entrance_count)
# except Exception as es:
# logger.error(f"挖机设备 {excavator_id} 出入场时间信息缺失, 已设为默认值(1min)")
# logger.error(es)
self.entrance_time[
self.excavator_uuid_to_index_dict[excavator_id]
] = 0.50
self.exit_time[self.excavator_uuid_to_index_dict[excavator_id]] = 0.50
# 读取出入场时间
def get_loading_task_time(self):
loading_time = self.loading_time
excavator_entrance_time = self.entrance_time
excavator_exit_time = self.exit_time
loading_task_time = loading_time + excavator_entrance_time + excavator_exit_time
return loading_task_time
def update_excavator_material(self):
logger.info("self.dynamic_excavator_set")
logger.info(self.dynamic_excavator_set)
for excavator_id in self.dynamic_excavator_set:
try:
load_area_id = session_mysql.query(Dispatch).filter_by(exactor_id=excavator_id, isdeleted=0, isauto=1).first().load_area_id
excavator_material_id = session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().Material
self.excavator_material[excavator_id] = excavator_material_id
except Exception as es:
logger.warning(es)
def update_excavator_priority(self):
logger.info("dynamic_excavator_set")
logger.info(self.dynamic_excavator_set)
for excavator_id in self.dynamic_excavator_set:
item = session_mysql.query(Equipment).filter_by(id=excavator_id).first()
logger.info("excavator_priority_coefficient")
logger.info(self.excavator_priority_coefficient)
self.excavator_priority_coefficient[self.excavator_uuid_to_index_dict[excavator_id]] = item.priority + 1
# 物料优先级控制
rule = 2
rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first()
material_priority_use = rule7.disabled
if material_priority_use == 0:
rule = rule7.rule_weight
if rule == 3:
if self.excavator_material[excavator_id] == 'e56eb559-a746-4cc4-8ada-ebf9819fbe27':
self.excavator_material_priority[self.excavator_uuid_to_index_dict[excavator_id]] = 5
elif rule == 1:
if self.excavator_material[excavator_id] == '81bb175d-50fe-4be3-937e-6791ac4d6fec':
self.excavator_material_priority[self.excavator_uuid_to_index_dict[excavator_id]] = 5
def reset(self):
# 装载设备数量
self.dynamic_excavator_num = get_value("dynamic_excavator_num")
# 用于动态调度的卸载设备集合
self.dynamic_excavator_set = get_value("dynamic_excavator_set")
# 装载时间
self.loading_time = np.zeros(self.dynamic_excavator_num)
# 入场时间
self.entrance_time = np.zeros(self.dynamic_excavator_num)
# 出场时间
self.exit_time = np.zeros(self.dynamic_excavator_num)
# 挖机对应物料类型
self.excavator_material = {}
# 挖机设备优先级
self.excavator_priority_coefficient = np.ones(self.dynamic_excavator_num)
# 挖机物料优先级
self.excavator_material_priority = np.ones(self.dynamic_excavator_num)
def para_period_update(self):
self.reset()
logger.info("Excavator update!")
rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first().disabled
logger.info("物料优先级规则")
logger.info(rule7)
# 装载周期参数
self.period_map_para_update()
self.period_walk_para_update()
# 用于动态调度的挖机设备
self.dynamic_excavator_set = set(update_autodisp_excavator())
self.dynamic_excavator_num = len(self.dynamic_excavator_set)
# 计算平均装载时间
self.update_excavator_loadtime()
# 更新挖机物料
self.update_excavator_material()
# 更新挖机优先级
self.update_excavator_priority()
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 11:28
# @Author : Opfer
# @Site :
# @File : truck.py
# @Software: PyCharm
from para_config import *
from equipment.dump import DumpInfo
from equipment.excavator import ExcavatorInfo
from typing import List
# 引入对象
dump = DumpInfo()
excavator = ExcavatorInfo()
# 矿卡设备类
class TruckInfo(WalkManage):
def __init__(self):
# object fileds
# self.walker = WalkManage()
# 矿卡数量
self.dynamic_truck_num = get_value("dynamic_truck_num")
# 用于动态派车的矿卡集合
self.dynamic_truck_set = get_value("dynamic_truck_set")
# 矿卡抵达卸载设备时间
self.cur_truck_reach_dump = np.zeros(self.dynamic_truck_num)
# 矿卡抵达挖机时间
self.cur_truck_reach_excavator = np.zeros(self.dynamic_truck_num)
# 矿卡最后装载/卸载时间
self.last_load_time = {}
self.last_unload_time = {}
# 相对矿卡最后装载/卸载时间
self.relative_last_load_time = {}
self.relative_last_unload_time = {}
# 矿卡当前任务
self.truck_current_task = {}
# 调度开始时间
self.start_time = datetime.now()
# 矿卡有效载重
self.payload = np.zeros(self.dynamic_truck_num)
# 矿卡时速
self.empty_speed = {}
self.heavy_speed = {}
# 矿卡长宽
self.geo_length = {}
self.geo_width = {}
# 矿卡型号
self.size = {}
# 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号)
self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
# 矿卡挖机绑定关系
self.truck_excavator_bind = {}
# 矿卡卸点绑定关系
self.truck_dump_bind = {}
# 矿卡挖机排斥关系
self.truck_excavator_exclude = {}
# 矿卡卸点排斥关系
self.truck_dump_exclude = {}
# 排斥关系modify
self.excavator_exclude_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
# 矿卡优先级
self.truck_priority = np.ones(self.dynamic_truck_num)
# 矿卡绑定物料
self.truck_material_bind = {}
# 矿卡绑定物料modify
self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)
# self.excavator_material_bind_modify =np.zeros(self.dynamic_truck_num)
self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
# 各卸载区矿卡数量
self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
# 各装载区矿卡数量
self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
# 初始化读取映射及路网
self.period_map_para_load()
self.period_walk_para_load()
# 初始化读取参数
self.para_period_update()
# # 矿卡所属group
# self.truck_group = {}
# 矿卡禁用列表
self.truck_disable_list = []
def get_truck_current_trip(self):
return self.truck_current_trip
def get_truck_current_task(self):
return self.truck_current_task
def get_truck_num(self):
return self.dynamic_truck_num
def get_truck_reach_dump(self):
return self.cur_truck_reach_dump
def get_truck_reach_excavator(self):
return self.cur_truck_reach_excavator
def get_dynamic_truck_set(self):
return self.dynamic_truck_set
def get_realative_last_load_time(self):
return self.relative_last_load_time
def get_realative_last_unload_time(self):
return self.relative_last_unload_time
def get_payload(self):
return self.payload
def get_width(self):
return self.geo_width
def get_length(self):
return self.geo_length
def get_dump_hold_truck_num(self):
return self.dump_hold_truck_num
def get_excavator_hold_truck_num(self):
return self.excavator_hold_truck_num
################################################ short term update ################################################
# 更新矿卡当前任务
def update_truck_current_task(self):
self.truck_current_task = {}
device_name_set = redis2.keys()
for item in device_name_set:
try:
item = item.decode(encoding="utf-8")
key_value_dict = redis2.hgetall(item) # reids str可以自动转为bytes
device_type = int(key_value_dict[str_to_byte("type")])
if device_type == 1:
if truck_name_to_uuid_dict[item] in self.dynamic_truck_set:
currentTask = int(key_value_dict[str_to_byte("currentTask")])
self.truck_current_task[
truck_name_to_uuid_dict[item]
] = currentTask
except Exception as es:
logger.error("读取矿卡任务异常-reids读取异常")
logger.error(es)
logger.info("矿卡当前任务:")
logger.info(self.truck_current_task)
# 更新矿卡最后装载/卸载时间
def update_truck_last_leave_time(self):
self.last_load_time = {}
self.last_unload_time = {}
self.relative_last_load_time = {}
self.relative_last_unload_time = {}
try:
for item in self.dynamic_truck_set:
key_value_dict = redis2.hgetall(truck_uuid_to_name_dict[item])
device_type = int(key_value_dict[str_to_byte("type")])
# 判断是否为矿卡
if device_type == 1:
task = self.truck_current_task[item]
if task in heavy_task_set:
if str_to_byte("lastLoadTime") in key_value_dict.keys(): # 若最后装载时间存在
last_load_time_tmp = eval(byte_to_str(key_value_dict[str_to_byte("lastLoadTime")]))
tmp_time = datetime.strptime(last_load_time_tmp, "%Y-%m-%d %H:%M:%S")
if tmp_time > datetime.strptime("2000-01-01 01:01:01", "%Y-%m-%d %H:%M:%S"): # 若最后装载时间异常
self.last_load_time[item] = tmp_time
else:
self.last_load_time[item] = datetime.now()
redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastLoadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
logger.info("lastLoadTime is Error")
else:
self.last_load_time[item] = datetime.now()
redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastLoadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
logger.info("lastLoadTime is None")
self.relative_last_load_time[item] = float(
(self.last_load_time[item] - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
# print("相对last_load_time", self.relative_last_load_time[item])
logger.info("相对last_load_time")
logger.info(self.relative_last_load_time[item])
if task in empty_task_set:
if str_to_byte("lastUnloadTime") in key_value_dict.keys():
last_unload_time_tmp = eval(key_value_dict[str_to_byte("lastUnloadTime")])
tmp_time = datetime.strptime(last_unload_time_tmp, "%Y-%m-%d %H:%M:%S")
if tmp_time > datetime.strptime("2000-01-01 01:01:01", "%Y-%m-%d %H:%M:%S"):
self.last_unload_time[item] = tmp_time
else:
self.last_unload_time[item] = datetime.now()
redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
logger.info("lastUnloadTime is Error")
else:
self.last_unload_time[item] = datetime.now()
# key_value_dict[str_to_byte("lastUnloadTime")] = datetime.now().strftime(
# "%b %d, %Y %I:%M:%S %p"
# )
redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
logger.info("lastUnloadTime is None")
self.relative_last_unload_time[item] = float(
(self.last_unload_time[item] - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
# print("相对last_unload_time", self.relative_last_unload_time[item])
logger.info("相对last_unload_time")
logger.info(self.relative_last_unload_time[item])
elif task == -2:
# print(datetime.now())
self.last_unload_time[item] = datetime.now()
# key_value_dict["lastUnloadTime"] = datetime.now().strftime(
# "%b %d, %Y %I:%M:%S %p")
if str_to_byte("lastUnloadTime") in key_value_dict.keys():
# redis2.hset(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
# datetime.now().strftime("%b %d, %Y %I:%M:%S %p"))
redis2.hset(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
else:
redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
"\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
# redis2.hsetnx(truck_uuid_to_name_dict[item], str(json.dumps(key_value_dict)))
except Exception as es:
logger.error("读取矿卡可用时间异常-redis读取异常")
logger.error(es)
def update_truck_trip(self):
walk_time_to_load_area = walk_manage.get_walk_time_to_load_area()
walk_time_to_unload_area = walk_manage.get_walk_time_to_unload_area()
# 初始化矿卡行程, -1代表备停区
self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
for i in range(self.dynamic_truck_num):
try:
session_mysql.commit()
truck_id = self.truck_index_to_uuid_dict[i]
task = self.truck_current_task[self.truck_index_to_uuid_dict[i]]
# print("truck_task:", truck_id, task)
item = (
session_mysql.query(EquipmentPair)
.filter_by(truck_id=truck_id, isdeleted=0)
.first()
)
if task in empty_task_set + heavy_task_set and item is None:
raise Exception(f"矿卡 {truck_id} 配对关系异常")
except Exception as es:
logger.error("配对关系异常")
logger.error(es)
continue
# try:
# 若矿卡状态为空运
if task in empty_task_set:
last_unload_time = self.relative_last_unload_time[
self.truck_index_to_uuid_dict[i]
]
# 开始区域id
start_area_id = self.dump_uuid_to_unload_area_uuid_dict[
item.dump_id
]
# 开始区域序号
start_area_index = unload_area_uuid_to_index_dict[start_area_id]
end_area_id = self.excavator_uuid_to_load_area_uuid_dict[
item.exactor_id
]
# 结束设备index
end_eqp_index = excavator.excavator_uuid_to_index_dict[item.exactor_id]
end_area_index = load_area_uuid_to_index_dict[end_area_id]
self.truck_current_trip[i] = [
self.dump_uuid_to_index_dict[item.dump_id],
self.excavator_uuid_to_index_dict[item.exactor_id],
]
self.cur_truck_reach_excavator[i] = (
last_unload_time
+ walk_time_to_load_area[start_area_index][end_area_index]
)
# 目的地矿卡数加一
self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
# 若矿卡状态为重载
elif task in heavy_task_set:
# print("读取重载行程")
# print(item.exactor_id, item.dump_id)
last_load_time = self.relative_last_load_time[
self.truck_index_to_uuid_dict[i]
]
# 开始区域id
start_area_id = self.excavator_uuid_to_load_area_uuid_dict[
item.exactor_id
]
# 开始区域序号
start_area_index = load_area_uuid_to_index_dict[start_area_id]
# 结束区域id
end_area_id = self.dump_uuid_to_unload_area_uuid_dict[item.dump_id]
# 结束区域序号
end_area_index = unload_area_uuid_to_index_dict[end_area_id]
# 结束设备index
end_eqp_index = dump.dump_uuid_to_index_dict[item.dump_id]
self.truck_current_trip[i] = [
self.excavator_uuid_to_index_dict[item.exactor_id],
self.dump_uuid_to_index_dict[item.dump_id],
]
self.cur_truck_reach_dump[i] = (
last_load_time
+ walk_time_to_unload_area[end_area_index][start_area_index]
)
# 目的地矿卡数加一
self.dump_hold_truck_num[end_eqp_index] = self.dump_hold_truck_num[end_eqp_index] + 1
# 其他状态,矿卡状态为-2,equipment_pair表不存在该矿卡
else:
# end_eqp_index = excavator.excavator_uuid_to_index_dict[item.exactor_id]
# self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
pass
# except Exception as es:
# logger.error("矿卡行程读取异常")
# logger.error(es)
print("self.dump_hold_truck_num")
print(self.dump_hold_truck_num)
print("self.excavator_hold_truck_num")
print(self.excavator_hold_truck_num)
self.truck_current_trip.flatten()
# print("当前矿卡行程:")
# print(self.truck_current_trip)
################################################ long term update ################################################
# 更新矿卡实际容量
def update_truck_payload(self):
self.payload = np.full(self.dynamic_truck_num, 220);
# try:
# self.payload = np.zeros(self.dynamic_truck_num)
# for truck_id in self.dynamic_truck_set:
# trcuk_index = self.truck_uuid_to_index_dict[truck_id]
# truck_spec = (
# session_mysql.query(Equipment)
# .filter_by(id=truck_id)
# .first()
# .equipment_spec
# )
# # truck_spec = query.equipment_spec
# self.payload[trcuk_index] = (
# session_mysql.query(EquipmentSpec)
# .filter_by(id=truck_spec)
# .first()
# .capacity
# )
# except Exception as es:
# logger.error("读取矿卡有效载重异常-矿卡型号信息缺失")
# logger.error(es)
def update_truck_priority(self):
self.truck_priority = np.full(self.dynamic_truck_num, 0)
rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first()
if rule6.disabled == 0:
for truck_id in self.dynamic_truck_set:
item = session_mysql.query(Equipment).filter_by(id=truck_id).first()
truck_index = self.truck_uuid_to_index_dict[truck_id]
if item.priority == 0:
self.truck_priority[truck_index] = 0
elif item.priority == 1:
self.truck_priority[truck_index] = 2
elif item.priority == 2:
self.truck_priority[truck_index] = 5
elif item.priority == 3:
self.truck_priority[truck_index] = 10
def update_truck_dump_area_bind(self):
try:
rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
if rule5.disabled == 0:
self.truck_dump_bind = {}
for dump_area in session_postgre.query(DumpArea).all():
if dump_area.BindList is not None:
for truck_name in dump_area.BindList:
self.truck_dump_bind[truck_name_to_uuid_dict[truck_name]] = str(
dump_area.Id
)
except Exception as es:
logger.error("矿卡-卸载区域绑定关系读取异常")
logger.error(es)
def update_truck_excavator_bind(self):
try:
rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
if rule5.disabled == 0:
self.truck_excavator_bind = {}
for excavator_id in get_value("dynamic_excavator_set"):
item = session_mysql.query(Equipment).filter_by(id=excavator_id).first()
if item.bind_list is not None:
for truck_name in json.loads(item.bind_list):
self.truck_excavator_bind[
truck_name_to_uuid_dict[truck_name]
] = excavator_id
except Exception as es:
logger.error("矿卡-挖机绑定关系读取异常")
logger.error(es)
def update_truck_excavator_exclude(self):
self.truck_excavator_exclude = {}
self.excavator_exclude_modify = np.full(
(self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0
)
try:
rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
if rule5.disabled == 0:
for excavator_id in get_value("dynamic_excavator_set"):
item = (
session_mysql.query(Equipment)
.filter_by(id=excavator_id, only_allowed=1)
.first()
)
if item is not None:
for truck_id in self.dynamic_truck_set:
if truck_uuid_to_name_dict[truck_id] not in item.bind_list:
self.truck_excavator_exclude[truck_id] = excavator_id
self.excavator_exclude_modify[
self.truck_uuid_to_index_dict[truck_id]
][
self.excavator_uuid_to_index_dict[excavator_id]
] = 1000000
except Exception as es:
logger.error("矿卡-挖机禁止关系读取异常")
logger.error(es)
def update_truck_dump_exclude(self):
pass
def update_truck_material(self):
self.truck_material_bind = {}
self.update_truck_excavator_bind()
self.update_truck_dump_area_bind()
self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)
for truck_id in self.dynamic_truck_set:
if truck_id in self.truck_dump_bind:
unload_area_id = self.truck_dump_bind[truck_id]
dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Material
self.truck_material_bind[truck_id] = dump_material_id
if truck_id in self.truck_excavator_bind:
excavator_id = self.truck_excavator_bind[truck_id]
# print(self.excavator.excavator_material)
excavator_material_id = excavator.excavator_material[excavator_id]
self.truck_material_bind[truck_id] = excavator_material_id
for truck_id in self.dynamic_truck_set:
truck_index = self.truck_uuid_to_index_dict[truck_id]
if truck_id in self.truck_material_bind:
material = self.truck_material_bind[truck_id]
for excavator_id in get_value("dynamic_excavator_set"):
excavator_material_id = excavator.excavator_material[excavator_id]
excavator_index = excavator.excavator_uuid_to_index_dict[excavator_id]
print(truck_index, excavator_index)
if excavator_material_id != material:
self.excavator_material_bind_modify[truck_index][excavator_index] = 1000000
for dump_id in get_value("dynamic_dump_set"):
dump_material_id = dump.dump_material[dump_id]
dump_index = dump.dump_uuid_to_index_dict[dump_id]
if dump_material_id != material:
self.dump_material_bind_modify[truck_index][dump_index] = 1000000
def update_truck_spec(self):
for truck_id in self.dynamic_truck_set:
self.size[truck_id] = session_mysql.query(Equipment).filter_by(id=truck_id).first().equipment_spec
def update_truck_size(self):
self.update_truck_spec()
for truck_id in self.dynamic_truck_set:
truck_spec_id = self.size[truck_id]
self.geo_length[truck_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().length
self.geo_width[truck_spec_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().width
def update_truck_speed(self):
for truck_id in self.dynamic_truck_set:
self.empty_speed[truck_id] = session_mysql.query(EquipmentSpec). \
join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
filter(Equipment.id == truck_id).first().max_speed
self.heavy_speed[truck_id] = session_mysql.query(EquipmentSpec). \
join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
filter(Equipment.id == truck_id).first().max_speed
def update_truck_disable_list(self) -> List:
for item in session_mysql.query(Equipment).filter_by(device_type=1, disabled=1).all():
self.truck_disable_list.append(item.equipment_id)
return self.truck_disable_list
def reset(self):
# 更新矿卡数量
self.dynamic_truck_num = get_value("dynamic_truck_num")
# 更新矿卡集合
self.dynamic_truck_set = get_value("dynamic_truck_set")
# 矿卡挖机绑定关系
self.truck_excavator_bind = {}
# 矿卡卸点绑定关系
self.truck_dump_bind = {}
# 矿卡挖机排斥关系
self.truck_excavator_exclude = {}
# 矿卡卸点排斥关系
self.truck_dump_exclude = {}
# 排斥关系modify
self.excavator_exclude_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
# 矿卡优先级
self.truck_priority = np.ones(self.dynamic_truck_num)
# 矿卡绑定物料
self.truck_material_bind = {}
# 矿卡绑定物料modify
self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
# self.excavator_material_bind_modify =np.zeros(self.dynamic_truck_num)
self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
# # group_id
# self.truck_group = {}
# 各卸载区矿卡数量
self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
# 各装载区矿卡数量
self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
def para_period_update(self):
excavator.para_period_update()
dump.para_period_update()
# 初始化参数
self.reset()
# 距离成本启动
rule1 = session_mysql.query(DispatchRule).filter_by(id=1).first().disabled
# 拥堵成本启用
rule2 = session_mysql.query(DispatchRule).filter_by(id=2).first().disabled
# 车流规划启用
rule3 = session_mysql.query(DispatchRule).filter_by(id=3).first().disabled
rule4 = session_mysql.query(DispatchRule).filter_by(id=4).first().disabled
# 锁定禁止启用
rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first().disabled
# 设备优先级启用
rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first().disabled
logger.info("Para truck update!")
# 装载周期参数
self.period_map_para_update()
self.period_walk_para_update()
# # 更新全部矿卡设备集合
# truck_set = set(update_total_truck())
#
# # 更新固定派车矿卡集合
# fixed_truck_set = set(update_fixdisp_truck())
#
# # 更新动态派车矿卡集合
# self.dynamic_truck_set = truck_set.difference(fixed_truck_set)
# 更新有效载重
self.update_truck_payload()
logger.info("距离成本规则")
logger.info(rule1)
logger.info("拥堵成本规则")
logger.info(rule2)
logger.info("车流规划规则")
logger.info(rule3 or rule4)
logger.info("生产组织规则")
logger.info(rule5)
logger.info("设备优先级规则")
logger.info(rule6)
if not rule5:
# 更新绑定关系
self.update_truck_dump_area_bind()
self.update_truck_excavator_bind()
# 更新禁止关系
self.update_truck_excavator_exclude()
if not rule6:
# 更新矿卡调度优先级
self.update_truck_priority()
# # 更新矿卡group
# self.update_truck_group()
# 更新矿卡物料类型
self.update_truck_material()
def state_period_update(self):
# 更新卡车当前任务
self.update_truck_current_task()
# 更新卡车最后一次装载/卸载时间
self.update_truck_last_leave_time()
# 更新卡车当前行程
self.update_truck_trip()
# 矿卡速度更新
self.update_truck_speed()
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/4 15:50
# @Author : Opfer
# @Site :
# @File : para_config.py
# @Software: PyCharm
from static_data_process import *
from settings import *
import numpy as np
# 全局参数设定
# 空载任务集合
empty_task_set = [0, 1, 5]
# 重载任务集合
heavy_task_set = [2, 3, 4]
# 空载矿卡速度,单位(km/h)
global empty_speed
empty_speed = 25
# 重载矿卡速度,单位(km/h)
global heavy_speed
heavy_speed = 22
# 卸载设备目标卸载量
dump_target_mass = 5000
# 挖机目标装载量
excavator_target_mass = 5000
# 任务集合
task_set = [-2, 0, 1, 2, 3, 4, 5]
#
# truck = TruckInfo()
# excavator = ExcavatorInfo()
# dump = DumpInfo()
# Big integer
M = 100000000
# 装载区、卸载区、备停区在调度算法运行器件默认不发生改变,提前计算部分参量
# (uuid,index(id)映射关系, 装载区数量, 卸载区数量, 备停区数量, 以及初次统计动态调度矿卡)
(
load_area_uuid_to_index_dict,
unload_area_uuid_to_index_dict,
load_area_index_to_uuid_dict,
unload_area_index_to_uuid_dict,
) = build_work_area_uuid_index_map()
load_area_num, unload_area_num = len(load_area_uuid_to_index_dict), len(
unload_area_uuid_to_index_dict
)
park_uuid_to_index_dict, park_index_to_uuid_dict = build_park_uuid_index_map()
park_num = len(park_uuid_to_index_dict)
truck_uuid_to_name_dict, truck_name_to_uuid_dict = build_truck_uuid_name_map()
# 矿卡集合
truck_set = set(update_total_truck())
# 固定派车矿卡集合
fixed_truck_set = set(update_fixdisp_truck())
# 动态派车矿卡集合
# dynamic_truck_set = truck_set.difference(fixed_truck_set)
dynamic_truck_set = update_dynamic_truck()
dynamic_truck_num = len(dynamic_truck_set)
logger.info("可用于动态派车的矿卡:")
logger.info(dynamic_truck_set)
# 用于动态调度的挖机及卸载设备
dynamic_excavator_set = set(update_autodisp_excavator())
dynamic_excavator_num = len(dynamic_excavator_set)
dynamic_dump_set = set(update_autodisp_dump())
dynamic_dump_num = len(dynamic_dump_set)
global global_dict
global_dict = {}
global_dict["dynamic_truck_set"] = dynamic_truck_set
global_dict["dynamic_truck_num"] = dynamic_truck_num
global_dict["dynamic_excavator_set"] = dynamic_excavator_set
global_dict["dynamic_excavator_num"] = dynamic_excavator_num
global_dict["dynamic_dump_set"] = dynamic_dump_set
global_dict["dynamic_dump_num"] = dynamic_dump_num
global_dict["park_num"] = park_num
def get_value(name):
return global_dict[name]
# 设备映射类, 存储除工作区以外的映射关系
# 其余设备类继承该类
class DeviceMap:
def __init__(self):
self.excavator_uuid_to_index_dict = {}
self.dump_uuid_to_index_dict = {}
self.excavator_index_to_uuid_dict = {}
self.dump_index_to_uuid_dict = {}
self.dump_uuid_to_unload_area_uuid_dict = {}
self.excavator_uuid_to_load_area_uuid_dict = {}
self.excavator_index_to_load_area_index_dict = {}
self.dump_index_to_unload_area_index_dict = {}
self.truck_uuid_to_index_dict = {}
self.truck_index_to_uuid_dict = {}
def get_excavator_uuid_to_index_dict(self):
return self.excavator_uuid_to_index_dict
def get_dump_uuid_to_index_dict(self):
return self.dump_uuid_to_index_dict
def get_excavator_index_to_uuid_dict(self):
return self.excavator_index_to_uuid_dict
def get_dump_index_to_uuid_dict(self):
return self.dump_index_to_uuid_dict
def get_dump_uuid_to_unload_area_uuid_dict(self):
return self.dump_uuid_to_unload_area_uuid_dict
def get_excavator_uuid_to_load_area_uuid_dict(self):
return self.excavator_uuid_to_load_area_uuid_dict
def get_excavator_index_to_load_area_index_dict(self):
return self.excavator_index_to_load_area_index_dict
def get_dump_index_to_unload_area_index_dict(self):
return self.dump_index_to_unload_area_index_dict
def get_truck_uuid_to_index_dict(self):
return self.truck_uuid_to_index_dict
def get_truck_index_to_uuid_dict(self):
return self.truck_index_to_uuid_dict
def reset(self):
self.excavator_uuid_to_index_dict = {}
self.dump_uuid_to_index_dict = {}
self.excavator_index_to_uuid_dict = {}
self.dump_index_to_uuid_dict = {}
self.dump_uuid_to_unload_area_uuid_dict = {}
self.excavator_uuid_to_load_area_uuid_dict = {}
self.excavator_index_to_load_area_index_dict = {}
self.dump_index_to_unload_area_index_dict = {}
self.truck_uuid_to_index_dict = {}
self.truck_index_to_uuid_dict = {}
def period_map_para_update(self):
self.reset()
device_map_dict = update_deveices_map(
unload_area_uuid_to_index_dict, load_area_uuid_to_index_dict
)
self.excavator_uuid_to_index_dict = device_map_dict[
"excavator_uuid_to_index_dict"
]
self.dump_uuid_to_index_dict = device_map_dict["dump_uuid_to_index_dict"]
self.excavator_index_to_uuid_dict = device_map_dict[
"excavator_index_to_uuid_dict"
]
self.dump_index_to_uuid_dict = device_map_dict["dump_index_to_uuid_dict"]
self.dump_uuid_to_unload_area_uuid_dict = device_map_dict[
"dump_uuid_to_unload_area_uuid_dict"
]
self.excavator_uuid_to_load_area_uuid_dict = device_map_dict[
"excavator_uuid_to_load_area_uuid_dict"
]
self.excavator_index_to_load_area_index_dict = device_map_dict[
"excavator_index_to_load_area_index_dict"
]
self.dump_index_to_unload_area_index_dict = device_map_dict[
"dump_index_to_unload_area_index_dict"
]
truck_map_dict = update_truck_uuid_index_map(get_value("dynamic_truck_set"))
self.truck_uuid_to_index_dict = truck_map_dict["truck_uuid_to_index_dict"]
self.truck_index_to_uuid_dict = truck_map_dict["truck_index_to_uuid_dict"]
def period_map_para_load(self):
# 装载关系映射
self.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict
self.dump_uuid_to_index_dict = device_map.dump_uuid_to_index_dict
self.excavator_index_to_uuid_dict = device_map.excavator_index_to_uuid_dict
self.dump_index_to_uuid_dict = device_map.dump_index_to_uuid_dict
self.dump_uuid_to_unload_area_uuid_dict = (
device_map.dump_uuid_to_unload_area_uuid_dict
)
self.excavator_uuid_to_load_area_uuid_dict = (
device_map.excavator_uuid_to_load_area_uuid_dict
)
self.excavator_index_to_load_area_index_dict = (
device_map.excavator_index_to_load_area_index_dict
)
self.dump_index_to_unload_area_index_dict = (
device_map.dump_index_to_unload_area_index_dict
)
self.truck_uuid_to_index_dict = device_map.truck_uuid_to_index_dict
self.truck_index_to_uuid_dict = device_map.truck_index_to_uuid_dict
# 路网信息类
class WalkManage(DeviceMap):
def __init__(self):
# # 工作区和设备不具备一一对应关系, 为方便就计算, 算法维护两套路网: 面向路网和面向设备
# 路网真实距离
self.walk_time_to_excavator = np.full(
(dynamic_dump_num, dynamic_excavator_num), M
)
self.walk_time_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
self.walk_time_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
self.walk_time_park_to_load_area = np.full((park_num, load_area_num), M)
self.walk_time_to_load_area = np.full((unload_area_num, load_area_num), M)
self.walk_time_to_unload_area = np.full((unload_area_num, load_area_num), M)
# 路网行驶时间
self.distance_to_excavator = np.full(
(dynamic_dump_num, dynamic_excavator_num), M
)
self.distance_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
self.distance_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
self.distance_park_to_load_area = np.full((park_num, load_area_num), M)
self.distance_to_load_area = np.full((unload_area_num, load_area_num), M)
self.distance_to_unload_area = np.full((unload_area_num, load_area_num), M)
def get_walk_time_to_load_area(self):
return self.walk_time_to_load_area
def get_walk_time_to_unload_area(self):
return self.walk_time_to_unload_area
def get_walk_time_to_excavator(self):
return self.walk_time_to_excavator
def get_walk_time_to_dump(self):
return self.walk_time_to_dump
def get_walk_time_park_to_load_area(self):
return self.walk_time_park_to_load_area
def get_walk_time_park_to_excavator(self):
return self.walk_time_park_to_excavator
def get_distance_to_load_area(self):
return self.distance_to_load_area
def get_distance_to_unload_area(self):
return self.distance_to_unload_area
def get_distance_to_excavator(self):
return self.distance_to_excavator
def get_distance_to_dump(self):
return self.distance_to_dump
def get_distance_park_to_load_area(self):
return self.distance_park_to_load_area
def get_distance_park_to_excavator(self):
return self.distance_park_to_excavator
def reset(self):
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_dump_num = get_value("dynamic_dump_num")
park_num = get_value("park_num")
# 路网真实距离
self.walk_time_to_excavator = np.full(
(dynamic_dump_num, dynamic_excavator_num), M
)
self.walk_time_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
self.walk_time_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
self.walk_time_park_to_load_area = np.full((park_num, load_area_num), M)
self.walk_time_to_load_area = np.full((unload_area_num, load_area_num), M)
self.walk_time_to_unload_area = np.full((unload_area_num, load_area_num), M)
# 路网行驶时间
self.distance_to_excavator = np.full(
(dynamic_dump_num, dynamic_excavator_num), M
)
self.distance_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
self.distance_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
self.distance_park_to_load_area = np.full((park_num, load_area_num), M)
self.distance_to_load_area = np.full((unload_area_num, load_area_num), M)
self.distance_to_unload_area = np.full((unload_area_num, load_area_num), M)
def period_walk_para_update(self):
self.reset()
self.period_map_para_update()
# 计算路网距离及行走时间
try:
# 处理距离
for item in session_postgre.query(WalkTime).all():
load_area = str(item.load_area_id)
unload_area = str(item.unload_area_id)
load_area_index = load_area_uuid_to_index_dict[load_area]
unload_area_index = unload_area_uuid_to_index_dict[unload_area]
self.distance_to_load_area[unload_area_index][load_area_index] = float(
item.to_load_distance
)
self.walk_time_to_load_area[unload_area_index][load_area_index] = float(
60 / 1000 * item.to_load_distance / empty_speed
)
self.distance_to_unload_area[unload_area_index][
load_area_index
] = float(item.to_unload_distance)
self.walk_time_to_unload_area[unload_area_index][
load_area_index
] = float(60 / 1000 * item.to_unload_distance / heavy_speed)
except Exception as es:
logger.error("路网信息异常")
logger.error(es)
# 计算设备路网距离及行走时间
try:
for i in range(dynamic_dump_num):
for j in range(dynamic_excavator_num):
self.distance_to_excavator[i][j] = self.distance_to_load_area[
self.dump_index_to_unload_area_index_dict[i]
][self.excavator_index_to_load_area_index_dict[j]]
self.walk_time_to_excavator[i][j] = self.walk_time_to_load_area[
self.dump_index_to_unload_area_index_dict[i]
][self.excavator_index_to_load_area_index_dict[j]]
self.distance_to_dump[i][j] = self.distance_to_unload_area[
self.dump_index_to_unload_area_index_dict[i]
][self.excavator_index_to_load_area_index_dict[j]]
self.walk_time_to_dump[i][j] = self.walk_time_to_unload_area[
self.dump_index_to_unload_area_index_dict[i]
][self.excavator_index_to_load_area_index_dict[j]]
except Exception as es:
logger.error("设备路网信息异常异常")
logger.error(es)
try:
for item in session_postgre.query(WalkTimePark).all():
load_area = str(item.load_area_id)
park_area = str(item.park_area_id)
load_area_index = load_area_uuid_to_index_dict[load_area]
park_index = park_uuid_to_index_dict[park_area]
self.distance_park_to_load_area[park_index][load_area_index] = float(
item.park_load_distance
)
self.walk_time_park_to_load_area[park_index][load_area_index] = float(
60 / 1000 * item.park_load_distance / empty_speed
)
except Exception as es:
logger.error("备停区路网信息异常")
logger.error(es)
try:
for i in range(park_num):
for j in range(dynamic_excavator_num):
self.distance_park_to_excavator[i][j] = self.distance_park_to_load_area[
i
][self.excavator_index_to_load_area_index_dict[j]]
self.walk_time_park_to_excavator[i][
j
] = self.walk_time_park_to_load_area[i][
self.excavator_index_to_load_area_index_dict[j]
]
except Exception as es:
logger.error("备停区设备路网信息异常")
logger.error(es)
def period_walk_para_load(self):
# 装载路网信息
self.distance_to_load_area = walk_manage.distance_to_load_area
self.distance_to_unload_area = walk_manage.distance_to_unload_area
self.distance_park_to_load_area = walk_manage.distance_park_to_load_area
self.distance_to_excavator = walk_manage.distance_to_excavator
self.distance_to_dump = walk_manage.distance_to_dump
self.distance_park_to_excavator = walk_manage.distance_park_to_excavator
self.walk_time_to_excavator = walk_manage.walk_time_to_excavator
self.walk_time_to_dump = walk_manage.walk_time_to_dump
self.walk_time_park_to_excavator = walk_manage.walk_time_park_to_excavator
self.walk_time_to_load_area = walk_manage.walk_time_to_load_area
self.walk_time_to_unload_area = walk_manage.walk_time_to_unload_area
self.walk_time_park_to_load_area = walk_manage.walk_time_park_to_load_area
device_map = DeviceMap()
walk_manage = WalkManage()
device_map.period_map_para_update()
walk_manage.period_map_para_load()
walk_manage.period_walk_para_update()
def period_para_update():
global load_area_uuid_to_index_dict, load_area_index_to_uuid_dict
global unload_area_uuid_to_index_dict, unload_area_index_to_uuid_dict
global load_area_num, unload_area_num, park_num
global park_uuid_to_index_dict, park_index_to_uuid_dict
global truck_uuid_to_name_dict, truck_name_to_uuid_dict
global dynamic_truck_num, dynamic_excavator_num, dynamic_dump_num
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 装载区、卸载区、备停区在调度算法运行器件默认不发生改变,提前计算部分参量
# (uuid,index(id)映射关系, 装载区数量, 卸载区数量, 备停区数量, 以及初次统计动态调度矿卡)
(
load_area_uuid_to_index_dict,
unload_area_uuid_to_index_dict,
load_area_index_to_uuid_dict,
unload_area_index_to_uuid_dict,
) = build_work_area_uuid_index_map()
load_area_num, unload_area_num = len(load_area_uuid_to_index_dict), len(
unload_area_uuid_to_index_dict
)
park_uuid_to_index_dict, park_index_to_uuid_dict = build_park_uuid_index_map()
park_num = len(park_uuid_to_index_dict)
truck_uuid_to_name_dict, truck_name_to_uuid_dict = build_truck_uuid_name_map()
# 矿卡集合
truck_set = set(update_total_truck())
logger.info("truck_set")
logger.info(truck_set)
# 固定派车矿卡集合
fixed_truck_set = set(update_fixdisp_truck())
logger.info("fixed_truck_set")
logger.info(fixed_truck_set)
# 动态派车矿卡集合
# dynamic_truck_set = truck_set.difference(fixed_truck_set)
dynamic_truck_set = update_dynamic_truck()
dynamic_truck_num = len(dynamic_truck_set)
logger.info("可用于动态派车的矿卡:")
logger.info(dynamic_truck_num)
logger.info(dynamic_truck_set)
# 用于动态调度的挖机及卸载设备
dynamic_excavator_set = set(update_autodisp_excavator())
dynamic_excavator_num = len(dynamic_excavator_set)
dynamic_dump_set = set(update_autodisp_dump())
dynamic_dump_num = len(dynamic_dump_set)
device_map.period_map_para_update()
walk_manage.period_walk_para_update()
global_dict["dynamic_truck_set"] = dynamic_truck_set
global_dict["dynamic_truck_num"] = dynamic_truck_num
global_dict["dynamic_excavator_set"] = dynamic_excavator_set
global_dict["dynamic_excavator_num"] = dynamic_excavator_num
global_dict["dynamic_dump_set"] = dynamic_dump_set
global_dict["dynamic_dump_num"] = dynamic_dump_num
global_dict["park_num"] = park_num
global_dict["distance_to_excavator"] = walk_manage.distance_to_excavator
global_dict["distance_park_to_excavator"] = walk_manage.distance_park_to_excavator
global_dict["distance_to_dump"] = walk_manage.distance_to_dump
logger.info("walk_manage_para")
logger.info("distance_to_excavator")
logger.info(walk_manage.distance_to_excavator)
logger.info("distance_park_to_excavator")
logger.info(walk_manage.distance_park_to_excavator)
logger.info("distance_to_dump")
logger.info(walk_manage.distance_to_dump)
logger.info("excavator_uuid_to_index_dict")
logger.info(walk_manage.excavator_uuid_to_index_dict)
logger.info("dump_uuid_to_index_dict")
logger.info(walk_manage.dump_uuid_to_index_dict)
logger.info("walk_manage.distance_park_to_excavator")
logger.info(walk_manage.distance_park_to_excavator)
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/3 10:51
# @Author : Opfer
# @Site :
# @File : __init__.py.py
# @Software: PyCharm
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/26 14:35
# @Author : Opfer
# @Site :
# @File : path_plannner.py
# @Software: PyCharm
from equipment.truck import TruckInfo
from path_plan.priority_control import weighted_walk_cost, available_walk, update_group_walk_available
from para_config import *
from tables import *
M = 1000000
truck = TruckInfo()
truck.update_truck_size()
class PathPlanner(WalkManage):
def __init__(self):
# 路线行驶成本
self.rout_cost = np.array((unload_area_num, load_area_num))
# 路段集合
self.lane_set = {}
# 车辆长度(暂)
# self.truck_length = float(sum(truck.get_length().values())) / len(truck.get_length())
self.truck_length = 3
# 装载区数量
self.num_of_load_area = len(set(update_load_area()))
# 卸载区数量
self.num_of_unload_area = len(set(update_unload_area()))
# 备停区数量
self.num_of_park_area = len(set(update_park_area()))
# 路网行驶成本信息信息
self.cost_to_load_area = np.full((self.num_of_unload_area, self.num_of_load_area), M)
self.cost_to_unload_area = np.full((self.num_of_unload_area, self.num_of_load_area), M)
# 路网信息(备停区)
self.cost_park_to_load_area = np.full((self.num_of_park_area, self.num_of_load_area), M)
# 路段类
self.lane = LaneInfo()
self.lane.lane_speed_generate()
def path_cost_generate(self, load_area_id, unload_area_id, is_park):
# 卸载道路阻塞成本初始化
cost_to_unload_blockage = 0
# 装载道路阻塞成本初始化
cost_to_load_blockage = 0
# 卸载道路总成本初始化
to_unload_cost = 0
# 装载道路总成本初始化
to_load_cost = 0
# # 道路权重
# weighted_distance = weighted_walk_cost()
# 修正因子
weight = 60
# 阻塞成本权重
alpha = 0
# 距离成本权重
beta = 1
session_mysql.commit()
# 距离成本启用
rule1 = session_mysql.query(DispatchRule).filter_by(id=1).first()
if rule1.disabled == 0:
beta = rule1.rule_weight
# 拥堵成本启用
rule2 = session_mysql.query(DispatchRule).filter_by(id=2).first()
if rule2.disabled == 0:
alpha = rule2.rule_weight
beta /= beta
alpha = alpha / beta * weight
try:
# 备停区处理
if is_park:
# 提取指定道路记录
path = session_postgre.query(WalkTimePark).filter_by(park_area_id=unload_area_id,
load_area_id=load_area_id).first()
# 读取道路路段信息
for lane_id in path.park_load_lanes:
# 各路段阻塞成本累加
cost_to_load_blockage = cost_to_load_blockage + beta * self.lane_cost_generate(lane_id)
# 道路总成本=道路距离成本+道路阻塞成本
to_load_cost = alpha * cost_to_load_blockage + beta * path.park_load_distance
else:
path = session_postgre.query(WalkTime).filter_by(load_area_id=load_area_id,
unload_area_id=unload_area_id).first()
for lane_id in path.to_unload_lanes:
cost_to_unload_blockage = cost_to_unload_blockage + self.lane_cost_generate(lane_id)
for lane_id in path.to_load_lanes:
cost_to_load_blockage = cost_to_load_blockage + self.lane_cost_generate(lane_id)
to_unload_cost = alpha * cost_to_unload_blockage + beta * path.to_unload_distance
to_load_cost = alpha * cost_to_load_blockage + beta * path.to_load_distance
# print("拥堵因子-挖机")
# print(alpha, cost_to_load_blockage)
# print("拥堵因子-卸点")
# print(alpha, cost_to_unload_blockage)
except Exception as es:
logger.error(f'道路{load_area_id + "-" +unload_area_id}行驶成本计算异常')
logger.error(es)
return to_load_cost, to_unload_cost
def lane_cost_generate(self, lane_id):
try:
# 读取路段记录
lane_rec = session_postgre.query(Lane).filter_by(Id=lane_id).first()
# 道路长度
lane_length = lane_rec.Length
# 车辆自由行驶时的速度
clear_speed = lane_rec.MaxSpeed
# 1. 计算阻塞时车辆密度=路段长度/车辆长度
truck_density = lane_length / self.truck_length
# 2. 读取实际车流速度
actual_speed = self.lane.lane_speed_dict[lane_id]
# 3. 计算路段阻塞程度=(1-实际路段速度)/路段最高速度
lane_blockage = (1 - actual_speed / clear_speed) * truck_density
except Exception as es:
logger.error('路段拥堵成本计算异常')
logger.error(es)
return lane_blockage
def walk_cost(self):
self.period_walk_para_load()
self.period_map_para_load()
# 计算行驶成本前,更新路网速度信息
self.lane.lane_speed_generate()
try:
# 读取路网成本
for walk_time in session_postgre.query(WalkTime).all():
load_area_id, unload_area_id = str(walk_time.load_area_id), str(walk_time.unload_area_id)
unload_area_index = unload_area_uuid_to_index_dict[unload_area_id]
load_area_index = load_area_uuid_to_index_dict[load_area_id]
self.cost_to_load_area[unload_area_index][load_area_index], \
self.cost_to_unload_area[unload_area_index][load_area_index] = \
self.path_cost_generate(load_area_id, unload_area_id, False)
# 读取备停区路网成本
for walk_time_park in session_postgre.query(WalkTimePark).all():
park_area_index = park_uuid_to_index_dict[str(walk_time_park.park_area_id)]
load_area_index = load_area_uuid_to_index_dict[str(walk_time_park.load_area_id)]
self.cost_park_to_load_area[park_area_index][load_area_index], _ = \
self.path_cost_generate(str(walk_time_park.load_area_id), str(walk_time_park.park_area_id), True)
except Exception as es:
logger.error('路网信息计成本计算异常')
logger.error(es)
cost_to_excavator = np.zeros_like(get_value("distance_to_excavator"))
cost_to_dump = np.zeros_like(get_value("distance_to_dump"))
cost_park_to_excavator = np.zeros_like(get_value("distance_park_to_excavator"))
logger.info("distance_park_to_excavator")
logger.info(self.distance_park_to_excavator)
# try:
# 路网权重
walk_weight, park_walk_weight = weighted_walk_cost()
# 路网禁用关系
walk_available = available_walk()
group_walk_available = update_group_walk_available()
logger.info("path_weight")
logger.info(walk_weight)
logger.info("walk_avail")
logger.info(walk_available)
# except Exception as es:
# logger.error("无派车计划可用")
for i in range(get_value("dynamic_dump_num")):
for j in range(get_value("dynamic_excavator_num")):
load_area_index = self.excavator_index_to_load_area_index_dict[j]
unload_area_index = self.dump_index_to_unload_area_index_dict[i]
logger.info("cost_to_excavator")
logger.info(cost_to_excavator)
cost_to_excavator[i][j] = self.cost_to_load_area[unload_area_index][load_area_index] / walk_weight[i][j] + group_walk_available[i][j]
cost_to_dump[i][j] = self.cost_to_unload_area[unload_area_index][load_area_index] / walk_weight[i][j] + walk_available[i][j] + group_walk_available[i][j]
for j in range(get_value("dynamic_excavator_num")):
load_area_index = self.excavator_index_to_load_area_index_dict[j]
cost_park_to_excavator[0][j] = self.cost_park_to_load_area[0][load_area_index] / park_walk_weight[0][j]
logger.info("真实路网距离-驶往挖机:")
logger.info(self.distance_to_excavator)
logger.info("真实路网距离-驶往卸点:")
logger.info(self.distance_to_dump)
logger.info("真实备停区路网距离-驶往挖机:")
logger.info(self.distance_park_to_excavator)
logger.info("阻塞路网距离-驶往挖机:")
logger.info(cost_to_excavator)
logger.info("阻塞路网距离-驶往卸点:")
logger.info(cost_to_dump)
logger.info("阻塞备停区路网距离-驶往挖机:")
logger.info(cost_park_to_excavator)
return cost_to_excavator, cost_to_dump, cost_park_to_excavator
class LaneInfo:
def __init__(self):
self.lane_speed_dict = {}
def update_truck_speed(self):
# 读取矿卡实时速度信息
try:
truck_speed_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
# json_value = json.loads(redis2.get(item))
key_value_dict = redis2.hgetall(item)
device_type = key_value_dict[str_to_byte('type')]
if device_type == 1 and str_to_byte('speed') in key_value_dict.keys():
truck_speed = key_value_dict[str_to_byte('speed')]
truck_speed_dict[truck_name_to_uuid_dict[item]] = truck_speed
except Exception as es:
logger.error(f'矿卡{item}实时速度读取异常')
logger.error(es)
return truck_speed_dict
def update_truck_loacate(self):
# 读取矿卡所在路段信息
try:
truck_locate_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
# json_value = json.loads(redis2.get(item))
key_value_dict = redis2.hgetall(item)
device_type = key_value_dict[str_to_byte('type')]
# is_online = key_value_dict[str_to_byte('online')]
key_set = key_value_dict.keys()
if device_type == 1 and str_to_byte('online') in key_set and str_to_byte('laneId') in key_set:
truck_locate = key_value_dict[str_to_byte('laneId')]
truck_locate_dict[truck_name_to_uuid_dict[item]] = truck_locate
except Exception as es:
logger.error(f'矿卡{item}所在路段信息读取异常')
logger.error(es)
return truck_locate_dict
def lane_speed_generate(self):
# truck -> lane
truck_locate_dict = self.update_truck_loacate()
logger.info("矿卡位于路段:")
logger.info(truck_locate_dict)
# truck -> speed
truck_speed_dict = self.update_truck_speed()
logger.info("矿卡当前速度:")
logger.info(truck_speed_dict)
try:
# lane_set, 用到的路段集合
lane_set = []
for walk_time in session_postgre.query(WalkTime).all():
for lane in walk_time.to_load_lanes:
lane_set.append(lane)
for lane in walk_time.to_unload_lanes:
lane_set.append(lane)
for walk_time_park in session_postgre.query(WalkTimePark).all():
for lane in walk_time_park.park_load_lanes:
lane_set.append(lane)
lane_set = set(lane_set)
except Exception as es:
logger.error('所用路网路段集合读取异常')
logger.info(es)
# lane -> speed, 各路段平均行驶速度
self.lane_speed_dict = {}
# lane -> num, 各路段行驶车辆
lane_trucks_dict = {}
# used lane, 存在行驶矿卡的路段
tmp_lane_set = []
try:
# 初始化
for lane_id in lane_set:
self.lane_speed_dict[str(lane_id)] = 0
lane_trucks_dict[str(lane_id)] = 0
# 对于各路段信息
for truck in truck_locate_dict.keys():
lane_id = truck_locate_dict[truck]
if lane_id in lane_set:
self.lane_speed_dict[truck_locate_dict[truck]] = self.lane_speed_dict[truck_locate_dict[truck]] + \
truck_speed_dict[truck]
# 该路段矿卡数量加一
lane_trucks_dict[truck_locate_dict[truck]] = lane_trucks_dict[truck_locate_dict[truck]] + 1
# 记录存在行驶矿卡的路段
tmp_lane_set.append(lane_id)
# 存在矿卡的路段
# print("存在矿卡的路段:")
# print(tmp_lane_set)
logger.info("存在矿卡的路段:")
logger.info(tmp_lane_set)
# 对不存在的矿卡路段,实时速度设置为最高
for lane_id in lane_set:
if lane_id not in tmp_lane_set:
self.lane_speed_dict[str(lane_id)] = session_postgre.query(Lane).filter_by(Id=lane_id).first().MaxSpeed
lane_trucks_dict[str(lane_id)] = 1
# 各路段实时速度取平均
for lane in lane_trucks_dict:
self.lane_speed_dict[lane] = self.lane_speed_dict[lane] / lane_trucks_dict[lane]
except Exception as es:
logger.error("路段实时速度计算异常")
logger.error(es)
return self.lane_speed_dict
# path_planner = PathPlanner()
#
# path_planner.walk_cost()
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/9/3 14:44
# @Author : Opfer
# @Site :
# @File : priority_control.py
# @Software: PyCharm
from equipment.truck import *
from equipment.dump import *
from equipment.excavator import *
from para_config import *
truck = TruckInfo()
excavator = ExcavatorInfo()
dump = DumpInfo()
def weighted_walk_cost():
dynamic_dump_num = get_value("dynamic_dump_num")
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_dump_set = get_value("dynamic_dump_set")
dynamic_excavator_set = get_value("dynamic_excavator_set")
excavator.para_period_update()
dump.para_period_update()
walk_weight = np.ones((dynamic_dump_num, dynamic_excavator_num))
excavator_priority = excavator.excavator_priority_coefficient
excavator_material_priority = excavator.excavator_material_priority
dump_priority = dump.dump_priority_coefficient
dump_material_priority = np.ones(dynamic_dump_num)
park_walk_weight = np.ones((park_num, dynamic_excavator_num))
rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first()
if not rule6.disabled:
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = excavator.excavator_uuid_to_index_dict[excavator_id]
walk_weight[dump_index][excavator_inedx] += dump_priority[dump_index] * \
excavator_priority[excavator_inedx]
park_walk_weight = park_walk_weight * excavator.excavator_priority_coefficient
rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first()
if not rule7.disabled:
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = excavator.excavator_uuid_to_index_dict[excavator_id]
walk_weight[dump_index][excavator_inedx] += dump_material_priority[dump_index] * \
excavator_material_priority[excavator_inedx]
park_walk_weight = park_walk_weight * excavator.excavator_material_priority
walk_weight = walk_weight - (walk_weight.min() - 1)
park_walk_weight = park_walk_weight - (park_walk_weight.min() - 1)
return walk_weight, park_walk_weight
def available_walk():
dynamic_dump_num = get_value("dynamic_dump_num")
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_dump_set = get_value("dynamic_dump_set")
dynamic_excavator_set = get_value("dynamic_excavator_set")
excavator.para_period_update()
dump.para_period_update()
walk_weight = np.zeros((dynamic_dump_num, dynamic_excavator_num))
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = excavator.excavator_uuid_to_index_dict[excavator_id]
if excavator.excavator_material[excavator_id] != dump.dump_material[dump_id]:
walk_weight[dump_index][excavator_inedx] += 1000000
return walk_weight
def update_group_walk_available():
group_walk_available = np.full((get_value("dynamic_dump_num"), get_value("dynamic_excavator_num")), 1000000)
for dump_id in get_value("dynamic_dump_set"):
for excavator_id in get_value("dynamic_excavator_set"):
item = session_mysql.query(Dispatch).filter_by(dump_id=dump_id, exactor_id=excavator_id, isauto=1, isdeleted=0).first()
if item is not None:
dump_index = dump.dump_uuid_to_index_dict[dump_id]
excavator_index = excavator.excavator_uuid_to_index_dict[excavator_id]
group_walk_available[dump_index][excavator_index] = 0
return group_walk_available
#还没想好写什么
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/21 16:45
# @Author : Opfer
# @Site :
# @File : realtime_dispatch.py
# @Software: PyCharm
# 实时调度模块
from traffic_flow.traffic_flow_planner import *
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo()
# 调度类
class Dispatcher(WalkManage):
def __init__(self):
# 模拟挖机/卸载设备产量(防止调度修改真实产量)
self.sim_dump_real_mass = np.zeros(dump.get_dump_num())
self.sim_excavator_real_mass = np.zeros(excavator.get_excavator_num())
# 真实设备可用时间
self.cur_truck_reach_dump = np.zeros(truck.get_truck_num())
self.cur_truck_reach_excavator = np.zeros(truck.get_truck_num())
self.cur_excavator_ava_time = np.zeros(excavator.get_excavator_num())
self.cur_dump_ava_time = np.zeros(dump.get_dump_num())
# 卡车完成装载及卸载时间(矿卡可用时间)
self.cur_truck_ava_time = np.zeros(truck.get_truck_num())
# 模拟矿卡可用时间
self.sim_truck_ava_time = np.zeros(truck.get_truck_num())
# 模拟各设备可用时间(防止调度修改真实产量)
self.sim_excavator_ava_time = np.zeros(excavator.get_excavator_num())
self.sim_dump_ava_time = np.zeros(dump.get_dump_num())
# 挖机/卸载设备预计产量(包含正在驶往挖机/卸载设备那部分矿卡的载重)
self.pre_dump_real_mass = np.zeros(dump.get_dump_num())
self.pre_excavator_real_mass = np.zeros(excavator.get_excavator_num())
# 维护一个矿卡调度表
self.Seq = [[] for _ in range(truck.get_truck_num())]
# 调度开始时间
self.start_time = datetime.now()
# self.relative_now_time = datetime.now() - self.start_time
# 下面是交通流调度部分
# 驶往挖机的实际车流
self.actual_goto_excavator_traffic_flow = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
# 驶往卸载设备的实际车流
self.actual_goto_dump_traffic_flow = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往挖机的实际车次
self.goto_dump_truck_num = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往卸载设备的实际车次
self.goto_excavator_truck_num = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
# 驶往挖机的理想车流
self.opt_goto_dump_traffic_flow = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往卸载设备的实际车流
self.opt_goto_excavator_traffic_flow = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
self.path = PathPlanner()
self.group = Group()
# 更新矿卡预计抵达目的地时间
def update_truck_reach_time(self):
try:
dynamic_excavator_num = excavator.get_excavator_num()
dumps = dump.get_dump_num()
trucks = truck.get_truck_num()
truck_current_task = truck.get_truck_current_task()
truck_current_trip = truck.get_truck_current_trip()
cur_truck_reach_excavator = truck.get_truck_reach_excavator()
cur_truck_reach_dump = truck.get_truck_reach_dump()
excavator_ava_ls = [[] for _ in range(dynamic_excavator_num)]
dump_ava_ls = [[] for _ in range(dumps)]
for i in range(trucks):
task = truck_current_task[truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
if task in [0, 1]:
reach_time = cur_truck_reach_excavator[i]
excavator_ava_ls[end_area_index].append(
[reach_time, i, end_area_index]
)
elif task in [3, 4]:
reach_time = cur_truck_reach_dump[i]
dump_ava_ls[end_area_index].append([reach_time, i, end_area_index])
elif task == -2:
self.cur_truck_ava_time[i] = (
datetime.now() - self.start_time
) / timedelta(hours=0, minutes=1, seconds=0)
# print(truck_index_to_uuid_dict)
# print(excavator_ava_ls)
# print(dump_ava_ls)
except Exception as es:
logger.error("矿卡预计抵达时间计算异常")
logger.error(es)
return excavator_ava_ls, dump_ava_ls
# 更新挖机预计可用时间
def update_excavator_ava_time(self, excavator_ava_ls):
# 初始化挖机可用时间
self.cur_excavator_ava_time = np.full(
get_value("dynamic_excavator_num"),
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
loading_time = excavator.get_loading_time()
loading_task_time = 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_ava_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])
self.cur_excavator_ava_time[excavator_index] = (
max(tmp[i][0], self.cur_excavator_ava_time[excavator_index])
+ loading_task_time[excavator_index]
)
self.cur_truck_ava_time[
int(tmp[i][1])
] = self.cur_excavator_ava_time[excavator_index]
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.cur_excavator_ava_time[excavator_index] - now) > 60:
# self.cur_truck_ava_time[int(tmp[i][1])] = now
# if abs(self.cur_excavator_ava_time[excavator_index] - now) > 60:
# self.cur_excavator_ava_time[excavator_index] = now
except Exception as es:
logger.error("挖机可用时间计算异常")
logger.error(es)
# 更新卸载设备预计可用时间
def update_dump_ava_time(self, dump_ava_ls):
dynamic_dump_num = dump.get_dump_num()
# 初始化卸载设备可用时间
self.cur_dump_ava_time = np.full(
dynamic_dump_num,
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
unloading_time = dump.get_unloading_time()
unloading_task_time = 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_ava_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])
self.cur_dump_ava_time[dump_index] = (
max(tmp[i][0], self.cur_dump_ava_time[dump_index])
+ unloading_task_time[dump_index]
)
self.cur_truck_ava_time[
int(tmp[i][1])
] = self.cur_dump_ava_time[dump_index]
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.cur_dump_ava_time[dump_index] - now) > 60:
# self.cur_dump_ava_time[dump_index] = now
# if abs(self.cur_truck_ava_time[int(tmp[i][1])] - now) > 60:
# self.cur_truck_ava_time[int(tmp[i][1])] = now
except Exception as es:
logger.error("卸载设备可用时间计算异常")
logger.error(es)
# 更新实际交通流
def update_actual_traffic_flow(self):
loading_task_time = excavator.get_loading_task_time()
unloading_task_time = dump.get_unloading_task_time()
truck_current_task = truck.get_truck_current_task()
truck_current_trip = truck.get_truck_current_trip()
payload = truck.get_payload()
dynamic_dump_num = dump.get_dump_num()
dynamic_excavator_num = excavator.get_excavator_num()
self.goto_dump_truck_num = np.zeros((dynamic_excavator_num, dynamic_dump_num))
self.actual_goto_dump_traffic_flow = np.zeros(
(dynamic_excavator_num, dynamic_dump_num)
)
self.goto_excavator_truck_num = np.zeros(
(dynamic_dump_num, dynamic_excavator_num)
)
self.actual_goto_excavator_traffic_flow = np.zeros(
(dynamic_dump_num, dynamic_excavator_num)
)
# try:
for i in range(dynamic_truck_num):
task = truck_current_task[truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
start_area_index = truck_current_trip[i][0]
if task in heavy_task_set:
self.goto_dump_truck_num[start_area_index][end_area_index] += 1
self.actual_goto_dump_traffic_flow[start_area_index][end_area_index] += float(payload[i])
# logger.info("debug2")
if task in empty_task_set:
self.goto_excavator_truck_num[start_area_index][end_area_index] += 1
self.actual_goto_excavator_traffic_flow[start_area_index][end_area_index] += float(payload[i])
self.actual_goto_dump_traffic_flow = self.actual_goto_dump_traffic_flow / (
self.distance_to_dump.reshape(dynamic_excavator_num, dynamic_dump_num)
/ (1000 * empty_speed)
+ np.expand_dims(unloading_task_time, axis=0).repeat(
dynamic_excavator_num, axis=0
)
)
self.actual_goto_excavator_traffic_flow = (
self.actual_goto_excavator_traffic_flow
/ (
self.distance_to_excavator.reshape(
dynamic_dump_num, dynamic_excavator_num
)
/ (1000 * heavy_speed)
+ np.expand_dims(loading_task_time, axis=0).repeat(
dynamic_dump_num, axis=0
)
)
)
logger.info("self.goto_dump_truck_num")
logger.info(self.goto_dump_truck_num)
logger.info("self.actual_goto_dump_traffic_flow")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("self.goto_excavator_truck_num")
logger.info(self.goto_excavator_truck_num)
logger.info("self.actual_goto_excavator_traffic_flow")
logger.info(self.actual_goto_excavator_traffic_flow)
# except Exception as es:
# logger.error("未知错误001")
# logger.error(es)
# print("驶往卸点实际载重")
# print(self.actual_goto_dump_traffic_flow)
# print("卸点路段行驶时间(h)")
# print((self.distance_to_dump.reshape(dynamic_excavator_num, dynamic_dump_num) / (1000 * empty_speed)))
# print("驶往卸点实际车流")
# print(self.actual_goto_dump_traffic_flow)
logger.info("驶往卸点实际载重")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("卸点路段行驶时间(h)")
logger.info(
(
self.distance_to_dump.reshape(dynamic_excavator_num, dynamic_dump_num)
/ (1000 * empty_speed)
)
)
logger.info("驶往卸点实际车流")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("________________loading_task_time__________")
logger.info(loading_task_time)
# self.actual_goto_excavator_traffic_flow = (
# self.actual_goto_excavator_traffic_flow
# / (
# self.distance_to_excavator.reshape(
# dynamic_dump_num, dynamic_excavator_num
# )
# / (1000 * heavy_speed)
# + np.expand_dims(loading_task_time, axis=0).repeat(
# dynamic_dump_num, axis=0
# )
# )
# )
# print("驶往挖机实际载重")
# print(self.actual_goto_excavator_traffic_flow)
# print("挖机路段行驶时间(h)")
# print((self.distance_to_excavator.reshape(dynamic_excavator_num, dynamic_dump_num) / (1000 * heavy_speed)))
# print("驶往挖机实际车流")
# print(self.actual_goto_excavator_traffic_flow)
logger.info("驶往挖机实际载重")
logger.info(self.actual_goto_excavator_traffic_flow)
logger.info("挖机路段行驶时间(h)")
logger.info(
(
self.distance_to_excavator.reshape(
dynamic_excavator_num, dynamic_dump_num
)
/ (1000 * heavy_speed)
)
)
logger.info("驶往挖机实际车流")
logger.info(self.actual_goto_excavator_traffic_flow)
def para_period_update(self):
logger.info("#####################################周期更新开始#####################################")
# 调度分组更新
self.group.period_update()
# 装载映射参数及
self.period_map_para_load()
self.period_walk_para_load()
# 更新卸载设备对象
dump.para_period_update()
# 更新挖机对象
excavator.para_period_update()
# 更新矿卡对象
truck.para_period_update()
def state_period_update(self):
# try:
truck.state_period_update()
# 更新实时车流
self.update_actual_traffic_flow()
# 计算理想车流
(self.opt_goto_dump_traffic_flow, self.opt_goto_excavator_traffic_flow,) = traffic_flow_plan()
# 矿卡抵达时间
excavator_reach_list, dump_reach_list = self.update_truck_reach_time()
# 挖机可用时间
self.update_excavator_ava_time(excavator_reach_list)
# 卸载设备可用时间
self.update_dump_ava_time(dump_reach_list)
self.cost_to_excavator, self.cost_to_dump, self.cost_park_to_excavator = self.path.walk_cost()
# except Exception as es:
# logger.error("周期更新异常")
# logger.error(es)
def sim_para_reset(self):
# 设备可用时间重置
self.sim_truck_ava_time = copy.deepcopy(self.cur_truck_ava_time)
self.sim_excavator_ava_time = copy.deepcopy(self.cur_excavator_ava_time)
self.sim_dump_ava_time = copy.deepcopy(self.cur_dump_ava_time)
def reset(self):
# 模拟挖机/卸载设备产量(防止调度修改真实产量)
self.sim_dump_real_mass = np.zeros(dump.get_dump_num())
self.sim_excavator_real_mass = np.zeros(excavator.get_excavator_num())
# 真实设备可用时间
self.cur_truck_reach_dump = np.zeros(truck.get_truck_num())
self.cur_truck_reach_excavator = np.zeros(truck.get_truck_num())
self.cur_excavator_ava_time = np.zeros(excavator.get_excavator_num())
self.cur_dump_ava_time = np.zeros(dump.get_dump_num())
# 卡车完成装载及卸载时间(矿卡可用时间)
self.cur_truck_ava_time = np.zeros(truck.get_truck_num())
# 模拟矿卡可用时间
self.sim_truck_ava_time = np.zeros(truck.get_truck_num())
# 模拟各设备可用时间(防止调度修改真实产量)
self.sim_excavator_ava_time = np.zeros(excavator.get_excavator_num())
self.sim_dump_ava_time = np.zeros(dump.get_dump_num())
# 挖机/卸载设备预计产量(包含正在驶往挖机/卸载设备那部分矿卡的载重)
self.pre_dump_real_mass = np.zeros(dump.get_dump_num())
self.pre_excavator_real_mass = np.zeros(excavator.get_excavator_num())
# 维护一个矿卡调度表
self.Seq = [[] for _ in range(truck.get_truck_num())]
# 下面是交通流调度部分
# 驶往挖机的实际车流
self.actual_goto_excavator_traffic_flow = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
# 驶往卸载设备的实际车流
self.actual_goto_dump_traffic_flow = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往挖机的实际车次
self.goto_dump_truck_num = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往卸载设备的实际车次
self.goto_excavator_truck_num = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
# 驶往挖机的理想车流
self.opt_goto_dump_traffic_flow = np.zeros(
(excavator.get_excavator_num(), dump.get_dump_num())
)
# 驶往卸载设备的实际车流
self.opt_goto_excavator_traffic_flow = np.zeros(
(dump.get_dump_num(), excavator.get_excavator_num())
)
def truck_schedule(self, truck_id):
rule3 = session_mysql.query(DispatchRule).filter_by(id=3).first().disabled
rule4 = session_mysql.query(DispatchRule).filter_by(id=4).first().disabled
# cost_to_excavator, cost_to_dump, cost_park_to_excavator = self.path.walk_cost()
excavator_priority_coefficient = excavator.excavator_priority_coefficient
excavator_material_priority = excavator.excavator_material_priority
# 矿卡对应序号
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.truck_index_to_uuid_dict[truck_index]]
# 挖机装载时间
loading_time = excavator.get_loading_time()
# 路网信息
walk_time_park_to_excavator = walk_manage.get_walk_time_park_to_excavator() \
* (empty_speed / float(truck.empty_speed[truck_id]))
if truck_id not in self.group.dispatch_truck_group:
logger.error("无该矿卡")
return -1
# 矿卡调度分组
group_id = self.group.dispatch_truck_group[truck_id]
dynamic_dump_num = dump.get_dump_num()
dynamic_excavator_num = excavator.get_excavator_num()
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0))
logger.info("==========================================================")
logger.info(f"调度矿卡 {truck_id} {truck_index} {truck_uuid_to_name_dict[truck_id]}")
target = 0
if task == -2:
try:
logger.info("矿卡状态:矿卡启动或故障恢复")
logger.info("矿卡行程:无")
logger.info(f"涉及挖机:{list(excavator.excavator_uuid_to_index_dict.keys())}")
logger.info(
f"行程时间:{(np.maximum(self.sim_excavator_ava_time, now + walk_time_park_to_excavator[0, :]) + loading_time - now)}")
logger.info(f"行驶时间:{walk_time_park_to_excavator[0, :] + loading_time}")
logger.info("物料类型")
if truck_id in truck.truck_material_bind:
logger.info(truck.truck_material_bind[truck_id])
logger.info("挖机物料优先级")
logger.info(excavator_material_priority)
logger.info("挖机设备优先级")
logger.info(excavator_priority_coefficient)
logger.info("分组车流")
logger.info(self.group.group_actual_goto_dump_traffic_flow[group_id])
logger.info(self.group.group_opt_goto_dump_traffic_flow[group_id])
except Exception as es:
logger.error(f"矿卡{truck_id}状态不匹配")
logger.error(es)
# 矿卡是否存在绑定挖机
if truck_id in truck.truck_excavator_bind:
target = excavator.excavator_uuid_to_index_dict[truck.truck_excavator_bind[truck_id]]
else:
transport_value = self.group.group_park_to_excavator[group_id]
excavator_exclude_modify = self.group.group_excavator_exclude_modify[truck_id]
excavator_material_bind_modify = self.group.group_excavator_material_bind_modify[truck_id]
logger.info("transport_value")
# logger.info(transport_value)
# target = np.argmin(
# transport_value
# + truck.excavator_exclude_modify[truck_index]
# + truck.excavator_material_bind_modify[truck_index])
logger.info(transport_value)
target = np.argmin(
transport_value
+ excavator_exclude_modify)
# + excavator_material_bind_modify)
target = self.excavator_uuid_to_index_dict[self.group.group_excavator_index_to_uuid_dict[group_id][target]]
logger.info(f"目的地:{excavator.excavator_index_to_uuid_dict[target]}")
if task in [0, 1, 2]:
try:
logger.info("矿卡状态:矿卡空载")
logger.info(f"涉及卸载设备:{list(dump.dump_uuid_to_index_dict.keys())}")
except Exception as es:
logger.error(f"矿卡{truck_id}状态不匹配")
logger.error(es)
try:
assert np.array(self.actual_goto_dump_traffic_flow).shape == (
dynamic_excavator_num,
dynamic_dump_num,)
assert np.array(self.opt_goto_dump_traffic_flow).shape == (
dynamic_excavator_num,
dynamic_dump_num,)
except Exception as es:
logger.warning(es)
self.actual_goto_dump_traffic_flow = np.array(
self.actual_goto_dump_traffic_flow).reshape((dynamic_excavator_num, dynamic_dump_num))
self.opt_goto_dump_traffic_flow = np.array(
self.opt_goto_dump_traffic_flow).reshape((dynamic_excavator_num, dynamic_dump_num))
self.actual_goto_dump_traffic_flow = np.array(self.actual_goto_dump_traffic_flow)
self.opt_goto_dump_traffic_flow = np.array(self.opt_goto_dump_traffic_flow)
try:
logger.info("挖机id:")
logger.info(excavator.excavator_uuid_to_index_dict)
logger.info("卸点id:")
logger.info(dump.dump_uuid_to_index_dict)
logger.info(f"卸载点实际车流:")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info(f"卸载点理想车流:")
logger.info(self.opt_goto_dump_traffic_flow)
logger.info("卸载点实际车流")
logger.info(self.actual_goto_dump_traffic_flow[int(trip[1]), :])
logger.info("卸载点理想车流")
logger.info(self.opt_goto_dump_traffic_flow[int(trip[1]), :])
logger.info("空载trip")
logger.info(trip)
logger.info("物料类型")
if truck_id in truck.truck_material_bind:
logger.info(truck.truck_material_bind[truck_id])
logger.info("驶往卸点的运输成本")
logger.info(self.cost_to_dump)
logger.info("卸点物料修正")
logger.info(truck.dump_material_bind_modify)
except Exception as es:
logger.info("车流及修正因子")
logger.info(es)
if truck_id in truck.truck_dump_bind:
bind_unload_area_id = truck.truck_dump_bind[truck_id]
for key, value in dump.dump_index_to_unload_area_index_dict.items():
if value == unload_area_uuid_to_index_dict[bind_unload_area_id]:
target = key
break
else:
excavator_index = int(trip[1])
excavator_id = self.excavator_index_to_uuid_dict[excavator_index]
print(self.group.group_excavator_uuid_to_index_dict[group_id])
group_excavator_index = self.group.group_excavator_uuid_to_index_dict[group_id][excavator_id]
if rule3 and rule4:
# transport_value = self.cost_to_dump[:, int(trip[1])]
transport_value = self.group.group_walk_to_dump_cost[group_excavator_index, :]
else:
# 提取group actual traffic flow
group_actual_goto_dump_traffic_flow = self.group.group_actual_goto_dump_traffic_flow[group_id]
# 提取group actual traffic flow
group_opt_goto_dump_traffic_flow = self.group.group_opt_goto_dump_traffic_flow[group_id]
logger.info("驶往卸点分组车流")
logger.info(group_actual_goto_dump_traffic_flow)
logger.info(group_opt_goto_dump_traffic_flow)
transport_value = (group_actual_goto_dump_traffic_flow[group_excavator_index, :] + 0.001) \
/ (group_opt_goto_dump_traffic_flow[group_excavator_index, :] + 0.001)
# transport_value = (self.actual_goto_dump_traffic_flow[int(trip[1]), :] + 0.001) \
# / (self.opt_goto_dump_traffic_flow[int(trip[1]), :] + 0.001)
logger.info("transport_value")
logger.info(transport_value)
logger.info("dump_material_bind_modify")
logger.info(truck.dump_material_bind_modify[truck_index])
dump_material_bind_modify = self.group.group_dump_material_bind_modify[truck_id]
target = np.argmin(
transport_value
+ dump_material_bind_modify)
target = self.dump_uuid_to_index_dict[self.group.group_dump_index_to_uuid_dict[group_id][target]]
logger.info("车流比:")
logger.info((self.actual_goto_dump_traffic_flow[int(trip[1]), :] + 0.001) \
/ (self.opt_goto_dump_traffic_flow[int(trip[1]), :] + 0.001))
logger.info(f"目的地:{dump.dump_index_to_uuid_dict[target]}")
elif task in [3, 4, 5]:
try:
logger.info("矿卡状态:矿卡重载")
logger.info(f"涉及挖机设备:{list(excavator.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
logger.error(f"矿卡{truck_id}状态不匹配")
logger.error(es)
# 读取车流信息
try:
assert np.array(self.actual_goto_excavator_traffic_flow).shape == (
dynamic_dump_num,
dynamic_excavator_num,)
assert np.array(self.opt_goto_excavator_traffic_flow).shape == (
dynamic_dump_num,
dynamic_excavator_num,)
except Exception as es:
logger.warning(es)
self.actual_goto_excavator_traffic_flow = np.array(
self.actual_goto_excavator_traffic_flow).reshape((dynamic_dump_num, dynamic_excavator_num))
self.opt_goto_excavator_traffic_flow = np.array(
self.opt_goto_excavator_traffic_flow).reshape((dynamic_dump_num, dynamic_excavator_num))
# 不知道为什么,偶尔变成了list
self.actual_goto_excavator_traffic_flow = np.array(self.actual_goto_excavator_traffic_flow)
self.opt_goto_excavator_traffic_flow = np.array(self.opt_goto_excavator_traffic_flow)
try:
logger.info("挖机id:")
logger.info(excavator.excavator_uuid_to_index_dict)
logger.info("卸点id:")
logger.info(dump.dump_uuid_to_index_dict)
logger.info(f"挖机实际车流:")
logger.info(self.actual_goto_excavator_traffic_flow)
logger.info(f"挖机理想车流:")
logger.info(self.opt_goto_excavator_traffic_flow)
logger.info("重载trip")
logger.info(trip)
try:
logger.info("挖机实际车流_行")
logger.info(self.actual_goto_excavator_traffic_flow[trip[1], :])
logger.info("挖机理想车流_行")
logger.info(self.opt_goto_excavator_traffic_flow[trip[1], :])
except Exception as es:
logger.info("trip出错")
logger.info(trip)
logger.info(es)
logger.info("物料类型")
if truck_id in truck.truck_material_bind:
logger.info(truck.truck_material_bind[truck_id])
logger.info("驶往挖机的运输成本")
logger.info(self.cost_to_excavator)
logger.info("挖机物料修正")
logger.info(truck.excavator_material_bind_modify)
logger.info("挖机优先级修正")
logger.info(excavator.excavator_priority_coefficient)
except Exception as es:
logger.info("车流及修正因子")
logger.info(es)
# 计算目的地
try:
if truck_id in truck.truck_excavator_bind:
target = excavator.excavator_uuid_to_index_dict[truck.truck_excavator_bind[truck_id]]
logger.info("矿卡已绑定挖机")
else:
logger.info("cost_to_excavator")
logger.info(self.cost_to_excavator)
dump_index = int(trip[1])
dump_id = self.dump_uuid_to_index_dict[dump_index]
if rule3 and rule4:
# transport_value = self.cost_to_excavator[int(trip[1]), :]
transport_value = self.group.group_walk_to_excavator_cost[dump_index, :]
else:
group_dump_index = self.group.group_dump_uuid_to_index_dict[group_id][dump_id]
# 提取group actual traffic flow
group_actual_goto_excavator_traffic_flow = self.group.group_actual_goto_excavator_traffic_flow[
group_id]
# 提取group actual traffic flow
group_opt_goto_excavator_traffic_flow = self.group.group_opt_goto_excavator_traffic_flow[
group_id]
logger.info("驶往挖机分组车流")
logger.info(group_actual_goto_excavator_traffic_flow)
logger.info(group_opt_goto_excavator_traffic_flow)
transport_value = (group_actual_goto_excavator_traffic_flow[group_dump_index, :] + 0.001) \
/ (group_opt_goto_excavator_traffic_flow[group_dump_index, :] + 0.001)
# transport_value = (self.actual_goto_excavator_traffic_flow[trip[1], :] + 0.001) \
# / (self.opt_goto_excavator_traffic_flow[trip[1], :] + 0.001)
logger.info("transport_value")
logger.info(transport_value)
# target = np.argmin(transport_value
# + truck.excavator_exclude_modify[truck_index]
# + truck.excavator_material_bind_modify[truck_index])
excavator_exclude_modify = self.group.group_excavator_exclude_modify[truck_id]
excavator_material_bind_modify = self.group.group_excavator_material_bind_modify[truck_id]
logger.info(transport_value)
target = np.argmin(
transport_value
+ excavator_exclude_modify)
# + excavator_material_bind_modify)
target = self.excavator_uuid_to_index_dict[self.group.group_excavator_index_to_uuid_dict[target]]
except Exception as es:
logger.info("trip出错1")
logger.info(es)
try:
logger.info("车流比:")
logger.info(
(self.actual_goto_excavator_traffic_flow[trip[1], :] + 0.001)
/ (self.opt_goto_excavator_traffic_flow[trip[1], :] + 0.001))
except Exception as es:
logger.info("trip出错2")
logger.info(es)
logger.info(f"目的地:{excavator.excavator_index_to_uuid_dict[target]}")
logger.info("==========================================================")
return target
def schedule_construct(self):
global truck
global excavator
global dump
self.reset()
print("self.cur_truck_ava_time", self.cur_truck_ava_time)
# try:
# 读取所需信息
trucks = truck.get_truck_num()
truck_current_trip = truck.get_truck_current_trip()
truck_current_task = truck.get_truck_current_task()
payload = truck.get_payload()
unloading_time = dump.get_unloading_time()
loading_time = excavator.get_loading_time()
# 出入场时间
loading_task_time = excavator.get_loading_task_time()
unloading_task_time = dump.get_unloading_task_time()
walk_time_to_unload_area = walk_manage.get_walk_time_to_unload_area()
walk_time_to_load_area = walk_manage.get_walk_time_to_load_area()
# Seq初始化
Seq = [[truck_current_trip[i][1], -1] for i in range(trucks)]
# 根据矿卡最早可用时间顺序进行规划
print(self.cur_truck_ava_time)
print(truck.truck_priority)
temp = copy.deepcopy(self.cur_truck_ava_time) - truck.truck_priority
try:
# 没有启动的矿卡加上一个很大的值,降低其优先级
for i in range(trucks):
task = truck_current_task[truck.truck_index_to_uuid_dict[i]]
if task == -2:
temp[i] = temp[i] + M
except Exception as es:
logger.error("矿卡排序启动异常")
logger.error(es)
index = np.argsort(temp.reshape(1, -1))
index = index.flatten()
# 对于在线矿卡已经赋予新的派车计划,更新其最早可用时间,及相关设备时间参数
for truck_index in index:
if len(Seq[truck_index]) > 0:
# try:
# 获取矿卡id
truck_id = truck.truck_index_to_uuid_dict[truck_index]
# 判断矿卡是否禁用
if truck_id in truck.update_truck_disable_list():
continue
# 获取矿卡当前任务
task = truck_current_task[truck.truck_index_to_uuid_dict[truck_index]]
# 矿卡结束当前派车计划后的目的地
end_eq_index = truck_current_trip[truck_index][1]
# 调用调度函数,得到最优目的地序号
target_eq_index = self.truck_schedule(truck.truck_index_to_uuid_dict[truck_index])
# 写入Seq序列
Seq[truck_index][1] = target_eq_index
try:
group_id = self.group.dispatch_truck_group[truck_id]
except Exception as es:
logger.error("非动态调度矿卡")
logger.error(es)
# except Exception as es:
# logger.error(f'矿卡 {truck_uuid_to_name_dict[self.truck_index_to_uuid_dict[truck_index]]} 派车计划计算异常')
# logger.error(es)
try:
if task in empty_task_set:
target_area_index = dump.dump_index_to_unload_area_index_dict[target_eq_index]
end_area_index = excavator.excavator_index_to_load_area_index_dict[end_eq_index]
# 更新变量,预计产量更新
self.sim_dump_real_mass[target_eq_index] = \
(self.sim_dump_real_mass[target_eq_index] + payload[truck_index])
# 预计卸载设备可用时间更新
self.sim_dump_ava_time[target_eq_index] = (
max(
self.sim_dump_ava_time[target_eq_index],
self.sim_truck_ava_time[truck_index] + \
walk_time_to_unload_area[target_area_index][end_area_index],)
+ unloading_task_time[target_eq_index]
)
elif task in heavy_task_set:
target_area_index = (excavator.excavator_index_to_load_area_index_dict[target_eq_index])
end_area_index = dump.dump_index_to_unload_area_index_dict[end_eq_index]
# 更新变量,预计产量更新
self.sim_excavator_real_mass[target_eq_index] = (self.sim_excavator_real_mass[target_eq_index]
+ payload[truck_index])
# 预计装载点可用时间更新
self.sim_excavator_ava_time[target_eq_index] = (
max(self.sim_excavator_ava_time[target_eq_index], self.sim_truck_ava_time[truck_index]
+ walk_time_to_unload_area[end_area_index][target_area_index],) \
+ loading_task_time[target_eq_index])
else:
pass
except Exception as es:
logger.error( f"矿卡 {truck_uuid_to_name_dict[truck.truck_index_to_uuid_dict[truck_index]]} 调度状态更新异常")
logger.error(es)
for i in range(len(Seq)):
# try:
truck_id = truck.truck_index_to_uuid_dict[i]
group_id = self.group.dispatch_truck_group[truck_id]
record = {"truckId": truck.truck_index_to_uuid_dict[i]}
task = truck.get_truck_current_task()[truck.truck_index_to_uuid_dict[i]]
if task in empty_task_set:
item = (
session_mysql.query(Dispatch)
.filter_by(dump_id=dump.dump_index_to_uuid_dict[Seq[i][1]],
exactor_id=excavator.excavator_index_to_uuid_dict[Seq[i][0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0,).first())
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")
elif task in heavy_task_set:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=excavator.excavator_index_to_uuid_dict[Seq[i][1]],
dump_id=dump.dump_index_to_unload_area_index_dict[Seq[i][0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0,).first())
record["exactorId"] = excavator.excavator_index_to_uuid_dict[Seq[i][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")
elif task == -2:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=excavator.excavator_index_to_uuid_dict[Seq[i][1]], group_id=group_id,
isauto=1, isdeleted=0,).first())
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")
else:
pass
redis5.set(truck.truck_index_to_uuid_dict[i], str(json.dumps(record)))
# except Exception as es:
# logger.error("调度结果写入异常-redis写入异常")
# logger.error(f"调度结果:{Seq}")
# logger.error(es)
for i in range(trucks):
print("dispatch_setting:")
print(redis5.get(truck.truck_index_to_uuid_dict[i]))
# except Exception as es:
# logger.error("更新不及时")
# logger.error(es)
logger.info("#####################################周期更新结束#####################################")
return Seq
class Group(WalkManage):
def __init__(self):
self.dispatch_truck_group = {}
self.group_num = 1
self.group_set = set()
self.device_group = {}
self.group_walk_to_excavator_cost = {}
self.group_walk_to_dump_cost = {}
self.group_park_to_excavator = {}
self.group_opt_goto_dump_traffic_flow = {}
self.group_opt_goto_excavator_traffic_flow = {}
self.group_actual_goto_dump_traffic_flow = {}
self.group_actual_goto_excavator_traffic_flow = {}
self.group_excavator_uuid_to_index_dict = {}
self.group_dump_uuid_to_index_dict = {}
self.group_excavator_index_to_uuid_dict = {}
self.group_dump_index_to_uuid_dict = {}
self.group_excavator_exclude_modify = {}
self.group_excavator_material_bind_modify = {}
self.group_dump_material_bind_modify = {}
self.path = PathPlanner()
def update_dispatch_truck_group(self):
# 更新矿卡-调度分组隶属关系
self.dispatch_truck_group = {}
dynamic_truck_set = get_value("dynamic_truck_set")
for truck_id in dynamic_truck_set:
item = session_mysql.query(Dispatch).filter_by(truck_id=truck_id, isauto=1, isdeleted=0).first()
if item is None:
continue
self.dispatch_truck_group[truck_id] = item.group_id
def update_group_set(self):
# 更新调度组
self.group_set = set()
for item in session_mysql.query(Dispatch).all():
if item.group_id is not None:
self.group_set.add(item.group_id)
self.group_num = len(self.group_set)
def update_device_group(self):
# 更新设备分组group_id -> {set(dump_id), set(excavator_id)}
self.device_group = {}
for group_id in self.get_group_set():
self.device_group[group_id] = [set(), set()]
for item in session_mysql.query(Dispatch).filter_by(group_id=group_id, isauto=1, isdeleted=0).all():
self.device_group[group_id][0].add(item.dump_id)
self.device_group[group_id][1].add(item.exactor_id)
def update_group_truck_flow(self):
# 更新调度分组内车实时/最佳车流
global dispatcher
actual_goto_excavator_traffic_flow, actual_goto_dump_traffic_flow = \
dispatcher.actual_goto_excavator_traffic_flow, dispatcher.actual_goto_dump_traffic_flow
opt_goto_dump_traffic_flow, opt_goto_excavator_traffic_flow = traffic_flow_plan()
# try:
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
excavator_group = self.device_group[group_id][1]
local_opt_goto_dump_traffic_flow = np.zeros((len(excavator_group), len(dump_group)))
local_opt_goto_excavator_traffic_flow = np.zeros((len(dump_group), len(excavator_group)))
local_actual_goto_dump_traffic_flow = np.zeros((len(excavator_group), len(dump_group)))
local_actual_goto_excavator_traffic_flow = np.zeros((len(dump_group), len(excavator_group)))
for excavator_id in excavator_group:
for dump_id in dump_group:
dump_group_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
excavator_group_index = self.group_excavator_uuid_to_index_dict[group_id][excavator_id]
local_opt_goto_dump_traffic_flow[excavator_group_index][dump_group_index] = \
opt_goto_dump_traffic_flow[dump.excavator_uuid_to_index_dict[excavator_id]][dump.dump_uuid_to_index_dict[dump_id]]
local_opt_goto_excavator_traffic_flow[dump_group_index][excavator_group_index] = \
opt_goto_excavator_traffic_flow[dump.dump_uuid_to_index_dict[dump_id]][excavator.excavator_uuid_to_index_dict[excavator_id]]
local_actual_goto_dump_traffic_flow[excavator_group_index][dump_group_index] = \
actual_goto_dump_traffic_flow[excavator.excavator_uuid_to_index_dict[excavator_id]][dump.dump_uuid_to_index_dict[dump_id]]
local_actual_goto_excavator_traffic_flow[dump_group_index][excavator_group_index] = \
actual_goto_excavator_traffic_flow[dump.dump_uuid_to_index_dict[dump_id]][excavator.excavator_uuid_to_index_dict[excavator_id]]
self.group_opt_goto_dump_traffic_flow[group_id] = local_opt_goto_dump_traffic_flow
self.group_opt_goto_excavator_traffic_flow[group_id] = local_opt_goto_excavator_traffic_flow
self.group_actual_goto_dump_traffic_flow[group_id] = local_actual_goto_dump_traffic_flow
self.group_actual_goto_excavator_traffic_flow[group_id] = local_actual_goto_excavator_traffic_flow
# except Exception as es:
# logger.info(es)
logger.info("group_opt_traffic_flow")
logger.info(self.group_opt_goto_dump_traffic_flow)
logger.info(self.group_opt_goto_excavator_traffic_flow)
def update_group_walk_cost(self):
# 更新调度分组路网行驶成本
walk_to_excavator_cost, walk_to_dump_cost, park_to_excavator_cost = self.path.walk_cost()
# try:
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
excavator_group = self.device_group[group_id][1]
local_walk_to_excavator_cost = np.zeros((len(dump_group), len(excavator_group)))
local_walk_to_dump_cost = np.zeros((len(dump_group), len(excavator_group)))
local_park_to_excavator_cost = np.zeros((park_num, len(excavator_group)))
for excavator_id in excavator_group:
for dump_id in dump_group:
dump_group_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
excavator_group_index = self.group_excavator_uuid_to_index_dict[group_id][excavator_id]
local_walk_to_excavator_cost[dump_group_index][excavator_group_index] = \
walk_to_excavator_cost[dump.dump_uuid_to_index_dict[dump_id]][excavator.excavator_uuid_to_index_dict[excavator_id]]
local_walk_to_dump_cost[dump_group_index][excavator_group_index] = \
walk_to_dump_cost[dump.dump_uuid_to_index_dict[dump_id]][excavator.excavator_uuid_to_index_dict[excavator_id]]
for park_index in range(park_num):
for excavator_id in excavator_group:
excavator_group_index = self.group_excavator_uuid_to_index_dict[group_id][excavator_id]
local_park_to_excavator_cost[park_index][excavator_group_index] = \
park_to_excavator_cost[park_index][excavator.excavator_uuid_to_index_dict[excavator_id]]
self.group_walk_to_excavator_cost[group_id] = local_walk_to_excavator_cost
self.group_walk_to_dump_cost[group_id] = local_walk_to_dump_cost
self.group_park_to_excavator[group_id] = local_park_to_excavator_cost
# except Exception as es:
# logger.info(es)
def update_group_device_map(self):
# 更新调度分组内设备映射
self.group_excavator_uuid_to_index_dict = {}
self.group_dump_uuid_to_index_dict = {}
self.group_excavator_index_to_uuid_dict = {}
self.group_dump_index_to_uuid_dict = {}
for group_id in self.group_set:
excavator_num = 0
dump_num = 0
dump_group = self.device_group[group_id][0]
excavator_group = self.device_group[group_id][1]
self.group_excavator_uuid_to_index_dict[group_id] = {}
self.group_excavator_index_to_uuid_dict[group_id] = {}
self.group_dump_uuid_to_index_dict[group_id] = {}
self.group_dump_index_to_uuid_dict[group_id] = {}
for excavator_id in excavator_group:
if excavator_id not in self.group_excavator_uuid_to_index_dict:
self.group_excavator_index_to_uuid_dict[group_id][excavator_num] = excavator_id
self.group_excavator_uuid_to_index_dict[group_id][excavator_id] = excavator_num
excavator_num = excavator_num + 1
for dump_id in dump_group:
if dump_id not in self.group_dump_uuid_to_index_dict:
self.group_dump_index_to_uuid_dict[group_id][dump_num] = dump_id
self.group_dump_uuid_to_index_dict[group_id][dump_id] = dump_num
dump_num = dump_num + 1
logger.info("group_map")
logger.info(self.group_dump_uuid_to_index_dict)
logger.info(self.group_excavator_uuid_to_index_dict)
def update_modify(self):
self.group_excavator_exclude_modify = {}
self.group_excavator_material_bind_modify = {}
self.group_dump_material_bind_modify = {}
for truck_id in dynamic_truck_set:
group_id = self.dispatch_truck_group[truck_id]
group_dump_num = len(self.device_group[group_id][0])
group_excavator_num = len(self.device_group[group_id][1])
excavator_exclude_modify = np.zeros(group_excavator_num)
excavator_material_bind_modify = np.zeros(group_excavator_num)
dump_material_bind_modify = np.zeros(group_dump_num)
truck_index = truck.truck_uuid_to_index_dict[truck_id]
for group_excavator_index in range(group_excavator_num):
excavator_index = excavator.excavator_uuid_to_index_dict[self.group_excavator_index_to_uuid_dict[group_id][group_excavator_index]]
excavator_exclude_modify[group_excavator_index] = truck.excavator_exclude_modify[truck_index][excavator_index]
for group_excavator_index in range(group_excavator_num):
excavator_index = excavator.excavator_uuid_to_index_dict[
self.group_excavator_index_to_uuid_dict[group_id][group_excavator_index]]
excavator_material_bind_modify[group_excavator_index] = truck.excavator_material_bind_modify[truck_index][excavator_index]
for group_dump_index in range(group_dump_num):
dump_index = dump.dump_uuid_to_index_dict[self.group_dump_index_to_uuid_dict[group_id][group_dump_index]]
dump_material_bind_modify[group_dump_index] = truck.dump_material_bind_modify[truck_index][dump_index]
self.group_excavator_exclude_modify[truck_id] = excavator_exclude_modify
self.group_excavator_material_bind_modify[truck_id] = excavator_material_bind_modify
self.group_dump_material_bind_modify[truck_id] = dump_material_bind_modify
def period_update(self):
self.reset()
self.update_dispatch_truck_group()
self.update_group_set()
self.update_device_group()
self.update_group_device_map()
self.update_group_walk_cost()
self.update_group_truck_flow()
self.update_modify()
def get_diaptch_truck_group(self):
return self.dispatch_truck_group
def get_group_num(self):
return self.group_num
def get_group_set(self):
return self.group_set
def reset(self):
self.dispatch_truck_group = {}
self.group_num = 1
self.group_set = set()
self.device_group = {}
self.group_walk_to_excavator_cost = {}
self.group_walk_to_dump_cost = {}
self.group_park_to_excavator = {}
self.group_opt_goto_dump_traffic_flow = {}
self.group_opt_goto_excavator_traffic_flow = {}
self.group_actual_goto_dump_traffic_flow = {}
self.group_actual_goto_excavator_traffic_flow = {}
self.group_excavator_uuid_to_index_dict = {}
self.group_dump_uuid_to_index_dict = {}
self.group_excavator_index_to_uuid_dict = {}
self.group_dump_index_to_uuid_dict = {}
self.group_excavator_exclude_modify = {}
self.group_excavator_material_bind_modify = {}
self.group_dump_material_bind_modify = {}
def para_process(dispatcher):
logger.info("papa_process!")
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
# 周期更新
dispatcher.para_period_update()
def state_process(dispatcher):
print("state_process!")
logger.info("state_process!")
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
# 周期更新
dispatcher.state_period_update()
# 参数重置
dispatcher.sim_para_reset()
# try:
# 调度计算
dispatcher.schedule_construct()
# except Exception as es:
# logger.error("更新不及时")
# logger.error(es)
# 下面三个函数保证程序定期执行,不用管他
def process(dispatcher):
# try:
# 更新周期参数
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
para_process(dispatcher)
state_process(dispatcher)
# except Exception as es:
# logger.error(es)
scheduler = sched.scheduler(time.time, time.sleep)
dispatcher = Dispatcher()
def perform(inc, dispatcher):
scheduler.enter(inc, 0, perform, (inc, dispatcher))
process(dispatcher)
def main(inc, dispatcher):
scheduler.enter(0, 0, perform, (inc, dispatcher))
scheduler.run()
if __name__ == "__main__":
logger.info(" ")
logger.info("调度系统启动")
# dispatcher = Dispatcher()
main(10, dispatcher)
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/23 11:25
# @Author : Opfer
# @Site :
# @File : settings.py
# @Software: PyCharm
# 数据库设备, redis设置, 日志设置
from tables import *
from urllib.parse import quote
import logging.handlers
import numpy as np
import os
from redis import StrictRedis, ConnectionPool
import redis
from datetime import datetime, timedelta
import copy
import json
import sched
import time
# 创建日志
########################################################################################################################
# 日志存储地址
log_path = "/usr/local/fleet-log/dispatch"
# 创建日志目录
# if not os.path.exists(log_path):
# os.mkdir(log_path)
# logging初始化工作
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
# 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)
filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10)
# 设置后缀名称,跟strftime的格式一样
filehandler.suffix = "%Y-%m-%d_%H-%M.log"
formatter = logging.Formatter("%(asctime)s - %(name)s: %(levelname)s %(filename)s %(message)s")
filehandler.setFormatter(formatter)
logger.addHandler(filehandler)
# 连接reids
########################################################################################################################
# redis 5 存储设备状态
pool5 = ConnectionPool(host="192.168.28.111", db=5, port=6379, password="Huituo@123")
redis5 = StrictRedis(connection_pool=pool5)
# redis 2 存储派车计划
pool2 = ConnectionPool(host="192.168.28.111", db=2, port=6379, password="Huituo@123")
redis2 = StrictRedis(connection_pool=pool2)
# 数据库连接设置
########################################################################################################################
# 创建对象的基类:
Base = declarative_base()
try:
engine_mysql = create_engine(
"mysql+mysqlconnector://root:%s@192.168.28.111:3306/waytous"
% quote("Huituo@123")
)
engine_postgre = create_engine(
"postgresql://postgres:%s@192.168.28.111:5432/shenbao_2021520"
% quote("Huituo@123")
)
# 创建DBsession_mysql类型:
DBsession_mysql = sessionmaker(bind=engine_mysql)
DBsession_mysql = scoped_session(DBsession_mysql)
DBsession_postgre = sessionmaker(bind=engine_postgre)
DBsession_postgre = scoped_session(DBsession_postgre)
# 创建session_mysql对象:
session_mysql = DBsession_mysql()
session_mysql.expire_on_commit = False
session_postgre = DBsession_postgre()
session_postgre.expire_on_commit = False
except Exception as es:
logger.error("数据库连接失败")
logger.error(es)
def str_to_byte(item):
return bytes(item, encoding='utf8')
def byte_to_str(item):
return str(item, encoding='utf-8')
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/23 11:23
# @Author : Opfer
# @Site :
# @File : static_data_process.py
# @Software: PyCharm
# 静态数据处理(函数名即为注释)
from settings import *
def build_work_area_uuid_index_map():
# load_area_id <-> load_area_index
# unload_area_id <-> unload_area_index
load_area_uuid_to_index_dict = {}
unload_area_uuid_to_index_dict = {}
load_area_index_to_uuid_dict = {}
unload_area_index_to_uuid_dict = {}
unload_area_num = 0
load_area_num = 0
try:
for item in session_postgre.query(WalkTime).all():
load_area = str(item.load_area_id)
unload_area = str(item.unload_area_id)
if load_area not in load_area_uuid_to_index_dict:
load_area_uuid_to_index_dict[load_area] = load_area_num
load_area_index_to_uuid_dict[load_area_num] = load_area
load_area_num = load_area_num + 1
if unload_area not in unload_area_uuid_to_index_dict:
unload_area_uuid_to_index_dict[unload_area] = unload_area_num
unload_area_index_to_uuid_dict[unload_area_num] = unload_area
unload_area_num = unload_area_num + 1
if unload_area_num < 1 or load_area_num < 1:
raise Exception("无路网信息")
except Exception as es:
raise Exception("路网读取")
logger.error(es)
return (
load_area_uuid_to_index_dict,
unload_area_uuid_to_index_dict,
load_area_index_to_uuid_dict,
unload_area_index_to_uuid_dict,
)
def build_park_uuid_index_map():
# park_id <-> park_index
park_uuid_to_index_dict = {}
park_index_to_uuid_dict = {}
park_num = 0
try:
for item in session_postgre.query(WalkTimePark).all():
park = str(item.park_area_id)
if park not in park_uuid_to_index_dict:
park_uuid_to_index_dict[park] = park_num
park_index_to_uuid_dict[park_num] = park
park_num = park_num + 1
if park_num < 1:
raise Exception("无备停区路网信息")
except Exception as es:
logger.info("备停区路网读取")
logger.error(es)
return park_uuid_to_index_dict, park_index_to_uuid_dict
def build_truck_uuid_name_map():
# truck_id <-> truck_name
truck_uuid_to_name_dict = {}
truck_name_to_uuid_dict = {}
try:
for item in session_mysql.query(Equipment).filter_by(device_type=1).all():
truck_id = item.id
truck_name = item.equipment_id
truck_name_to_uuid_dict[truck_name] = truck_id
truck_uuid_to_name_dict[truck_id] = truck_name
if len(truck_uuid_to_name_dict) < 1 or len(truck_name_to_uuid_dict) < 1:
raise Exception("无矿卡设备可用-矿卡设备映射异常")
except Exception as es:
logger.warning(es)
return truck_uuid_to_name_dict, truck_name_to_uuid_dict
def update_deveices_map(unload_area_uuid_to_index_dict, load_area_uuid_to_index_dict):
excavator_uuid_to_index_dict = {} # 用于将Excavator表中的area_id映射到index
dump_uuid_to_index_dict = {} # 用于将Dump表中的area_id映射到index
excavator_index_to_uuid_dict = {} # 用于将index映射到Excavator表中的area_id
dump_index_to_uuid_dict = {} # 用于将index映射到Dump表中的area_id
dump_uuid_to_unload_area_uuid_dict = {}
excavator_uuid_to_load_area_uuid_dict = {}
excavator_index_to_load_area_index_dict = {}
dump_index_to_unload_area_index_dict = {}
try:
excavator_num = 0
dump_num = 0
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
):
# excavator_id <-> excavator_index
# dump_id <-> dump_index
# excavator_id <-> load_area_id
# dump_id <-> unload_area_id
# excavator_index <-> load_area_index
# dump_index <-> unload_area_index
excavator_id = item.exactor_id
load_area_id = item.load_area_id
unload_area_id = item.unload_area_id
dump_id = item.dump_id
if dump_id not in dump_uuid_to_unload_area_uuid_dict:
dump_uuid_to_index_dict[dump_id] = dump_num
dump_index_to_uuid_dict[dump_num] = dump_id
dump_uuid_to_unload_area_uuid_dict[dump_id] = unload_area_id
dump_index_to_unload_area_index_dict[
dump_uuid_to_index_dict[dump_id]
] = unload_area_uuid_to_index_dict[unload_area_id]
dump_num = dump_num + 1
if excavator_id not in excavator_uuid_to_index_dict:
excavator_uuid_to_index_dict[excavator_id] = excavator_num
excavator_index_to_uuid_dict[excavator_num] = excavator_id
excavator_uuid_to_load_area_uuid_dict[excavator_id] = load_area_id
excavator_index_to_load_area_index_dict[
excavator_uuid_to_index_dict[excavator_id]
] = load_area_uuid_to_index_dict[load_area_id]
excavator_num = excavator_num + 1
if excavator_num < 1 or dump_num < 1:
raise Exception("无动态派车计划可用-动态派车挖机/卸载设备映射失败")
except Exception as es:
logger.warning(es)
return {
"excavator_uuid_to_index_dict": excavator_uuid_to_index_dict,
"dump_uuid_to_index_dict": dump_uuid_to_index_dict,
"excavator_index_to_uuid_dict": excavator_index_to_uuid_dict,
"dump_index_to_uuid_dict": dump_index_to_uuid_dict,
"dump_uuid_to_unload_area_uuid_dict": dump_uuid_to_unload_area_uuid_dict,
"excavator_uuid_to_load_area_uuid_dict": excavator_uuid_to_load_area_uuid_dict,
"excavator_index_to_load_area_index_dict": excavator_index_to_load_area_index_dict,
"dump_index_to_unload_area_index_dict": dump_index_to_unload_area_index_dict,
}
def update_truck_uuid_index_map(dynamic_truck_set):
truck_uuid_to_index_dict = {}
truck_index_to_uuid_dict = {}
# truck_id <-> truck_index
truck_num = 0
for truck_id in dynamic_truck_set:
truck_uuid_to_index_dict[truck_id] = truck_num
truck_index_to_uuid_dict[truck_num] = truck_id
truck_num = truck_num + 1
return {
"truck_uuid_to_index_dict": truck_uuid_to_index_dict,
"truck_index_to_uuid_dict": truck_index_to_uuid_dict,
}
def update_total_truck():
# 矿卡集合
truck_list = []
try:
query = np.array(
session_mysql.query(Equipment)
.filter_by(device_type=1, isdeleted=0)
.all()
)
# for item in query:
# json_value = json.loads(redis2.get(item.equipment_id))
# is_online = json_value.get('isOnline')
# if is_online:
# truck_list.append(item.id)
for item in query:
truck_list.append(item.id)
if len(truck_list) < 1:
raise Exception("无矿卡设备可用-矿卡集合读取异常")
except Exception as es:
logger.info("矿卡读取")
logger.error(es)
return truck_list
def update_dynamic_truck():
dynamic_truck_list = []
try:
query = np.array(
session_mysql.query(Dispatch).filter_by(isauto=1, isdeleted=0).all()
)
for item in query:
if item.truck_id is not None:
dynamic_truck_list.append(item.truck_id)
except Exception as es:
logger.error(es)
logger.error("动态调度矿卡读取异常")
return set(dynamic_truck_list)
def update_fixdisp_truck():
# 固定派车矿卡集合
fixed_truck_list = []
try:
query = np.array(
session_mysql.query(Dispatch).filter_by(isauto=0, isdeleted=0).all()
)
for item in query:
fixed_truck_list.append(item.truck_id)
rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first().disabled
if not rule5:
query = np.array(
session_mysql.query(Equipment)
.filter_by(device_type=1, isdeleted=0, disabled=1)
.all()
)
for item in query:
fixed_truck_list.append(item.id)
if len(fixed_truck_list) < 1:
raise Exception("无固定派车计划可用-固定派车矿卡集合读取异常")
except Exception as es:
logger.info("派车计划读取")
logger.error(es)
return set(fixed_truck_list)
def update_autodisp_excavator():
# 用于动态派车的挖机集合
dynamic_excavator_list = []
try:
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
):
dynamic_excavator_list.append(item.exactor_id)
if len(dynamic_excavator_list) < 1:
raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
except Exception as es:
logger.warning(es)
return set(dynamic_excavator_list)
def update_autodisp_dump():
# 用于动态调度的卸载点集合
dynamic_dump_list = []
try:
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
):
dynamic_dump_list.append(item.dump_id)
if len(dynamic_dump_list) < 1:
raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
except Exception as es:
logger.warning(es)
return set(dynamic_dump_list)
def update_load_area():
load_area_list = []
for walk_time in session_postgre.query(WalkTime).all():
load_area_list.append(walk_time.load_area_id)
return load_area_list
def update_unload_area():
unload_area_list = []
for walk_time in session_postgre.query(WalkTime).all():
unload_area_list.append(walk_time.unload_area_id)
return unload_area_list
def update_park_area():
park_area_list = []
for walk_time_park in session_postgre.query(WalkTimePark).all():
park_area_list.append(walk_time_park.park_area_id)
return park_area_list
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/6/22 12:46
# @Author : Opfer
# @Site :
# @File : tables.py
# @Software: PyCharm
# 存储数据库表结构
from sqlalchemy import Column, create_engine
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
# 创建对象的基类:
Base = declarative_base()
engine_mysql = create_engine(
"mysql+mysqlconnector://root:%s@192.168.28.111:3306/waytous"
% quote("Huituo@123")
)
engine_postgre = create_engine(
"postgresql://postgres:%s@192.168.28.111:5432/shenbao_2021520"
% quote("Huituo@123")
)
# 创建DBsession_mysql类型:
DBsession_mysql = sessionmaker(bind=engine_mysql)
DBsession_mysql = scoped_session(DBsession_mysql)
DBsession_postgre = sessionmaker(bind=engine_postgre)
DBsession_postgre = scoped_session(DBsession_postgre)
# 创建session_mysql对象:
session_mysql = DBsession_mysql()
session_mysql.expire_on_commit = False
session_postgre = DBsession_postgre()
session_postgre.expire_on_commit = False
# # 创建对象的基类:
# Base = declarative_base()
#
# # 初始化数据库连接:
# engine_mysql = create_engine('mysql+mysqlconnector://root:Huituo@123@192.168.28.111:3306/waytous')
#
# engine_postgre = create_engine('postgresql://postgres:Huituo@123@192.168.28.111:5432/shenbao_2021520')
#
# # 创建DBsession_mysql类型:
# DBsession_mysql = sessionmaker(bind=engine_mysql)
#
# DBsession_mysql = scoped_session(DBsession_mysql)
#
# DBsession_postgre = sessionmaker(bind=engine_postgre)
#
# DBsession_postgre = scoped_session(DBsession_postgre)
#
# # 创建session_mysql对象:
# session_mysql = DBsession_mysql()
#
# session_postgre = DBsession_postgre()
# 定义对象:
# class Excavator(Base):
# __tablename__ = 'excavator_property'
#
# excavator_id = Column(VARCHAR(36), primary_key=True)
# load_area_id = Column(VARCHAR(36))
# average_load_time = Column(Integer)
# target_mass = Column(Float(2))
# actual_mass = Column(Float(2))
# # virtual_mass = Column(Float(2))
# # last_load_time = Column(DateTime)
#
# def __init__(self, excavator_id, load_area_id, average_load_time, target_mass, actual_mass):
# self.excavator_id = excavator_id
# self.load_area_id = load_area_id
# self.average_load_time = average_load_time
# self.target_mass = target_mass
# self.actual_mass = actual_mass
# # self.virtual_mass = virtual_mass
# # self.last_load_time = last_load_time
# class Dump(Base):
# __tablename__ = 'dump_property'
#
# dump_id = Column(VARCHAR(36), primary_key=True)
# unload_area_id = Column(VARCHAR(36))
# average_unload_time = Column(Integer)
# target_mass = Column(Float(2))
# actual_mass = Column(Float(2))
# # virtual_mass = Column(Float(2))
# # last_unload_time = Column(DateTime)
#
# def __init__(self, dump_id, unload_area_id, average_unload_time, target_mass, actual_mass):
# self.dump_id = dump_id
# self.unload_area_id = unload_area_id
# self.average_unload_time = average_unload_time
# self.target_mass = target_mass
# self.actual_mass = actual_mass
# # self.virtual_mass = virtual_mass
# # self.last_unload_time = last_unload_time
# class Walk_time(Base):
# __tablename__ = 'walk_time'
#
# Rid = Column(VARCHAR(36), primary_key=True)
# load_area_id = Column(VARCHAR(36))
# unload_area_id = Column(VARCHAR(36))
# walktime_load = Column(Float(2))
# walktime_unload = Column(Float(2))
#
# def __init__(self, Rid, load_area_id, unload_area_id, walktime_load, walktime_unload):
# self.Rid = Rid
# self.load_area_id = load_area_id
# self.unload_area_id = unload_area_id
# self.walktime_load = walktime_load
# self.walktime_unload = walktime_unload
class WalkTime(Base):
__tablename__ = 'work_area_distance'
load_area_id = Column(VARCHAR(36), primary_key=True)
unload_area_id = Column(VARCHAR(36), primary_key=True)
load_area_name = Column(VARCHAR(30))
unload_area_name = Column(VARCHAR(30))
to_unload_distance = Column(Float(10))
to_load_distance = Column(Float(10))
to_unload_lanes = Column(VARCHAR(100))
to_load_lanes = Column(VARCHAR(100))
def __init__(self, load_area_id, unload_area_id, load_area_name, unload_area_name, to_load_distance,
to_unload_distance, to_unload_lanes, to_load_lanes):
self.load_area_id = load_area_id
self.unload_area_id = unload_area_id
self.load_area_name = load_area_name
self.unload_area_name = unload_area_name
self.to_load_distance = to_load_distance
self.to_unload_distance = to_unload_distance
self.to_unload_lanes = to_unload_lanes
self.to_load_lanes = to_load_lanes
# Rid = Column(VARCHAR(36), primary_key=True)
# load_area_id = Column(VARCHAR(36))
# unload_area_id = Column(VARCHAR(36))
# walktime_load = Column(Float(2))
# walktime_unload = Column(Float(2))
#
# def __init__(self, Rid, load_area_id, unload_area_id, walktime_load, walktime_unload):
# self.Rid = Rid
# self.load_area_id = load_area_id
# self.unload_area_id = unload_area_id
# self.walktime_load = walktime_load
# self.walktime_unload = walktime_unload
# class Truck(Base):
# __tablename__ = 'truck_status'
#
# truck_id = Column(VARCHAR(36), primary_key=True)
# # dispatch_id = Column(VARCHAR(36))
# current_task = Column(Integer)
# # reach_time = Column(DateTime)
# last_load_time = Column(DateTime)
# last_unload_time = Column(DateTime)
# payload = Column(Float(2))
#
# def __init__(self, truck_id, current_task, last_load_time, last_unload_time, payload):
# self.truck_id = truck_id
# # self.dispatch_id = dispatch_id
# self.current_task = current_task
# # self.reach_time = reach_time
# self.last_load_time = last_load_time
# self.last_unload_time = last_unload_time
# self.payload = payload
#
# def check_existing(self):
# existing = session_mysql.query(Truck).filter_by(truck_id=self.truck_id).first()
# if not existing:
# truck = Truck(self.truck_id, self.dispatch_id, self.status, self.reach_time, self.last_load_time, self.last_unload_time, self.payload)
# else:
# truck = existing
# session_mysql.close()
# return truck
# class Dispatch(Base):
# __tablename__ = 'dispatch_pair'
#
# dispatch_id = Column(VARCHAR(36), primary_key=True)
# excavator_id = Column(VARCHAR(36))
# dump_id = Column(VARCHAR(36))
#
# def __init__(self, dispatch_id, excavator_id, dump_id):
# self.dispatch_id = dispatch_id
# self.excavator_id = excavator_id
# self.dump_id = dump_id
class EquipmentPair(Base):
__tablename__ = 'sys_equipment_pair'
id = Column(VARCHAR(36), primary_key=True)
truck_id = Column(VARCHAR(36))
exactor_id = Column(VARCHAR(36))
dump_id = Column(VARCHAR(36))
load_area_id = Column(VARCHAR(36))
unload_area_id = Column(VARCHAR(36))
dispatch_id = Column(VARCHAR(36))
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):
self.id = id
self.truck_id = truck_id
self.exactor_id = exactor_id
self.dump_id = dump_id
self.load_area_id = load_area_id
self.unload_area_id = unload_area_id
self.dispatch_id = dispatch_id
self.isdeleted = isdeleted
self.createtime = createtime
# class Lane(Base):
# # 表的名字
# __tablename__ = 'Geo_Node'
# Id = Column(VARCHAR(36), primary_key=True)
# LaneIds = Column(VARCHAR(100))
#
# def __init__(self, Id, LaneIds):
# self.Id = Id
# self.LaneIds = LaneIds
class Lane(Base):
# 表的名字
__tablename__ = 'Geo_Lane'
Id = Column(VARCHAR(36), primary_key=True)
Length = Column(Float)
MaxSpeed = Column(Float)
def __init__(self, Id, Length, MaxSpeed):
self.Id = Id
self.Length = Length
self.MaxSpeed = MaxSpeed
class Dispatch(Base):
# 表的名字:
__tablename__ = 'sys_dispatch_setting'
id = Column(VARCHAR(36), primary_key=True)
load_area_id = Column(VARCHAR(36))
exactor_id = Column(VARCHAR(36))
unload_area_id = Column(VARCHAR(36))
dump_id = Column(VARCHAR(36))
isauto = Column(BOOLEAN)
truck_id = Column(VARCHAR(36))
group_id = Column(VARCHAR(36))
remark = Column(VARCHAR(100))
proportion_id = Column(VARCHAR(36))
isdeleted = Column(BOOLEAN)
creator = Column(VARCHAR(36))
createtime = Column(DateTime)
updator = Column(VARCHAR(36))
updatetime = Column(DateTime)
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,
isdeleted, creator, createtime, updator, updatetime, deletor, deletetime):
self.id = id
self.load_area_id = load_area_id
self.excavator_id = exactor_id
self.unload_area_id = unload_area_id
self.dump_id = dump_id
self.isauto = isauto
self.truck_id = truck_id
self.group_id = group_id
self.remark = remark
self.proportion_id = proportion_id
self.isdeleted = isdeleted
self.creator = creator
self.createtime = createtime
self.updator = updator
self.updatetime = updatetime
self.deletor = deletor
self.deletetime = deletetime
class WalkTimePark(Base):
__tablename__ = 'park_load_distance'
park_area_id = Column(VARCHAR(36), primary_key=True)
load_area_id = Column(VARCHAR(36), primary_key=True)
park_area_name = Column(VARCHAR(36))
load_area_name = Column(VARCHAR(36))
park_load_distance = Column(Float(10))
park_load_lanes = Column(VARCHAR(100))
def __init__(self, park_area_id, load_area_id, park_area_name, load_area_name, park_load_distance, park_load_lanes):
self.park_area_id = park_area_id
self.load_area_id = load_area_id
self.park_area_name = park_area_name
self.load_area_name = load_area_name
self.park_load_distance = park_load_distance
self.park_load_lanes = park_load_lanes
class Equipment(Base):
__tablename__ = 'sys_equipment'
id = Column(VARCHAR(36), primary_key=True)
equipment_id = Column(VARCHAR(64))
device_name = Column(VARCHAR(64))
device_type = Column(VARCHAR(36))
equipment_spec = Column(VARCHAR(36))
equipment_state = Column(Integer)
isdeleted = Column(Integer)
disabled = Column(Integer)
bind_list = Column(VARCHAR(1000))
only_allowed = Column(Integer)
priority = Column(Integer)
def __init__(self, id, equipment_id, device_name, device_type, equipment_spec, equipment_state, isdeleted, \
disabled, bind_list, only_allowed, priority):
self.id = id
self.equipment_id = equipment_id
self.device_name = device_name
self.device_type = device_type
self.equipment_spec = equipment_spec
self.equipment_state = equipment_state
self.isdeleted = isdeleted
self.disabled = disabled
self.bind_list = bind_list
self.only_allowed = only_allowed
self.priority = priority
class EquipmentSpec(Base):
__tablename__ = 'sys_equipment_spec'
id = Column(VARCHAR(36), primary_key=True)
capacity = Column(Integer)
mining_abililty = Column(Float)
length = Column(Float)
width = Column(Float)
max_speed = Column(Float)
def __init__(self, id, capacity, mining_abililty, length, width, max_speed):
self.id = id
self.capacity = capacity
self.mining_abililty = mining_abililty
self.length = length
self.width = width
self.max_speed = max_speed
class LoadInfo(Base):
__tablename__ = 'sys_loadinfo'
time = Column(DateTime, primary_key=True)
dump_id = Column(VARCHAR(36), primary_key=True)
load_weight = Column(Float(8))
def __init__(self, time, dump_id, load_weight):
self.time = time
self.dump_id = dump_id
self.load_weght = load_weight
class JobRecord(Base):
__tablename__ = 'statistic_job_record'
id = Column(VARCHAR(36), primary_key=True)
equipment_id = Column(VARCHAR(50))
start_time = Column(DateTime)
end_time = Column(DateTime)
work_type = Column(Integer)
def __init__(self, id, equipment_id, start_time, end_time, work_type):
self.id = id
self.equipment_id = equipment_id
self.start_time = start_time
self.end_time = end_time
self.work_type = work_type
class WorkRecord(Base):
__tablename__ = 'statistic_work_record'
equipment_id = Column(VARCHAR(50), primary_key=True)
work_day = Column(DateTime, primary_key=True)
load_entrance_time = Column(Float)
load_entrance_count = Column(Integer)
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):
self.equipment_id = equipment_id
self.work_day = work_day
self.load_entrance_time = load_entrance_time
self.load_entrance_count = load_entrance_count
self.load_exit_time = load_exit_time
self.load_exit_count = load_exit_count
class DumpArea(Base):
__tablename__ = 'Geo_DumpArea'
Id = Column(VARCHAR(50), primary_key=True)
BindList = Column(VARCHAR(1000))
UnloadAbililty = Column(Float)
Disabled = Column(Integer)
Material = Column(VARCHAR(36))
Priority = Column(Integer)
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Material, Priority):
self.Id = Id
self.BindList = BindList
self.UnloadAbililty = UnloadAbililty
self.Disabled = Disabled
self.Material = Material
self.Priority = Priority
class DiggingWorkArea(Base):
__tablename__ = 'Geo_DiggingWorkArea'
Id = Column(VARCHAR(50), primary_key=True)
Material = Column(VARCHAR(36))
def __init__(self, Id, Material):
self.Id = Id
self.Material = Material
class DispatchRule(Base):
__tablename__ = 'sys_dispatch_rule'
id = Column(Integer, primary_key=True)
rule_weight = Column(Float)
disabled = Column(BOOLEAN)
def __init__(self, id, rule_weight, disabled):
self.id = id
self.rule_weight = rule_weight
self.disabled = disabled
class Material(Base):
__tablename__ = 'resource_metarials'
id = Column(VARCHAR(40), primary_key=True)
name = Column(VARCHAR(40))
def __init__(self, id, name):
self.id = id
self.name = name
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/31 15:17
# @Author : Opfer
# @Site :
# @File : __init__.py
# @Software: PyCharm
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/3 10:41
# @Author : Opfer
# @Site :
# @File : traffic_flow_info.py
# @Software: PyCharm
# import
from path_plan.path_plannner import *
from para_config import *
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from equipment.truck import TruckInfo
truck = TruckInfo()
excavator = ExcavatorInfo()
dump = DumpInfo()
# 车流规划类
class Traffic_para(WalkManage):
def __init__(self, num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump):
self.num_of_dump = num_of_dump
self.num_of_excavator = num_of_excavator
self.num_of_load_area = num_of_load_area
self.num_of_unload_area = num_of_unload_area
self.walk_time_to_load_area = np.zeros((num_of_unload_area, num_of_load_area)) # 空载运输路线距离
self.walk_time_to_unload_area = np.zeros((num_of_load_area, num_of_unload_area)) # 重载运输路线距离
# self.avg_goto_excavator_weight = np.zeros((num_of_load_area, num_of_unload_area))
self.avg_goto_excavator_weight = np.full((num_of_unload_area, num_of_load_area), 1)
# self.avg_goto_dump_weight = np.zeros((num_of_load_area, num_of_unload_area))
self.avg_goto_dump_weight = np.full((num_of_load_area, num_of_unload_area), 1)
self.walk_time_to_excavator = np.zeros((num_of_dump, num_of_excavator)) # 逻辑空载运输路线距离
self.walk_time_to_dump = np.zeros((num_of_excavator, num_of_dump)) # 逻辑重载运输路线距离
# self.payload = 200 # 有效载重(不同型号矿卡载重不同,这里暂时认为车队是同质的)
self.payload = np.mean(truck.get_payload())
try:
self.empty_speed = sum(truck.empty_speed.values()) / truck.get_truck_num() # 空载矿卡平均时速
self.heavy_speed = sum(truck.heavy_speed.values()) / truck.get_truck_num() # 重载矿卡平均时速
except Exception as es:
self.empty_speed = 25
self.heavy_speed = 22
logger.warning("矿卡速度设置为默认值")
logger.warning(es)
self.min_throughout = 1000 # 最小产量约束
self.truck_total_num = 0
self.excavator_strength = np.zeros(num_of_excavator) # 用于保存电铲的工作强度,单位是t/h
self.dump_strength = np.zeros(num_of_dump) # 卸载点的工作强度,单位是t/h
self.path_planner = PathPlanner()
self.path_planner.walk_cost()
self.excavator_priority_coefficient = np.ones(num_of_excavator) # 每个电铲的优先级系数
self.excavator_material_priority = np.ones(num_of_excavator) # 每个电铲的物料优先级系数
self.grade_loading_array = np.zeros(num_of_excavator) # 用于保存电铲挖掘矿石的品位
self.dump_priority_coefficient = np.ones(num_of_dump) # 每个卸载点的优先级系数
self.dump_material_priority = np.ones(num_of_excavator) # 每个卸载点的物料优先级系数
# 卸载道路的运输系数:卸载道路上,每运输1吨货物需要一辆卡车运行时长,等于(该卸载道路上车辆平均运行时长/卡车平均实际装载量)
self.goto_unload_area_factor = np.full((num_of_load_area, num_of_unload_area), 10, dtype=float)
# 装载道路的运输系数,装载道路上,每提供1吨的装载能力需要一辆卡车运行时长,等于(该装载道路上车辆平均运行时长/卡车平均装载能力)
self.goto_load_area_factor = np.full((num_of_unload_area, num_of_load_area), 10, dtype=float)
self.goto_dump_factor = np.full((num_of_excavator, num_of_dump), 10, dtype=float) # 逻辑卸载道路的运输系数
self.goto_excavator_factor = np.full((num_of_dump, num_of_excavator), 10, dtype=float) # 逻辑装载道路的运输系数
self.priority_coefficient_goto_dump = np.ones((num_of_excavator, num_of_dump)) # 卸载道路的优先级系数
self.priority_coefficient_goto_excavator = np.ones((num_of_dump, num_of_excavator)) # 装载道路的优先级系数
self.grade_lower_dump_array = np.zeros(num_of_dump) # 卸载点矿石品位下限
self.grade_upper_dump_array = np.zeros(num_of_dump) # 卸载点矿石品位上限
# 装/卸区的物料类型
self.load_area_material_type = {}
self.unload_area_material_type = {}
# 目的地矿卡数量
self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
# 设置卸载点信息
def extract_dump_info(self):
dynamic_dump_num = get_value("dynamic_dump_num")
try:
rule3 = session_mysql.query(DispatchRule).filter_by(id=3).first()
if not rule3.disabled:
for dump_index in range(dynamic_dump_num):
unload_area_id = unload_area_index_to_uuid_dict[self.dump_index_to_unload_area_index_dict[dump_index]]
unload_ability = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().UnloadAbililty
self.dump_strength[dump_index] = unload_ability # 卸载设备最大卸载能力,单位吨/小时
if unload_ability < 200:
raise Exception("卸载点卸载能力异常")
else:
self.dump_strength = np.full(self.num_of_dump, 5000)
for dump_index in range(dynamic_dump_num):
# self.dump_strength[dump_index] = 10000 # 卸载设备最大卸载能力,单位吨/小时
self.grade_upper_dump_array[dump_index] = 100 # 卸点品位上限
self.grade_lower_dump_array[dump_index] = 100 # 卸点品位下限
self.dump_priority_coefficient[dump_index] = 1 # 卸载设备优先级
except Exception as es:
logger.error(es)
logger.error("卸载点信息设置异常")
# 设置挖信息
def extract_excavator_info(self):
try:
rule4 = session_mysql.query(DispatchRule).filter_by(id=4).first()
if not rule4.disabled:
for excavator_index in range(len(self.excavator_index_to_uuid_dict)):
load_ability = session_mysql.query(EquipmentSpec.mining_abililty).\
join(Equipment, Equipment.equipment_spec == EquipmentSpec.id).\
filter(Equipment.id == self.excavator_index_to_uuid_dict[excavator_index]).first()
self.excavator_strength[excavator_index] = load_ability.mining_abililty
if load_ability.mining_abililty < 200:
raise Exception("挖机装载能力异常")
else:
self.excavator_strength = np.full(self.num_of_excavator, 5000)
for excavator_index in range(len(self.excavator_index_to_uuid_dict)):
# self.excavator_strength[excavator_index] = 1000 # 挖机最大装载能力,单位吨/小时
self.grade_loading_array[excavator_index] = 100 # 挖机装载物料品位
self.excavator_priority_coefficient[excavator_index] = 1 # 挖机优先级
except Exception as es:
logger.error(es)
logger.error("挖机信息设置异常")
def extract_walk_time_info(self):
try:
# 车流规划部分矩阵格式与其余两个模块不同
cost_to_load_area = self.path_planner.cost_to_load_area
cost_to_unload_area = self.path_planner.cost_to_unload_area
distance_to_load_area = self.path_planner.distance_to_load_area
distance_to_unload_area = self.path_planner.distance_to_unload_area
# 路网信息读取
for unload_area_index in range(unload_area_num):
for load_area_index in range(load_area_num):
self.goto_load_area_factor[unload_area_index][load_area_index] = \
(cost_to_load_area[unload_area_index][load_area_index] / (empty_speed * 1000)) / self.payload
self.goto_unload_area_factor[load_area_index][unload_area_index] = \
(cost_to_unload_area[unload_area_index][load_area_index] / (heavy_speed * 1000)) / self.payload
logger.info("goto_unload_area_factor")
logger.info(self.goto_unload_area_factor)
logger.info("cost_to_unload_area")
logger.info(cost_to_unload_area)
except Exception as es:
logger.error(es)
logger.error("车流规划信息计算异常")
# 初始化车流规划类
def Traffic_para_init(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump):
# try:
tra_para = Traffic_para(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump)
tra_para.period_map_para_load()
tra_para.period_walk_para_load()
tra_para.extract_excavator_info()
tra_para.extract_dump_info()
tra_para.extract_walk_time_info()
# 矿卡参数更新
truck.para_period_update()
truck.state_period_update()
truck.update_truck_payload()
tra_para.payload = np.mean(truck.get_payload())
# 动态派车矿卡集合
tra_para.truck_total_num = get_value("dynamic_truck_num")
# 目的地矿卡数量
tra_para.dump_hold_truck_num = truck.get_dump_hold_truck_num()
tra_para.excavator_hold_truck_num = truck.get_excavator_hold_truck_num()
# 计算逻辑道路因子
for i in range(num_of_excavator):
for j in range(num_of_dump):
# 查找挖机绑定的装载区, 卸载设备绑定的卸载区
load_area_index = tra_para.excavator_index_to_load_area_index_dict[i]
unload_area_index = tra_para.dump_index_to_unload_area_index_dict[j]
# 逻辑道路因子赋值, 来自实际道路因子
tra_para.goto_excavator_factor[j][i] = \
tra_para.goto_load_area_factor[unload_area_index][load_area_index]
tra_para.goto_dump_factor[i][j] = \
tra_para.goto_unload_area_factor[load_area_index][unload_area_index]
# print("cout", tra_para.priority_coefficient_goto_dump, tra_para.priority_coefficient_goto_excavator)
# except Exception as es:
# logger.error(es)
# logger.error("车流规划类比初始化异常")
return tra_para
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/19 15:05
# @Author : Opfer
# @Site :
# @File : traffic_flow_planner.py
# @Software: PyCharm
# import
import pulp
from traffic_flow.traffic_flow_info import *
from para_config import *
# 从数据库中读取挖机和卸载设备相关参数,并将线性规划所用参数保存在TrafficProgPara类中
# 解决线性规划问题,生成每条道路的流量
def transportation_problem_slove(coefficient_goto_dump, coefficient_goto_excavator, w_ij, s_ij, b_excavator,
b_dump, grade_loading_array,
max_unload_weigh_alg_flag, truck_total_num,
walk_time_to_excavator, walk_time_to_dump, min_throughout,
grade_lower_array=None, grade_upper_array=None,
dump_hold_truck_num = None, excavator_hold_truck_num = None):
row = len(coefficient_goto_dump) # 代表挖机的个数,第i行代表第i台挖机
col = len(coefficient_goto_dump[0]) # 代表卸载设备的个数,第j行代表第j个卸载设备
# prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMaximize)
# 卸载道路的流量,单位是吨/小时,i代表起点为第i个挖机,j代表终点为第j个卸载设备
var_x = [[pulp.LpVariable('x{0}{1}'.format(i, j), lowBound=0) for j in range(col)] for i in range(row)]
# 装载道路的流量,单位是吨/小时,i代表起点为第i个卸载设备,j代表终点为第j个挖机
var_y = [[pulp.LpVariable('y{0}{1}'.format(i, j), lowBound=0) for j in range(row)] for i in range(col)]
flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
# 定义目标函数
if max_unload_weigh_alg_flag == True:
prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMaximize)
# 得到目标函数,目标函数是使得系统的运输量最大
prob += (pulp.lpDot(flatten(var_x), coefficient_goto_dump.flatten()))
else:
prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMinimize)
goto_excavator_cost = var_y * walk_time_to_excavator
goto_dump_cost = var_x * walk_time_to_dump
prob += (pulp.lpSum(flatten(goto_excavator_cost)) + 1.5 * pulp.lpSum(flatten(goto_dump_cost)))
# 定义约束条件
# 最小产量约束,仅在最小化成本模式下成立
if max_unload_weigh_alg_flag == False:
for i in range(col):
prob += pulp.lpSum(var_y[i]) >= min_throughout[i]
logger.info("road_factor")
logger.info(w_ij)
logger.info(s_ij)
# 矿卡总数约束,在每条道路上的车辆总数要小于矿卡总个数
# 通过矩阵按元素相乘得到每条卸载道路上的车辆个数
unload_truck_total_num_array = w_ij * var_x
# 通过矩阵按元素相乘得到每条装载道路上的车辆个数
load_truck_totla_num_array = s_ij * var_y
# 装载的矿卡数和卸载的矿卡数需要小于矿卡总数
prob += (pulp.lpSum(unload_truck_total_num_array) +
pulp.lpSum(load_truck_totla_num_array) <= truck_total_num)
# 约束一:最大工作强度约束
# 约束每个挖机的工作强度
for i in range(row):
prob += (pulp.lpSum(var_x[i]) <= b_excavator[i])
# 约束每个卸载设备的工作强度
for j in range(col):
prob += (pulp.lpSum(var_y[j]) <= b_dump[j])
'''
# 车流基尔霍夫定理约束
# 进入挖机和从挖机出去的车辆个数需要相同
for i in range(row):
prob += (pulp.lpSum(unload_truck_total_num_array[i]) == pulp.lpSum(load_truck_totla_num_array[:,i]))
# 从装载点离开和进来的车辆个数需要相同
for j in range(col):
prob += (pulp.lpSum(load_truck_totla_num_array[j]) == pulp.lpSum(unload_truck_total_num_array[:,j]))
'''
# 约束二:基尔霍夫车流i约束
# # 从装载点去往卸载设备的流量之和要小于从卸载设备到装载点的流量之和
# for i in range(row):
# prob += (pulp.lpSum((np.array(var_x))[i]) <= pulp.lpSum((np.array(var_y))[:, i]))
#
# # 从卸载设备出发去往装载点的流量之和要小于从装载点到本卸载设备的流量之和
# for j in range(col):
# prob += (pulp.lpSum((np.array(var_y))[j]) <= pulp.lpSum((np.array(var_x))[:, j]))
# 约束三:矿石品位约束
# 矿石品位约束卸载
# 去往卸载设备的流量使用矩阵乘法乘以每个挖机处矿石的品位,得到每个卸载设备的矿石品位总和
grade_array = np.dot(grade_loading_array, var_x)
for j in range(col):
sum_traffic_unload = pulp.lpSum((np.array(var_x))[:, j])
prob += (grade_array[j] >= sum_traffic_unload * grade_lower_array[j])
prob += (grade_array[j] <= sum_traffic_unload * grade_upper_array[j])
# row 挖机
# col 卸点
# var_x 卸载车流
# var_y 装载车流
# 约束四:车流可行性约束
# 当前车流可行性约束
for i in range(row):
print(excavator_hold_truck_num[i])
prob += (pulp.lpSum((np.array(var_x))[i]) <= excavator_hold_truck_num[i] * 220 + 0.001)
for j in range(col):
print(dump_hold_truck_num[j])
prob += (pulp.lpSum((np.array(var_y))[j]) <= dump_hold_truck_num[j] * 220 + 0.001)
# 约束五:非负约束
for i in range(row):
for j in range(col):
prob += var_x[i][j] >= 0
prob += var_y[j][i] >= 0
prob.solve()
try:
if -1 == prob.status:
raise Exception("Model infeasible or unbounded")
except Exception as es:
logger.warning(es)
return {'objective': pulp.value(prob.objective),
'var_x': [[pulp.value(var_x[i][j]) for j in range(col)] for i in range(row)],
'var_y': [[pulp.value(var_y[i][j]) for j in range(row)] for i in range(col)]}
def traffic_flow_plan():
excavator_list = update_autodisp_excavator()
dump_list = update_autodisp_dump()
excavator_set = set(excavator_list)
dump_set = set(dump_list)
load_area_list = update_load_area()
unload_area_list = update_unload_area()
load_area_set = set(load_area_list)
unload_area_set = set(unload_area_list)
excavator_num = len(excavator_set)
dump_num = len(dump_set)
unload_area_num = len(unload_area_set)
load_area_num = len(load_area_set)
print("装载区数量:", load_area_num, "卸载区数量:", unload_area_num, "挖机数量:", excavator_num, "卸载设备数量:", dump_num)
# try:
# if (load_area_num * unload_area_num * excavator_num * dump_num == 0):
# raise Exception("无派车计划可用")
# 初始化参量
traffic_programme_para = Traffic_para_init(load_area_num, unload_area_num, excavator_num, dump_num)
# traffic_programme_para = traffic_programme_para_init(load_area_num, unload_area_num, excavator_num, dump_num)
# 系统是否以最大化产量为目标
max_unload_weigh_alg_flag = True
if max_unload_weigh_alg_flag:
logger.info(f'最大产量调度模式')
else:
logger.info(f'最小成本调度模式')
coefficient_goto_dump = traffic_programme_para.priority_coefficient_goto_dump
coefficient_goto_excavator = traffic_programme_para.priority_coefficient_goto_excavator
w_ij = traffic_programme_para.goto_dump_factor
s_ij = traffic_programme_para.goto_excavator_factor
b_excavator = traffic_programme_para.excavator_strength
b_dump = traffic_programme_para.dump_strength
grade_loading_array = traffic_programme_para.grade_loading_array
grade_lower_dump_array = traffic_programme_para.grade_lower_dump_array
grade_upper_dump_array = traffic_programme_para.grade_upper_dump_array
min_throughout = traffic_programme_para.min_throughout
walk_time_to_excavator = traffic_programme_para.walk_time_to_excavator
walk_time_to_dump = traffic_programme_para.walk_time_to_dump
truck_total_num = traffic_programme_para.truck_total_num
dump_hold_truck_num = traffic_programme_para.dump_hold_truck_num
excavator_hold_truck_num = traffic_programme_para.excavator_hold_truck_num
print(w_ij, s_ij, b_excavator, b_dump)
res = transportation_problem_slove(coefficient_goto_dump, coefficient_goto_excavator, w_ij, s_ij, b_excavator, b_dump,
grade_loading_array, max_unload_weigh_alg_flag, truck_total_num,
walk_time_to_excavator, walk_time_to_dump, min_throughout,
grade_upper_dump_array, grade_lower_dump_array,
dump_hold_truck_num, excavator_hold_truck_num)
if max_unload_weigh_alg_flag:
print('最大化产量', res["objective"])
logger.info(f'最大产量:{res["objective"]}')
else:
print('最小成本', res["objective"])
logger.info(f'最小成本:{res["objective"]}')
print('各变量的取值为:')
logger.info('各变量取值:')
print(dynamic_dump_set)
print(dynamic_excavator_set)
print(np.array(res['var_x']).round(3))
logger.info(f'重运车流:{res["var_x"]} 单位: 吨/时')
print(dynamic_excavator_set)
print(dynamic_dump_set)
print(np.array(res['var_y']).round(3))
logger.info(f'空运车流:{res["var_y"]} 单位: 吨/时')
# 通过矩阵按元素相乘得到每条卸载道路上的车辆个数
print("卸载道路上的车辆个数")
unload_traffic = res['var_x']
print((traffic_programme_para.goto_dump_factor * unload_traffic).round(3))
# 通过矩阵按元素相乘得到每条装载道路上的车辆个数
print("装载道路上的车辆个数")
load_traffic = res['var_y']
print((traffic_programme_para.goto_excavator_factor * load_traffic).round(3))
return res["var_x"], res["var_y"]
# except Exception as es:
# logger.error("车流规划参数异常")
# logger.error(es)
return None
# end = time.time()
# print("used {:.5}s".format(end-start))
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