Commit 1e0b7111 authored by 张晓彤's avatar 张晓彤

交叉口二次调度

parent 6f85727b
......@@ -6,11 +6,10 @@
# @File : alg.py
# @Software: PyCharm
from para_config import *
from equipment import ExcavatorInfo, DumpInfo, TruckInfo
from data.para_config import *
from equipment import DumpInfo
from data.dispatchInfo import DispatchInfo
# from core.group import Group
from core.schedule import PreSchedule
class AlgorithmBase:
......@@ -148,7 +147,7 @@ class ExpectedTime(AlgorithmBase):
:return: travel_time_value
"""
try:
# try:
# truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
......@@ -171,10 +170,10 @@ class ExpectedTime(AlgorithmBase):
group_dynamic_excavator_num = len(self.group.excavator)
group_dynamic_unload_area_num = len(self.group.unload_area)
except Exception as es:
self.logger.error("车辆调度信息读取异常")
self.logger.error(es)
#
# except Exception as es:
# self.logger.error("车辆调度信息读取异常")
# self.logger.error(es)
if task == -2:
################################################ 矿卡启动 ###############################################
......
from flask import Flask, request
from flask.json import jsonify
from para_config import *
from data.para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.dispatcher import PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
......
......@@ -8,23 +8,23 @@
},
"mysql": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"port": "3306",
"user": "root",
"password": "Huituo@123",
"database": "waytous"
"database": "ht_zhunneng"
},
"postgresql": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"port": "5432",
"user": "postgres",
"password": "Huituo@123",
"database": "shenbao_2021520"
"database": "gis_zhunneng"
},
"redis": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"password": "Huituo@123"
}
}
\ No newline at end of file
......@@ -9,16 +9,15 @@
from data.dispatchInfo import DispatchInfo
from core.group import Group
from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch, DispatchMatch, DispatchEquipment, DispatchGroup, DispatchSetting
from para_config import DeviceMap, get_value, global_period_para_update
from settings import get_logger, redis5
from tables import DispatchSetting
from data.para_config import get_value
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
from core.schedule import PreSchedule
import json
import uuid
from tables import session_mysql, session_postgre
import numpy as np
from datetime import datetime, timedelta
from graph.graph_load import graph_construct
class Dispatcher:
......@@ -34,6 +33,7 @@ class Dispatcher:
self.request_mode = request_mode
self.submission = DispatchSubmission(dump, excavator, truck)
self.logger = get_logger("zxt.dispatcher")
self.topo = graph_construct()
def period_update(self):
"""
......@@ -47,6 +47,7 @@ class Dispatcher:
self.excavator.excavator_para_period_update()
self.truck.truck_para_period_update(self.dump, self.excavator)
self.truck.state_period_update()
self.topo = graph_construct()
def group_generate(self):
"""
......@@ -57,7 +58,7 @@ class Dispatcher:
groups = DispatchInfo.get_all_group()
for group_id in groups:
if group_id not in self.group_list:
group = Group(group_id, self.truck, self.pre_sch, self.excavator, self.dump)
group = Group(group_id, self.truck, self.pre_sch, self.excavator, self.dump, self.topo)
self.group_list[group_id] = group
def group_info_update(self):
......@@ -77,13 +78,13 @@ class Dispatcher:
aa = self.group_list
for group in self.group_list.values():
try:
# try:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
except Exception as es:
self.logger.error(es)
self.logger.error(f'分组{group.group_id} 调度异常')
# except Exception as es:
# self.logger.error(es)
# self.logger.error(f'分组{group.group_id} 调度异常')
self.logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
self.logger.info("组内挖机")
......@@ -120,6 +121,7 @@ class DispatchSubmission:
record = {"truckId": truck_id}
task = self.truck.get_truck_current_task()[truck_id]
state = self.truck.get_truck_current_state()[truck_id]
except Exception as es:
self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
......@@ -157,7 +159,7 @@ class DispatchSubmission:
redis5.set(truck_id, str(json.dumps(record)))
else:
if task in [0, 1, 2]: # 卡车空载或在装载区出场前, 可变更卸载目的地
if task in [1, 2] or (task == 3 and state == 2): # 卡车空载或在装载区出场前, 可变更卸载目的地
# 查询车辆相关派车计划
try:
......@@ -174,18 +176,6 @@ class DispatchSubmission:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["dumpId"] = DispatchInfo.unload_area_dump_dict[dispatch_seq[1]]
# record["unloadAreaId"] = dispatch_seq[1]
# except Exception as es:
# # item = (session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first())
# record["dumpId"] = item.dump_id
# record["unloadAreaId"] = item.unload_area_id
# self.logger.error(es)
# 其余调度信息写入
try:
# record["dispatchId"] = item.id
......@@ -207,7 +197,7 @@ class DispatchSubmission:
finally:
redis5.set(truck_id, str(json.dumps(record)))
elif task in [3, 4, 5]: # 卡车重载或在卸载区出场前, 可变更装载目的地
elif task in [4, 5] or (task == 0 and state == 2): # 卡车重载或在卸载区出场前, 可变更装载目的地
# 查询车辆相关派车计划
try:
......@@ -221,18 +211,6 @@ class DispatchSubmission:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["exactorId"] = dispatch_seq[0]
# record["loadAreaId"] = DispatchInfo.excavator_load_dict[dispatch_seq[0]]
# except Exception as es:
# # item = (session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first())
# record["exactorId"] = item.exactor_id
# record["loadAreaId"] = item.load_area_id
# self.logger.error(es)
# 调度信息写入
try:
# record["dispatchId"] = item.id
......@@ -269,21 +247,6 @@ class DispatchSubmission:
isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["exactorId"] = dispatch_seq[0]
# record["loadAreaId"] = DispatchInfo.excavator_load_dict[dispatch_seq[0]]
# except Exception as es:
# item = (
# session_mysql.query(DispatchSetting)
# .filter_by(truck_id=truck_id,
# isdeleted=0).first())
# record["exactorId"] = item.exactor_id
# record["loadAreaId"] = item.load_area_id
# self.logger.error(es)
# 调度信息写入
try:
......@@ -332,6 +295,7 @@ class DispatchSubmission:
self.logger.info(dispatch_plan_dict)
for truck_id, dispatch_plan in dispatch_plan_dict.items():
try:
self.logger.info(f'======================================= 调度车辆 =======================================')
self.logger.info(f'矿车编号 {get_value("truck_uuid_to_name_dict")[truck_id]} {truck_id}')
self.logger.info(f'调度模式 {group.group_mode}')
......@@ -340,4 +304,6 @@ class DispatchSubmission:
self.logger.info(f'配对卸点 {dispatch_plan[1]}')
self.truck_dispatch_to_redis(truck_id, dispatch_plan)
self.logger.info("======================================== 完成写入 =======================================")
except Exception as es:
self.logger.error("group_dispatch_to_redis_error")
self.logger.error(es)
......@@ -11,7 +11,8 @@ from bidict import bidict
from alg.algorithm import AlgorithmBase,DistributionRatio
import numpy as np
# from settings import get_logger
from para_config import get_value
from data.para_config import get_value
class CurrentTruck:
""" class for the information of current dispatching truck.
......@@ -50,7 +51,7 @@ class Group:
"""
class for group instance.
"""
def __init__(self, group_id, truck, pre_sch, excavator_info, dump_info):
def __init__(self, group_id, truck, pre_sch, excavator_info, dump_info, topo):
""" Generate a group obj.
:param group_id: (uuid) group_id
"""
......@@ -63,6 +64,9 @@ class Group:
self.excavator_info = excavator_info
self.dump_info = dump_info
# topo graph
self.topo = topo
# group devices
self.excavator = {} # excavator_id -> unload_area_id
self.unload_area = {} # unload_area_id -> load_area_id
......@@ -267,14 +271,21 @@ class Group:
s = solver(self, self.truck, self.pre_sch) # algorithm init
for i in list(self.truck_set):
self.logger.info("车辆调度程序")
# try:
truck_trip = self.truck.get_truck_current_trip()[self.truck.truck_uuid_to_index_dict[i]]
truck_task = self.truck.get_truck_current_task()[i]
truck_info = CurrentTruck(i, self.group_id, truck_trip, truck_task)
self.truck_info_list[i] = truck_info
# except Exception as es:
# self.logger.error("车辆调度信息读取异常")
# self.logger.error(es)
# 全智能模式
if self.group_mode == 1:
if truck_task in [-2, 3, 4, 5]:
try:
# 车辆停止或者车辆位于装载区内, 调度车辆前往卸载区
if truck_task in [-2, 1, 2]:
# try:
if i in self.truck.truck_excavator_bind:
next_excavator_id = self.truck.truck_excavator_bind[i]
else:
......@@ -291,11 +302,11 @@ class Group:
next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
except Exception as es:
self.logger.error("重载车辆全智能模式-计算异常")
self.logger.error(es)
if truck_task in [0, 1, 2]:
# except Exception as es:
# self.logger.error("重载车辆全智能模式-计算异常")
# self.logger.error(es)
# 车辆位于卸载区内, 调度车辆前往装载区
elif truck_task in [4, 5]:
try:
next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[-1]]
next_unload_area_value = s.solve(truck_info)
......@@ -329,6 +340,109 @@ class Group:
self.logger.error("空载车辆全智能模式-计算异常")
self.logger.error(es)
truck_dispatch[i] = [None, None]
elif truck_task == 0:
truck_locate = self.truck.get_truck_locate_dict()[i]
# 车辆当前位于交叉路口前,且排队等待
self.logger.info(f'车辆位置 {truck_locate}')
self.logger.info(f'车辆状态 {self.truck.truck_current_state[i]}')
if truck_locate in self.topo.cross_bf_lanes and self.truck.truck_current_state[i] == 2:
self.logger.info("触发二次调度")
# 当前绑定卸载区
if truck_trip[0] == -1:
next_unload_area_id = session_mysql.query(EquipmentPair).filter_by(truck_id=i, isdeleted=0).first().unload_area_id
else:
dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[0]]
next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
# 当前绑定装载区
if truck_trip[-1] == -1:
item = session_mysql.query(EquipmentPair).filter_by(truck_id=i, isdeleted=0).first()
current_excavator_id = item.exactor_id
current_load_area_id = item.load_area_id
else:
current_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[-1]]
current_load_area_id = DispatchInfo.excavator_load_dict[current_excavator_id]
load_area_dict = self.topo.get_load_target_node_real(truck_locate, current_load_area_id)
self.logger.info(load_area_dict)
# if truck_locate in self.topo.get_cross_nodes() and self.truck.truck_current_state[i] == 0:
# print(self.topo.get_load_target_node_real("6b417083-83b0-4eec-a8bd-2f85f96cb029", "1010cbfe-b134-3ef1-91bb-d746241c975a"))
min_trip_time = 10000000
best_excavator_id = current_excavator_id
for load_area, value in load_area_dict.items():
# 车辆不需要掉头
if value[-1] == 1 and load_area in DispatchInfo.load_excavator_dict:
excavator_id = DispatchInfo.load_excavator_dict[load_area]
traveling_time = value[0] / self.truck.empty_speed[i]
now = float(
(datetime.now() - self.pre_sch.start_time) / timedelta(hours=0, minutes=1, seconds=0))
reach_time = now + traveling_time
print(self.pre_sch.excavator_avl_time_dict)
trip_time = max(reach_time, self.pre_sch.get_excavator_avl_time()[excavator_id]) - now
if min_trip_time > trip_time:
best_excavator_id = excavator_id
next_excavator_id = best_excavator_id
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
self.logger.info("二次调度结果")
self.logger.info(truck_dispatch[i])
elif truck_task == 3:
truck_locate = self.truck.get_truck_locate_dict()[i]
# 车辆当前位于交叉路口前,且排队等待
if truck_locate in self.topo.cross_bf_lanes and self.truck.truck_current_state[i] == 0:
# 当前绑定装载区
if truck_trip[0] == -1:
next_excavator_id = session_mysql.query(EquipmentPair).filter_by(truck_id=i, isdeleted=0).first().exactor_id
else:
next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[0]]
# 当前绑定卸载区
if truck_trip[-1] == -1:
item = session_mysql.query(EquipmentPair).filter_by(truck_id=i, isdeleted=0).first()
current_dump_id = item.dump_id
current_unload_area_id = item.unload_area_id
else:
current_dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
current_unload_area_id = DispatchInfo.dump_unload_area_dict[current_dump_id]
unload_area_dict = self.topo.get_unload_target_node_real(truck_locate, current_unload_area_id)
min_trip_time = 10000000
best_dump_id = current_dump_id
for unload_area, value in unload_area_dict.items():
# 车辆不需要掉头
if value[-1] == 1 and unload_area in DispatchInfo.unload_area_dump_dict:
dump_id = DispatchInfo.unload_area_dump_dict[unload_area]
traveling_time = value[0] / self.truck.heavy_speed[i]
now = float(
(datetime.now() - self.pre_sch.start_time) / timedelta(hours=0, minutes=1,
seconds=0))
reach_time = now + traveling_time
trip_time = max(reach_time,
self.pre_sch.get_dump_avl_time()[dump_id]) - now
if min_trip_time > trip_time:
best_dump_id = dump_id
next_unload_area_id = DispatchInfo.dump_unload_area_dict[best_dump_id]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
self.logger.info("二次调度结果")
self.logger.info(truck_dispatch[i])
# 空车智能模式
elif self.group_mode == 2:
if truck_task in [-2, 3, 4, 5]:
......
......@@ -6,14 +6,10 @@
# @File : schedule.py
# @Software: PyCharm
from data.dispatchInfo import DispatchInfo
# from core.group import Group
# from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
import json
from settings import get_logger
from data.para_config import get_value
import numpy as np
from datetime import datetime, timedelta
......@@ -81,6 +77,8 @@ class PreSchedule:
for i in range(trucks):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
if end_area_index == -1:
continue
# self.logger.info("update_truck_reach_time-truck_current_trip")
# self.logger.info(truck_current_trip)
if task in [0, 1]: # 卡车空载行驶或正在入场
......@@ -217,7 +215,7 @@ class PreSchedule:
unloading_task_time = self.dump.get_unloading_task_time()
try:
# try:
now = float(
(datetime.now() - self.start_time)
......@@ -248,9 +246,9 @@ class PreSchedule:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[i][1])] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
except Exception as es:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
# except Exception as es:
# self.logger.error("卸载设备可用时间计算异常")
# self.logger.error(es)
return self.dump_avl_time_dict
......
......@@ -6,7 +6,7 @@
# @File : para_config.py
# @Software: PyCharm
from static_data_process import *
from data.static_data_process import *
from settings import *
import numpy as np
......
......@@ -6,7 +6,7 @@
# @File : dump.py
# @Software: PyCharm
from para_config import *
from data.para_config import *
from settings import *
......
......@@ -6,7 +6,7 @@
# @File : excavator.py
# @Software: PyCharm
from para_config import *
from data.para_config import *
from settings import *
......
......@@ -6,9 +6,7 @@
# @File : truck.py
# @Software: PyCharm
from para_config import *
from equipment.dump import DumpInfo
from equipment.excavator import ExcavatorInfo
from data.para_config import *
from typing import List
......@@ -33,6 +31,8 @@ class TruckInfo(WalkManage):
self.relative_last_unload_time = {}
# 矿卡当前任务
self.truck_current_task = {}
# 矿卡当前状态
self.truck_current_state = {}
# 调度开始时间
self.start_time = datetime.now()
# 矿卡有效载重
......@@ -84,6 +84,8 @@ class TruckInfo(WalkManage):
# 对象域
self._dump = dump
self._excavator = excavator
# 车辆位置信息
self.truck_locate_dict = {}
def get_truck_current_trip(self):
return self.truck_current_trip
......@@ -91,6 +93,9 @@ class TruckInfo(WalkManage):
def get_truck_current_task(self):
return self.truck_current_task
def get_truck_current_state(self):
return self.truck_current_state
def get_truck_num(self):
return self.dynamic_truck_num
......@@ -124,6 +129,9 @@ class TruckInfo(WalkManage):
def get_excavator_hold_truck_num(self):
return self.excavator_hold_truck_num
def get_truck_locate_dict(self):
return self.truck_locate_dict
################################################ short term update ################################################
# 更新矿卡当前任务
......@@ -134,21 +142,24 @@ class TruckInfo(WalkManage):
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
for item in device_name_set:
try:
# 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:
bb = self.dynamic_truck_set
cc = truck_name_to_uuid_dict
if truck_name_to_uuid_dict[item] in self.dynamic_truck_set:
currentTask = int(key_value_dict[str_to_byte("currentTask")])
# currentTask = int(key_value_dict[str_to_byte("currentTask")])
currentTask = int(byte_to_str(key_value_dict[str_to_byte("currentTask")]))
self.truck_current_task[
truck_name_to_uuid_dict[item]
] = currentTask
except Exception as es:
self.logger.error("读取矿卡任务异常-reids读取异常")
self.logger.error(es)
currentState = int(float(byte_to_str(key_value_dict[str_to_byte("state")])))
self.truck_current_state[
truck_name_to_uuid_dict[item]
] = currentState
# except Exception as es:
# self.logger.error("读取矿卡任务异常-reids读取异常")
# self.logger.error(es)
self.logger.info("矿卡当前任务:")
self.logger.info(self.truck_current_task)
......@@ -277,13 +288,6 @@ class TruckInfo(WalkManage):
.filter_by(truck_id=truck_id, isdeleted=0)
.first()
)
# item = (
# session_mysql.query(DispatchSetting)
# .filter_by(truck_id=truck_id, isdeleted=0)
# .first()
# )
point = empty_task_set
point2 = heavy_task_set
if task in (empty_task_set + heavy_task_set) and item is None:
raise Exception(f"矿卡 {truck_id} 配对关系异常")
except Exception as es:
......@@ -295,14 +299,8 @@ class TruckInfo(WalkManage):
try:
load_area_uuid_to_index_dict = get_value("load_area_uuid_to_index_dict")
unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
aa = task
tt = truck_id
# 若矿卡状态为空运
if task in [0, 1, 2]: # 矿卡空载或仍未出装载区
# last_unload_time = self.relative_last_unload_time[
# self.truck_index_to_uuid_dict[i]
# ]
bb = self.relative_last_unload_time
last_unload_time = self.relative_last_unload_time[
truck_id
]
......@@ -473,6 +471,36 @@ class TruckInfo(WalkManage):
print("self.excavator_hold_truck_num")
print(self.excavator_hold_truck_num)
def update_trucks_locate(self):
"""
get trucks locates.
:return: truck_locate_dict
"""
try:
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
self.truck_locate_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
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 == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
and (str_to_byte('laneId') in key_set):
truck_locate = key_value_dict[str_to_byte('laneId')]
if eval(truck_locate) is not '':
self.truck_locate_dict[truck_name_to_uuid_dict[item]] = eval(truck_locate)
except Exception as es:
logger.error("车辆所在路段读取异常")
logger.error(es)
return {}
################################################ long term update ################################################
# 更新矿卡实际容量
......@@ -852,8 +880,6 @@ class TruckInfo(WalkManage):
# 更新矿卡物料类型
self.update_truck_material()
def state_period_update(self):
# 更新卡车当前任务
......@@ -870,3 +896,6 @@ class TruckInfo(WalkManage):
# 矿卡速度更新
self.update_truck_speed()
# 矿卡位置更新
self.update_trucks_locate()
......@@ -6,18 +6,13 @@
# @File : gothrough_digging.py
# @Software: PyCharm
from flask import Flask, request
from flask import request
from flask.json import jsonify
from para_config import *
from data.para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
from app import app
import uuid
......@@ -30,6 +25,8 @@ def redispatch_request():
# 车辆id
request_truck_id = data_json.get("truck_id")
request_truck_id = '309705a0-5ddf-4559-b6c4-ee17a57677ad'
# 调度开始时间
rtd_start_time = datetime.now()
......@@ -104,7 +101,7 @@ def redispatch_request():
logger.info("unload_distance")
logger.info(DispatchInfo.unload_distance)
# try:
try:
# # 实例化设备对象
dump = DumpInfo()
......@@ -116,26 +113,41 @@ def redispatch_request():
excavator.excavator_para_period_update()
truck.truck_para_period_update(dump, excavator)
truck.state_period_update()
#
# # 实例化调度预测器
# pre_sch = PreSchedule(truck, excavator, dump)
#
# # 实例化输出器
# submission = DispatchSubmission(dump, excavator, truck)
#
# # 实例化调度分组
# group = Group(group_id, truck, None, excavator, dump)
#
# # 更新调度分组信息
# group.update_group_device()
except Exception as es:
logger.error("对象实例化异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=504)
try:
# 读取挖机集合
excavators_id = DispatchInfo.get_excavator(group_id)
# 读取车辆位置信息
truck_locates_dict = get_trucks_locate()
logger.info("truck_locates_dict")
logger.info(truck_locates_dict)
# 装载区区分
closer_area_id, further_area_id = area_analysis(excavators_id)
# closer_area_id, further_area_id = area_analysis(excavators_id)
closer_area_id = 'f1d5f017-5134-65a0-f657-89eed06eacc1'
further_area_id = 'ef89f721-5134-3ef1-91e2-95b4e5004675'
closer_excavator_id, further_excavator_id = DispatchInfo.load_excavator_dict[closer_area_id], \
DispatchInfo.load_excavator_dict[further_area_id]
logger.info("近端装载区")
logger.info(closer_area_id)
logger.info("远端装载区")
logger.info(further_area_id)
# 读取挖机状态
closer_excavator_state, further_excavator_state = get_excavator_state(closer_excavator_id), \
get_excavator_state(further_excavator_id)
# 装载区入场点
closer_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(Id=closer_area_id).first().EntranceNodeId
......@@ -143,16 +155,58 @@ def redispatch_request():
further_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(
Id=further_area_id).first().EntranceNodeId
logger.info("近端装载区入场点")
logger.info(closer_entrance_node_id)
logger.info("远端装载区入场点")
logger.info(further_entrance_node_id)
except Exception as es:
logger.error("读取装载区及车辆信息异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=505)
# 目的地
target_excavator = None
# try:
try:
request_truck_lane_id = truck_locates_dict[request_truck_id]
logger.info("request_truck_lane_id:")
logger.info(request_truck_lane_id)
logger.info(truck_locates_dict)
except Exception as es:
logger.error("车辆位置信息不可用")
logger.error(es)
return jsonify(msg="车辆位置信息不可用, 请联系管理员", code=505)
# 车辆位置判断
if not truck_pass_first_area(request_truck_id, truck_locates_dict[request_truck_id], closer_entrance_node_id, further_entrance_node_id):
truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
if not truck_pass_first_area(request_truck_id, request_truck_lane_id, closer_entrance_node_id, further_entrance_node_id):
logger.info("车辆已经过近端装载区")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
else:
# logger.info(" ")
# logger.info(truck.excavator_hold_truck_list)
# logger.info(list(excavators_id)[0])
# logger.info(list(excavators_id)[1])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
# 近端挖机空闲
if closer_excavator_state == 1:
logger.info("近端挖机空闲, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[closer_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[closer_area_id])
# 远端挖机空闲
elif further_excavator_state == 1:
logger.info("远端挖机空闲, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
# 两挖机均不空闲
else:
logger.info(" ")
logger.info(truck.excavator_hold_truck_list)
logger.info(list(excavators_id)[0])
logger.info(list(excavators_id)[1])
logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
# 统计驶往两装载区的车辆
arrival_truck_set = truck.excavator_hold_truck_list[list(excavators_id)[0]]\
......@@ -161,68 +215,69 @@ def redispatch_request():
# 统计车辆抵达时间
arrival_truck_reach_time = [truck.cur_truck_reach_excavator[truck.truck_uuid_to_index_dict[truck_id]] for \
truck_id in arrival_truck_set]
logger.info(" ")
logger.info(arrival_truck_reach_time)
# arrival_truck_set = ['309705a0-5ddf-4559-b6c4-ee17a57677ad', '899705a0-5ddf-4559-b6c4-ee17a57677ad']
#
# arrival_truck_reach_time = [8.04, 6.05]
logger.info("arrival_truck_reach_time")
logger.info(arrival_truck_reach_time)
logger.info("arrival_truck_set")
logger.info(arrival_truck_set)
arrival_truck_list = list(zip(np.array(arrival_truck_set), np.array(arrival_truck_reach_time)))
arrival_truck_list = sorted(arrival_truck_list, key=lambda item: item[1])
logger.info("arrival_truck_list")
logger.info(arrival_truck_list)
logger.info("arrival_truck_list")
logger.info(arrival_truck_list)
lane_set = get_lanes_between_entrances(closer_entrance_node_id, further_entrance_node_id)
# 统计不同状态车辆数量
goto_closer_area_num = 0
goto_further_area_num = 0
for truck_id, reach_time in zip(*arrival_truck_list):
for truck_id, reach_time in arrival_truck_list:
truck_lane_id = truck_locates_dict[truck_id]
# # 车辆已经经过近端装载区
if truck_lane_id in lane_set:
goto_closer_area_num += 1
# # 车辆未经过近端装载区
else:
pass
goto_further_area_num += 1
goto_further_area_num -= 1
logger.info(" ")
logger.info(arrival_truck_list)
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
logger.info("goto_further_area_num-goto_closer_area_num")
logger.info(goto_further_area_num)
logger.info(goto_closer_area_num)
goto_closer_area_num = 1
# 在远处排队等待的车辆更少
if goto_closer_area_num > goto_further_area_num:
logger.info("远端挖机排队时间短, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
else:
logger.info("近端挖机排队时间短, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[closer_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[closer_area_id])
truck_dispatch_to_redis(request_truck_id, group_id, target_excavator)
# except Exception as es:
# logger.error("对象实例化异常")
# logger.error(" ")
# logger.error(es)
# session_mysql.rollback()
# session_postgre.rollback()
# return jsonify(msg="未知异常, 请联系管理员", code=504)
# try:
#
# # 调度分组派车计划计算
# try:
# truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度计算异常')
#
# try:
#
# logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
# submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度写入异常')
#
# except Exception as es:
# logger.error("最外层异常捕获")
# logger.error(es)
# return jsonify(msg="未知异常, 请联系管理员", code=505)
#
# session_mysql.close()
# session_postgre.close()
logger.info("#####################################请求调度更新结束#####################################")
# 调度结束时间
......@@ -240,6 +295,8 @@ def area_analysis(load_area_uuid):
:return: closer_area_uuid, further_area_uuid
"""
try:
excavator_uuid_to_load_area_uuid_dict = get_value("excavator_uuid_to_load_area_uuid_dict")
load_area_uuid = list(load_area_uuid)
......@@ -258,6 +315,11 @@ def area_analysis(load_area_uuid):
else:
return load_area_uuid[0], load_area_uuid[1]
except Exception as es:
logger.error("装载区距离分析异常")
logger.error(es)
return load_area_uuid[0], load_area_uuid[1]
def truck_pass_first_area(truck_id, lane_id, closer_entrance_node_id, further_entrance_node_id):
"""
......@@ -269,27 +331,55 @@ def truck_pass_first_area(truck_id, lane_id, closer_entrance_node_id, further_en
:return:
"""
max_find_it = 100
while max_find_it > 0:
logger.info(" ")
logger.info(lane_id)
# try:
def backtracking(root_node):
from collections import deque
que = deque([root_node])
while que:
size = len(que)
for _ in range(size):
cur_node = que.popleft()
if cur_node is None: continue
logger.info(cur_node)
if cur_node == closer_entrance_node_id:
logger.info("closer_entrance_node")
return 0
if cur_node == further_entrance_node_id:
logger.info("further_entrance_node")
return 1
for item in session_postgre.query(Lane).filter_by(StartNodeId=cur_node).all():
if item:
que.append(item.EndNodeId)
node_id = session_postgre.query(Lane).filter_by(Id=lane_id).first().EndNodeId
logger.info(node_id)
if node_id == closer_entrance_node_id:
if backtracking(root_node=node_id) == 0:
return True
if node_id == further_entrance_node_id:
else:
return False
lane_id = session_postgre.query(Lane).filter_by(StartNodeId=node_id, Type=2).first().Id
# except Exception as es:
# logger.error("车辆行驶位置判断异常")
# logger.error(es)
# return True
def get_trucks_locate():
"""
get trucks locates.
:return: truck_locate_dict
"""
try:
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
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')]
......@@ -299,12 +389,25 @@ def get_trucks_locate():
and (bytes.decode(is_online) in ["true" or "True"]) \
and (str_to_byte('laneId') in key_set):
truck_locate = key_value_dict[str_to_byte('laneId')]
if eval(truck_locate) is not '':
truck_locate_dict[truck_name_to_uuid_dict[item]] = eval(truck_locate)
return truck_locate_dict
except Exception as es:
logger.error("车辆所在路段读取异常")
logger.error(es)
return {}
def truck_dispatch_to_redis(truck_id, group_id, excavator_id):
"""
write truck dispatch to redis.
:param truck_id:
:param group_id:
:param excavator_id:
:return:
"""
# 查询车辆相关派车计划
record = {}
try:
......@@ -342,14 +445,53 @@ def truck_dispatch_to_redis(truck_id, group_id, excavator_id):
def get_lanes_between_entrances(closer_node_id, further_node_id):
"""
get lanes between two entrance nodes.
:param closer_node_id:
:param further_node_id:
:return: lane set
"""
try:
max_find_it = 100
next_node_id = closer_node_id
lane_set = []
while max_find_it > 0 and next_node_id != further_node_id:
item = session_postgre.query(Lane).filter_by(StartNodeId=next_node_id, Type=2).first()
if item:
next_lane_id = item.Id
next_node_id = item.EndNodeId
lane_set.append(next_lane_id)
max_find_it -= 1
max_find_it -= 1
return lane_set
except Exception as es:
logger.error("获取装载区间路段异常")
logger.error(es)
return []
def get_excavator_state(excavator_id):
"""
get excavator state.
:param excavator_id:
:return: state
"""
try:
device_name = session_mysql.query(Equipment).filter_by(equipment_id=excavator_id, device_type=2).first().device_name
key_value_dict = redis2.hgetall(device_name)
is_online = key_value_dict[str_to_byte('online')]
key_set = key_value_dict.keys()
state = 100
if (str_to_byte('online') in key_set) and (bytes.decode(is_online) in ["true" or "True"]):
state = key_value_dict[str_to_byte('workState')]
return state
except Exception as es:
logger.error("挖机状态读取异常")
logger.error(es)
return 0
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/11/26 11:38
# @Time : 2022/9/7 9:55
# @Author : Opfer
# @Site :
# @File : __init__.py
......
......@@ -53,6 +53,10 @@ class Topo():
# 获取日志器
self.logger = get_logger("zxt.topo")
# 车辆交叉路口点集合
self.cross_nodes = []
self.cross_bf_lanes = []
"""
unload_G funcions
"""
......@@ -99,6 +103,8 @@ class Topo():
except Exception as es:
self.logger.error(es)
self.logger.error("获取地图信息出错")
session_mysql.rollback()
session_postgre.rollback()
def return_work_area_distance_info(self):
self.get_work_area_distance_info()
......@@ -111,6 +117,8 @@ class Topo():
except Exception as es:
self.logger.error(es)
self.logger.error("获取地图备停区信息出错")
session_mysql.rollback()
session_postgre.rollback()
"""
generate_topo_graph: unload_G and load_G
......@@ -186,6 +194,8 @@ class Topo():
except Exception as es:
self.logger.error(es)
self.logger.error("去卸载区拓扑图出错")
session_mysql.rollback()
session_postgre.rollback()
# path_node_for_trip.append(Exitnode_for_digging) # add node for trip
# if i_endpoint in self.unload_G_dump_nodes:
......@@ -211,7 +221,7 @@ class Topo():
try:
load_saved_lane = []
for i in item[2]:
for i in item[2]: # [[str(item.load_area_id), str(item.unload_area_id)], item.to_unload_lanes, item.to_load_lanes]
load_i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
load_i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
......@@ -248,6 +258,8 @@ class Topo():
except Exception as es:
self.logger.error(es)
self.logger.error("去装载区拓扑图生成失败")
session_mysql.rollback()
session_postgre.rollback()
print(self.load_G.nodes.data())
......@@ -355,7 +367,11 @@ class Topo():
def get_load_edge_node(self, truck_location_lane):
try:
# truck_location_lane = self.laneinfo.update_truck_loacate()[truck_id]
for (startnode, endnode, lane) in self.load_G.edges.data('lane'):
# print(self.load_G.edges.data())
# for item in self.load_G.edges.data('lane'):
# print(len(item))
# print(item[0], item[1], item[2])
for startnode, endnode, lane in self.load_G.edges.data('lane'):
if truck_location_lane in lane:
return startnode, endnode
except Exception as es:
......@@ -447,3 +463,27 @@ class Topo():
reachable_destinations[target_digging_area] = [k + distance_end_node, 1]
return reachable_destinations
def update_cross_nodes(self):
"""
get cross nodes.
:return:
"""
self.cross_nodes = []
for node_id, Type in self.load_G.nodes.data('name'):
if Type == 'None':
self.cross_nodes.append(node_id)
def update_cross_bf_lanes(self):
"""
get cross lanes.
:return:
"""
self.cross_bf_lanes = []
for node_id, Type in self.load_G.nodes.data('name'):
if Type == 'None':
self.cross_bf_lanes.append(str(session_postgre.query(Lane).filter_by(EndNodeId=node_id).first().Id))
def get_cross_nodes(self):
return self.cross_nodes
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/9/7 9:56
# @Author : Opfer
# @Site :
# @File : topo_update.py
# @Software: PyCharm
# 导入包
import os
from graph.graph_load import *
import networkx as nx
import matplotlib.pyplot as plt
import uuid
import sqlite3
def topo_graph_update():
# 拓扑图生成与写入
conn = sqlite3.connect('test.db')
c = conn.cursor()
print("数据库打开成功")
cursor = c.execute("DROP TABLE GRAPH_EDGE")
conn.commit()
cursor = c.execute("DROP TABLE GRAPH_NODE")
conn.commit()
cursor = c.execute("CREATE TABLE GRAPH_EDGE(id VARCHAR(30) PRIMARY KEY, startNodeId VARCHAR(30), endNodeId VARCHAR(30), distance FLOAT, type INT, lanes_sql VARCHAR(100))")
conn.commit()
cursor = c.execute("CREATE TABLE GRAPH_NODE(id VARCHAR(30) PRIMARY KEY, nodeId VARCHAR(30), name VARCHAR(30))")
conn.commit()
# 清空数据库数据
cursor = c.execute("DELETE FROM GRAPH_EDGE")
conn.commit()
cursor = c.execute("DELETE FROM GRAPH_NODE")
conn.commit()
# 生成拓扑图
topo = Topo()
topo.generate_topo_graph()
# 获取装载路径拓扑图
load_G = topo.get_load_G()
# 装载路径拓扑图数据写入数据库
for item in load_G.edges.data():
print("item load_G-edge")
print(item)
id = str(uuid.uuid4())
startNodeId = item[0]
endNodeId = item[1]
distance = item[2]['real_distance']
lanes = item[2]['lane']
lanes_sql = str(" ".join(lanes))
sql = "INSERT INTO GRAPH_EDGE VALUES ('%s', '%s', '%s', '%f', 1, '%s')" % (
id, startNodeId, endNodeId, distance, lanes_sql)
cursor = c.execute(sql)
conn.commit()
# 装载节点写入数据库
for item in load_G.nodes.data():
print("item load_G-nodes")
print(item)
id = str(uuid.uuid4())
nodeId = item[0]
if item[1] != {} and item[1]['name'] != None:
name = item[1]['name']
else:
name = 'None'
sql = "INSERT INTO GRAPH_NODE VALUES ('%s' ,'%s', '%s')" % (id, nodeId, name)
cursor = c.execute(sql)
conn.commit()
# 获取卸载路径拓扑图
unload_G = topo.get_unload_G()
# 卸载路径拓扑图写入数据库
for item in unload_G.edges.data():
print("item unload_G-edge")
print(item)
id = str(uuid.uuid4())
startNodeId = item[0]
endNodeId = item[1]
distance = item[2]['real_distance']
lanes = item[2]['lane']
lanes_sql = str(" ".join(lanes))
sql = "INSERT INTO GRAPH_EDGE VALUES ('%s', '%s', '%s', '%f', 2, '%s')" % (
id, startNodeId, endNodeId, distance, lanes_sql)
cursor = c.execute(sql)
conn.commit()
# 卸载节点写入数据库
for item in unload_G.nodes.data():
print("item unload_G-nodes")
print(item)
id = str(uuid.uuid4())
nodeId = item[0]
if item[1] != {} and item[1]['name'] != None:
name = item[1]['name']
else:
name = 'None'
sql = "INSERT INTO GRAPH_NODE VALUES ('%s', '%s', '%s')" % (id, nodeId, name)
cursor = c.execute(sql)
conn.commit()
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/11/26 11:34
# @Author : Opfer
# @Site :
# @File : group_control.py
# @Software: PyCharm
from settings import *
from para_config import *
from path_plan.path_plannner import PathPlanner
from traffic_flow.traffic_flow_planner import traffic_flow_plan
class Group(WalkManage):
""" class of truck group dispatch processing.
Description:
管理车辆调度分组,计算分组调度所需信息
Attribute:
equipment class: truck, excavator, dump
group info: group num, group set, group walk cost ...
path planner class
"""
def __init__(self, dump, excavator, truck, traffic_flow):
self.dump = dump
self.excavator = excavator
self.truck = truck
self.traffic_flow = traffic_flow
self.dispatch_truck_group = {}
self.group_dispatch_truck = {}
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(dump, excavator, truck)
self.logger = get_logger("zxt.group_control")
def update_dispatch_truck_group(self):
"""
更新车辆所属分组 -> (dispatch_truck_group)
"""
# 更新矿卡-调度分组隶属关系
self.dispatch_truck_group = {}
self.group_dispatch_truck = {}
dynamic_truck_set = get_value("dynamic_truck_set")
self.logger.info("dispatch_truck_group-dynamic_truck_set")
self.logger.info(dynamic_truck_set)
# 动态派车数量没变,但是此时某条派车计划被删除,dispatch_truck_group 就会缺失矿卡
for truck_id in dynamic_truck_set:
try:
item = session_mysql.query(Dispatch).filter_by(truck_id=truck_id, isauto=1, isdeleted=0).first()
except Exception as es:
self.logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
if item is None:
print(truck_id)
continue
self.dispatch_truck_group[truck_id] = item.group_id
if item.group_id not in self.group_dispatch_truck:
self.group_dispatch_truck[item.group_id] = [truck_id]
else:
self.group_dispatch_truck[item.group_id].append(truck_id)
self.logger.info("truck_id <-> group_id")
self.logger.info(self.dispatch_truck_group)
self.logger.info(self.group_dispatch_truck)
def update_group_set(self):
"""
更新分组集合 -> (group_set, group_num)
"""
# 更新调度组
self.group_set = set()
try:
for item in session_mysql.query(Dispatch).filter_by(isauto=1, isdeleted=0).all():
if item.group_id is not None:
self.group_set.add(item.group_id)
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
self.group_num = len(self.group_set)
def update_device_group(self):
"""
更新分组所包含挖机及卸点 -> (device_group)
"""
# 更新设备分组group_id -> {set(dump_id), set(excavator_id)}
self.device_group = {}
for group_id in self.get_group_set():
if group_id not in self.device_group:
self.device_group[group_id] = [set(), set()]
else:
continue
try:
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)
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
def update_actual_traffic_flow(self):
"""
更新实时交通流 -> (actual_traffic_flow)
"""
loading_task_time = self.excavator.get_loading_task_time()
unloading_task_time = self.dump.get_unloading_task_time()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
payload = self.truck.get_payload()
dynamic_dump_num = get_value("dynamic_dump_num")
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_truck_num = get_value("dynamic_truck_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:
self.logger.info("dynamic_truck_num")
self.logger.info(dynamic_truck_num)
self.logger.info("truck.truck_index_to_uuid_dict")
self.logger.info(self.truck.truck_index_to_uuid_dict)
self.logger.info("truck_current_task")
self.logger.info(truck_current_task)
for i in range(dynamic_truck_num):
task = truck_current_task[DeviceMap.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 [3, 4]: # 矿卡空载或正在入场装载区
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])
if task in [0, 1]: # 矿卡重载或正在入场卸载区
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)
)
)
def update_group_truck_flow(self):
"""
更新调度分组内车实时/最佳车流 -> (group_opt_goto_traffic_flow, group_actual_goto_traffic_flow)
!!! 目前该部分未使用
"""
global dispatcher
actual_goto_excavator_traffic_flow, actual_goto_dump_traffic_flow = \
self.traffic_flow.actual_goto_excavator_traffic_flow, self.traffic_flow.actual_goto_dump_traffic_flow
opt_goto_dump_traffic_flow, opt_goto_excavator_traffic_flow = traffic_flow_plan(self.truck)
try:
for group_id in self.group_set:
dump_group = self.device_group[group_id][0] # group 类最后更新,读取派车计划及分组情况,和前面的uuid 可能不一致
excavator_group = self.device_group[group_id][1]
print("group")
print(self.device_group)
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[DeviceMap.excavator_uuid_to_index_dict[excavator_id]][DeviceMap.dump_uuid_to_index_dict[dump_id]]
local_opt_goto_excavator_traffic_flow[dump_group_index][excavator_group_index] = \
opt_goto_excavator_traffic_flow[DeviceMap.dump_uuid_to_index_dict[dump_id]][DeviceMap.excavator_uuid_to_index_dict[excavator_id]]
local_actual_goto_dump_traffic_flow[excavator_group_index][dump_group_index] = \
actual_goto_dump_traffic_flow[DeviceMap.excavator_uuid_to_index_dict[excavator_id]][DeviceMap.dump_uuid_to_index_dict[dump_id]]
local_actual_goto_excavator_traffic_flow[dump_group_index][excavator_group_index] = \
actual_goto_excavator_traffic_flow[DeviceMap.dump_uuid_to_index_dict[dump_id]][DeviceMap.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:
self.logger.error(es)
self.logger.error("分组车流更新异常")
self.logger.info("group_opt_traffic_flow")
self.logger.info(self.group_opt_goto_dump_traffic_flow)
self.logger.info(self.group_opt_goto_excavator_traffic_flow)
def update_group_walk_cost(self):
"""
更新调度分组路网行驶成本 -> (group_walk_cost)
"""
walk_to_excavator_cost, walk_to_dump_cost, park_to_excavator_cost = self.path.walk_cost_cal()
park_num = get_value("park_num")
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(excavator_group), len(dump_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]
print("dump_group")
print(dump_group)
local_walk_to_excavator_cost[dump_group_index][excavator_group_index] = \
walk_to_excavator_cost[DeviceMap.dump_uuid_to_index_dict[dump_id]][DeviceMap.excavator_uuid_to_index_dict[excavator_id]]
local_walk_to_dump_cost[excavator_group_index][dump_group_index] = \
walk_to_dump_cost[DeviceMap.dump_uuid_to_index_dict[dump_id]][DeviceMap.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][DeviceMap.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:
self.logger.info(es)
self.logger.info("error-11")
def update_group_device_map(self):
"""
更新调度分组内设备映射 -> (group_uuid_to_index_dict, group_index_to_uuid_dict)
"""
# 更新调度分组内设备映射
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
self.logger.info("group_map")
self.logger.info(self.group_dump_uuid_to_index_dict)
self.logger.info(self.group_excavator_uuid_to_index_dict)
def update_modify(self):
"""
更新分组内车辆锁定-禁止-物料绑定修正 ->
(group_excavator_exclude_modify group_excavator_material_bind_modify group_dump_material_bind_modify)
"""
try:
dynamic_truck_set = get_value("dynamic_truck_set")
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 = self.truck.truck_uuid_to_index_dict[truck_id]
for group_excavator_index in range(group_excavator_num):
excavator_index = self.excavator.excavator_uuid_to_index_dict[self.group_excavator_index_to_uuid_dict[group_id][group_excavator_index]]
excavator_exclude_modify[group_excavator_index] = self.truck.excavator_exclude_modify[truck_index][excavator_index]
for group_excavator_index in range(group_excavator_num):
excavator_index = self.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] = self.truck.excavator_material_bind_modify[truck_index][excavator_index]
for group_dump_index in range(group_dump_num):
dump_index = self.dump.dump_uuid_to_index_dict[self.group_dump_index_to_uuid_dict[group_id][group_dump_index]]
print(self.truck.dump_material_bind_modify, truck_index, dump_index)
print(self.truck.dump_material_bind_modify[truck_index][dump_index], truck_index, dump_index)
dump_material_bind_modify[group_dump_index] = self.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
except Exception as es:
self.logger.error(es)
self.logger.error("modify update 异常")
def update_excavator_hold_truck(self, excavator_hold_truck):
"""
更新调度分组内挖机hold矿卡
:param excavator_hold_truck: (List[int]) 挖机hold矿卡数量列表
:return:
group_excavator_hold_truck: (Dict(group_id: List[int])) 分组内挖机hold矿卡数量列表
"""
group_excavator_hold_truck = {}
for group_id in self.group_set:
excavator_group = self.device_group[group_id][1]
group_excavator_hold_truck[group_id] = np.zeros(len(excavator_group))
for excavator_id in excavator_group:
group_excavator_index = self.group_excavator_uuid_to_index_dict[group_id][excavator_id]
excavator_index = self.excavator.excavator_uuid_to_index_dict[excavator_id]
group_excavator_hold_truck[group_id][group_excavator_index] = excavator_hold_truck[excavator_index]
return group_excavator_hold_truck
def update_dump_hold_truck(self, dump_hold_truck):
"""
更新调度分组内卸点hold矿卡
:param dump_hold_truck: (List[int]) 卸点hold矿卡数量列表
:return:
group_dump_hold_truck: (Dict(group_id: List[int])) 分组内卸点hold矿卡数量列表
"""
group_dump_hold_truck = {}
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
group_dump_hold_truck[group_id] = np.zeros(len(dump_group))
for dump_id in dump_group:
group_dump_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
group_dump_hold_truck[group_id][group_dump_index] = dump_hold_truck[dump_index]
return group_dump_hold_truck
def update_excavator_avl_time(self, excavator_avl_time):
"""
更新调度分组内挖机可用时间
:param excavator_avl_time: (List[int]) 挖机可用时间列表
:return:
group_excavator_avl_time: (Dict(group_id: List[int])) 分组内挖机可用时间列表
"""
group_excavator_avl_time= {}
for group_id in self.group_set:
excavator_group = self.device_group[group_id][1]
group_excavator_avl_time[group_id] = np.zeros(len(excavator_group))
for excavator_id in excavator_group:
group_excavator_index = self.group_excavator_uuid_to_index_dict[group_id][excavator_id]
excavator_index = self.excavator.excavator_uuid_to_index_dict[excavator_id]
group_excavator_avl_time[group_id][group_excavator_index] = excavator_avl_time[excavator_index]
return group_excavator_avl_time
def update_dump_avl_time(self, dump_avl_time):
"""
更新调度分组内卸点可用时间
:param dump_avl_time: (List[int]) 卸点可用时间列表
:return:
group_dump_avl_time: (Dict(group_id: List[int])) 分组内卸点可用时间列表
"""
group_dump_avl_time = {}
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
group_dump_avl_time[group_id] = np.zeros(len(dump_group))
for dump_id in dump_group:
group_dump_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
group_dump_avl_time[group_id][group_dump_index] = dump_avl_time[dump_index]
return group_dump_avl_time
def update_allow_flow_to_excavator(self):
"""
更新分组内最大允许驶往挖机车流
:return:
group_allow_flow_to_excavator: (Dict(group_id: List[int])) 分组内最大允许驶往挖机车流
"""
group_allow_flow_to_excavator = {}
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
group_allow_flow_to_excavator[group_id] = np.zeros(len(dump_group))
for dump_id in dump_group:
group_dump_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
group_allow_flow_to_excavator[group_id][group_dump_index] = self.excavator.excavator_strength[dump_index]
return group_allow_flow_to_excavator
def update_allow_flow_to_dump(self):
"""
更新分组内最大允许驶往卸点车流
:return:
group_allow_flow_to_dump (Dict(group_id: List[int])) 分组内最大允许驶往卸点车流
"""
group_allow_flow_to_dump = {}
for group_id in self.group_set:
dump_group = self.device_group[group_id][0]
group_allow_flow_to_dump[group_id] = np.zeros(len(dump_group))
for dump_id in dump_group:
group_dump_index = self.group_dump_uuid_to_index_dict[group_id][dump_id]
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
group_allow_flow_to_dump[group_id][group_dump_index] = self.dump.dump_strength[dump_index]
return group_allow_flow_to_dump
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 = {}
\ 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, DumpInfo, ExcavatorInfo
# from path_plan.priority_control import PriorityController
from path_plan.priority_control import PriorityController
from redispatch.topo_graph import *
from para_config import *
from tables import *
M = 1000000
class PathPlanner(WalkManage):
def __init__(self, topo):
# 路段类
self.lane = LaneInfo()
self.lane.lane_speed_generate()
self.topo = topo
# 生成的拓扑图
self.unload_G = self.topo.get_unload_G()
self.load_G = self.topo.get_load_G()
# 设备类
self.dump = DumpInfo()
self.excavator = ExcavatorInfo()
self.truck = TruckInfo(self.dump, self.excavator)
self.truck.update_truck_size()
# 控制类
self.controller = PriorityController(self.dump, self.excavator, self.truck)
# 路线行驶成本
self.rout_cost = np.array((unload_area_num, load_area_num))
# 路段集合
self.lane_set = {}
self.logger = get_logger("zxt.path_planner")
try:
self.truck_length = float(sum(self.truck.get_length().values())) / len(self.truck.get_length())
except Exception as es:
self.logger.error("无矿卡数据")
self.logger.error(es)
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.cost_to_excavator = np.zeros_like(get_value("distance_to_excavator"))
self.cost_to_dump = np.zeros_like(get_value("distance_to_dump"))
self.cost_park_to_excavator = np.zeros_like(get_value("distance_park_to_excavator"))
def update_load_G_locked_distance(self, source_node, target_node, alpha, beta):
_, park_path = nx.single_source_dijkstra(self.load_G, source=source_node, target=target_node,weight="real_distance")
for i in range(len(park_path) - 1):
data = dict(self.load_G[park_path[i]][park_path[i + 1]]['lane'])
for u, v in data.items():
u_lane_cost = self.lane_cost_generate(u)
data[u] = [v[0], beta * u_lane_cost]
self.load_G[park_path[i]][park_path[i + 1]]['locked_distance'] = sum([beta * sum(i[0] for i in list(data.values())) , alpha * sum(i[-1] for i in list(data.values()))])
def update_unload_G_locked_distance(self, source_node, target_node, alpha, beta):
_, park_path = nx.single_source_dijkstra(self.unload_G, source=source_node, target=target_node,weight="real_distance")
for i in range(len(park_path) - 1):
data = dict(self.unload_G[park_path[i]][park_path[i + 1]]['lane'])
for u, v in data.items():
u_lane_cost = self.lane_cost_generate(u)
data[u] = [v[0], beta * u_lane_cost]
self.unload_G[park_path[i]][park_path[i + 1]]['locked_distance'] = sum([beta * sum(i[0] for i in list(data.values())) , alpha * sum(i[-1] for i in list(data.values()))])
def path_cost_generate(self, load_area_id, unload_area_id, is_park):
# self.logger.info("path_拓扑图输出")
# self.logger.info(self.load_G.edges(data=True))
# self.logger.info(self.unload_G.edges(data=True))
# 卸载道路阻塞成本初始化
cost_to_unload_blockage = 0
# 装载道路阻塞成本初始化
cost_to_load_blockage = 0
# 卸载道路总成本初始化
to_unload_cost = 0
# 装载道路总成本初始化
to_load_cost = 0
# 修正因子
weight = 60
# 阻塞成本权重
alpha = 1
# 距离成本权重
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
# 备停区处理
if is_park:
try:
# 获取从指定备停区到装载区的指定路径并完成cost更新
park_source_node = str(session_postgre.query(Node).filter_by(Name="测试备停区出场点").first().Id)
park_end_node = str(session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().EntranceNodeId)
self.update_load_G_locked_distance(park_source_node, park_end_node, alpha, beta)
to_load_cost = nx.dijkstra_path_length(self.load_G, source=park_source_node, target=park_end_node,
weight="locked_distance")
except Exception as es:
self.logger.error(f"从备停区到装载区{load_area_id}cost更新异常")
self.logger.error(es)
else:
try:
# from load_G part
load_source_node = str(session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().ExitNodeId)
load_end_node =str(session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().EntranceNodeId)
self.update_load_G_locked_distance(load_source_node, load_end_node, alpha, beta)
to_load_cost = nx.dijkstra_path_length(self.load_G, source=load_source_node, target=load_end_node, weight="locked_distance")
except Exception as es:
self.logger.error(f"从卸载区{unload_area_id}到装载区{load_area_id}cost更新异常")
self.logger.error(es)
try:
# from unload_G part
unload_source_node = str(session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().ExitNodeId)
unload_end_node = str(session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().EntranceNodeId)
self.update_unload_G_locked_distance(unload_source_node, unload_end_node, alpha, beta)
to_unload_cost = nx.dijkstra_path_length(self.unload_G, source=unload_source_node, target=unload_end_node, weight="locked_distance")
except Exception as es:
self.logger.error(f"从装载区{load_area_id}到卸载区{unload_area_id}cost更新异常")
self.logger.error(es)
# print("拥堵因子-挖机")
# print(alpha, cost_to_load_blockage)
# print("拥堵因子-卸点")
# print(alpha, cost_to_unload_blockage)
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:
self.logger.error('路段拥堵成本计算异常')
self.logger.error(es)
return lane_blockage
def walk_cost_cal(self):
self.excavator.para_period_update()
self.dump.para_period_update()
self.truck.para_period_update(self.dump, self.excavator)
self.truck.state_period_update()
self.period_walk_para_load()
self.period_map_para_load()
# self.controller.period_update(self.dump, self.excavator, self.truck)
# 计算行驶成本前,更新路网速度信息
self.lane.lane_speed_generate()
try:
unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
load_area_uuid_to_index_dict = get_value("load_area_uuid_to_index_dict")
park_uuid_to_index_dict = get_value(" park_uuid_to_index_dict")
# 读取路网成本
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:
self.logger.error('路网信息计成本计算异常')
self.logger.error(es)
self.cost_to_excavator = np.zeros_like(get_value("distance_to_excavator"))
self.cost_to_dump = np.zeros_like(get_value("distance_to_dump"))
self.cost_park_to_excavator = np.zeros_like(get_value("distance_park_to_excavator"))
self.logger.info("distance_park_to_excavator")
self.logger.info(self.distance_park_to_excavator)
# try:
# 路网权重
walk_to_excavator_weight, walk_to_dump_weight, park_walk_weight = self.controller.weighted_walk_calc()
# # 路网禁用关系
# walk_available = self.controller.walk_available_calc()
# group_walk_available = self.controller.update_group_walk_available()
self.logger.info("path_weight")
self.logger.info(walk_to_excavator_weight)
self.logger.info(walk_to_dump_weight)
self.logger.info(park_walk_weight)
# self.logger.info("walk_avail")
# self.logger.info(walk_available)
# except Exception as es:
# self.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]
self.logger.info("cost_to_excavator")
self.logger.info(self.cost_to_excavator)
# self.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]
self.cost_to_excavator[i][j] = self.cost_to_load_area[unload_area_index][load_area_index] / \
walk_to_excavator_weight[i][j]
# self.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]
self.cost_to_dump[i][j] = self.cost_to_unload_area[unload_area_index][load_area_index] / \
walk_to_dump_weight[j][i]
for j in range(get_value("dynamic_excavator_num")):
load_area_index = self.excavator_index_to_load_area_index_dict[j]
self.cost_park_to_excavator[0][j] = self.cost_park_to_load_area[0][load_area_index] / park_walk_weight[0][j]
self.logger.info("真实路网距离-驶往挖机:")
self.logger.info(self.distance_to_excavator)
self.logger.info("真实路网距离-驶往卸点:")
self.logger.info(self.distance_to_dump)
self.logger.info("真实备停区路网距离-驶往挖机:")
self.logger.info(self.distance_park_to_excavator)
self.logger.info("阻塞路网距离-驶往挖机:")
self.logger.info(self.cost_to_excavator)
self.logger.info("阻塞路网距离-驶往卸点:")
self.logger.info(self.cost_to_dump)
self.logger.info("阻塞备停区路网距离-驶往挖机:")
self.logger.info(self.cost_park_to_excavator)
return self.cost_to_excavator, self.cost_to_dump, self.cost_park_to_excavator
class LaneInfo:
def __init__(self):
self.lane_speed_dict = {}
self.logger = get_logger("zxt.laneinfo")
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 == str_to_byte("1") and str_to_byte('speed') in key_value_dict.keys():
truck_speed = float(key_value_dict[str_to_byte('speed')])
truck_speed_dict[truck_name_to_uuid_dict[item]] = truck_speed
except Exception as es:
self.logger.error(f'矿卡{item}实时速度读取异常')
self.logger.error(es)
print("truck_speed_dict")
print(truck_speed_dict)
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 == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
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]] = eval(truck_locate)
except Exception as es:
self.logger.error(f'矿卡{item}所在路段信息读取异常')
self.logger.error(es)
print("truck_locate_dict")
print(truck_locate_dict)
return truck_locate_dict
def lane_speed_generate(self):
# truck -> lane
truck_locate_dict = self.update_truck_loacate()
self.logger.info("矿卡位于路段:")
self.logger.info(truck_locate_dict)
# truck -> speed
truck_speed_dict = self.update_truck_speed()
self.logger.info("矿卡当前速度:")
self.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:
self.logger.error('所用路网路段集合读取异常')
self.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
# 对于各路段信息
print("truck_locate_dict")
print(truck_locate_dict.keys())
for truck in truck_locate_dict.keys():
lane_id = truck_locate_dict[truck]
self.logger.info("lane_speed_generate-lane_id")
self.logger.info(lane_id)
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)
self.logger.info("存在矿卡的路段:")
self.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:
self.logger.error("路段实时速度计算异常")
self.logger.error(es)
return self.lane_speed_dict
# path_planner = PathPlanner()
#
# path_planner.walk_cost()
#!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, DumpInfo, ExcavatorInfo
# from path_plan.priority_control import PriorityController
from path_plan.priority_control import PriorityController
from para_config import *
from tables import *
M = 1000000
class PathPlanner(WalkManage):
def __init__(self, dump, excavator, truck):
# 路段类
self.lane = LaneInfo()
self.lane.lane_speed_generate()
# 设备类
# self.dump = DumpInfo()
# self.excavator = ExcavatorInfo()
# self.truck = TruckInfo(self.dump, self.excavator)
self.dump = dump
self.excavator = excavator
self.truck = truck
# self.truck.update_truck_size()
# 控制类
self.controller = PriorityController(self.dump, self.excavator, self.truck)
# 路线行驶成本
self.rout_cost = np.array((get_value("unload_area_num"), get_value("load_area_num")))
# 路段集合
self.lane_set = {}
# 车辆长度(暂)
try:
self.truck_length = float(sum(self.truck.get_length().values())) / len(self.truck.get_length())
except Exception as es:
logger.error("无矿卡数据")
logger.error(es)
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.cost_to_excavator = np.zeros_like(get_value("distance_to_excavator"))
self.cost_to_dump = np.zeros_like(get_value("distance_to_dump"))
self.cost_park_to_excavator = np.zeros_like(get_value("distance_park_to_excavator"))
def path_cost_generate(self, load_area_id, unload_area_id, is_park, lane_cost_memory, alpha, beta):
# 卸载道路阻塞成本初始化
cost_to_unload_blockage = 0
# 装载道路阻塞成本初始化
cost_to_load_blockage = 0
# 卸载道路总成本初始化
to_unload_cost = 0
# 装载道路总成本初始化
to_load_cost = 0
# # 道路权重
# weighted_distance = weighted_walk_cost()
# 修正因子
weight = 10
session_mysql.commit()
if alpha > 0:
beta /= (beta + 0.001)
alpha = alpha / beta * weight
else:
beta = 1
try:
# 备停区处理
if is_park:
# 提取指定道路记录
try:
path = session_postgre.query(WalkTimePark).filter_by(park_area_id=unload_area_id,
load_area_id=load_area_id).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
# 读取道路路段信息
for lane_id in path.park_load_lanes:
if lane_id in self.lane.used_lane_set:
if lane_id in lane_cost_memory:
lane_cost = lane_cost_memory[lane_id]
else:
lane_cost = self.lane_cost_generate(lane_id)
lane_cost_memory[lane_id] = lane_cost
# 各路段阻塞成本累加
cost_to_load_blockage = cost_to_load_blockage + beta * lane_cost
# 道路总成本=道路距离成本+道路阻塞成本
to_load_cost = alpha * cost_to_load_blockage + beta * path.park_load_distance
else:
try:
path = session_postgre.query(WalkTime).filter_by(load_area_id=load_area_id,
unload_area_id=unload_area_id).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
for lane_id in path.to_unload_lanes:
if lane_id in self.lane.used_lane_set:
if lane_id in lane_cost_memory:
lane_cost = lane_cost_memory[lane_id]
else:
lane_cost = self.lane_cost_generate(lane_id)
lane_cost_memory[lane_id] = lane_cost
cost_to_unload_blockage = cost_to_unload_blockage + lane_cost
for lane_id in path.to_load_lanes:
if lane_id in self.lane.used_lane_set:
if lane_id in lane_cost_memory:
lane_cost = lane_cost_memory[lane_id]
else:
lane_cost = self.lane_cost_generate(lane_id)
lane_cost_memory[lane_id] = lane_cost
cost_to_load_blockage = cost_to_load_blockage + lane_cost
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
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):
""" 计算路段拥堵成本
:param lane_id: (uuid) 路段id
:return:
lane_blockage: (float) 路段拥堵度
"""
lane_blockage = 0 # 路段拥堵度默认为0
try:
try:
lane_rec = session_postgre.query(Lane).filter_by(Id=lane_id).first() # 读取路段记录
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
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_cal(self):
"""
计算路网行驶成本
:return:
cost_to_excavator: (Matrix[int]) 卸载区驶往装载区行驶成本
cost_to_dump: (Matrix[int]) 装载区驶往卸载区行驶成本
cost_park_to_excavator: (Matrix[int]) 备停区驶往装载区行驶成本
"""
alpha = 0 # 阻塞成本权重
beta = 1 # 距离成本权重
lane_cost_memory = {} # 路段拥堵度列表, 记忆化搜索
# 距离成本启用
try:
rule1 = session_mysql.query(DispatchRule).filter_by(id=1).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
if rule1.disabled == 0:
beta = rule1.rule_weight
# 拥堵成本启用
try:
rule2 = session_mysql.query(DispatchRule).filter_by(id=2).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
if rule2.disabled == 0:
alpha = rule2.rule_weight
try:
unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
load_area_uuid_to_index_dict = get_value("load_area_uuid_to_index_dict")
park_uuid_to_index_dict = get_value("park_uuid_to_index_dict")
# 读取路网成本
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, lane_cost_memory, alpha, beta)
# self.cost_to_load_area[unload_area_index][load_area_index] = \
# WalkManage.distance_to_load_area[unload_area_index][load_area_index]
# self.cost_to_unload_area[unload_area_index][load_area_index] = \
# WalkManage.distance_to_unload_area[unload_area_index][load_area_index]
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
# 读取备停区路网成本
try:
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, lane_cost_memory, alpha, beta)
# self.cost_park_to_load_area[park_area_index][load_area_index] = \
# WalkManage.distance_park_to_load_area[park_area_index][load_area_index]
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
logger.info(self.cost_park_to_load_area)
logger.info(self.distance_park_to_excavator)
except Exception as es:
logger.error('路网信息计成本计算异常')
logger.error(es)
# 基于工作区路网行驶成本, 更新设备间逻辑路网行驶成本
# 调度算法以设备间逻辑路网作为调度的依据
self.cost_to_excavator = np.zeros_like(get_value("distance_to_excavator"))
self.cost_to_dump = np.zeros_like(get_value("distance_to_dump"))
self.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_to_excavator_weight, walk_to_dump_weight, park_walk_weight = self.controller.weighted_walk_calc()
# walk_available = self.controller.walk_available_calc()
# group_walk_available = self.controller.update_group_walk_available()
logger.info("path_weight")
logger.info(walk_to_excavator_weight)
logger.info(walk_to_dump_weight)
logger.info(park_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(self.cost_to_excavator)
# self.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]
self.cost_to_excavator[i][j] = self.cost_to_load_area[unload_area_index][load_area_index] / \
walk_to_excavator_weight[i][j]
# self.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]
self.cost_to_dump[i][j] = self.cost_to_unload_area[unload_area_index][load_area_index] / \
walk_to_dump_weight[j][i]
for j in range(get_value("dynamic_excavator_num")):
load_area_index = self.excavator_index_to_load_area_index_dict[j]
self.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(self.cost_to_excavator)
logger.info("阻塞路网距离-驶往卸点:")
logger.info(self.cost_to_dump)
logger.info("阻塞备停区路网距离-驶往挖机:")
logger.info(self.cost_park_to_excavator)
return self.cost_to_excavator, self.cost_to_dump, self.cost_park_to_excavator
class LaneInfo:
def __init__(self):
self.lane_speed_dict = {} # 路段速度表
self.used_lane_set = [] # 存在矿卡路段表
def update_truck_speed(self):
"""读取矿卡实时速度信息
:return:
truck_speed_dict: (Dict{key:truck_id, value:speed}) 矿卡速度表
"""
truck_speed_dict = {}
try:
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_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 == str_to_byte("1") and str_to_byte('speed') in key_value_dict.keys():
truck_speed = float(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):
"""读取矿卡所在路段信息
:return:
truck_locate_dict: (Dict{key:truck_id, value:lane_id}) 矿卡所在路段表
"""
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
self.used_lane_set = []
# 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 == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
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]] = eval(truck_locate)
self.used_lane_set.append(eval(truck_locate))
# except Exception as es:
# logger.error(f'矿卡{item}所在路段信息读取异常')
# logger.error(es)
logger.info("truck_locate_dict")
logger.info(truck_locate_dict)
return truck_locate_dict
def lane_speed_generate(self):
"""计算存在矿卡路段实时速度
:return:
lane_speed_dict: (Dict{key:lane_id, value:avg_speed}) 各路段矿卡平均速度
"""
truck_locate_dict = self.update_truck_loacate() # truck -> lane
logger.info("矿卡位于路段:")
logger.info(truck_locate_dict)
truck_speed_dict = self.update_truck_speed() # 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)
self.lane_speed_dict = {} # lane -> avg_speed
lane_trucks_dict = {} # lane -> truck_num
try:
# 初始化
for lane_id in self.used_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]
logger.info("lane_speed_generate-lane_id")
logger.info(lane_id)
# 矿卡速度字段和位置字段存在
if truck in truck_speed_dict and truck in truck_locate_dict:
self.lane_speed_dict[truck_locate_dict[truck]] += truck_speed_dict[truck]
# 该路段矿卡数量加一
lane_trucks_dict[truck_locate_dict[truck]] += 1
# # 记录存在行驶矿卡的路段
# self.used_lane_set.append(lane_id)
# 存在矿卡的路段
logger.info("存在矿卡的路段:")
logger.info(self.used_lane_set)
# # 对不存在的矿卡路段,实时速度设置为最高
# for lane_id in lane_set:
# if lane_id not in self.used_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 *
class PriorityController:
def __init__(self, dump, excavator, truck):
# 设备类
self.dump = dump
self.excavator = excavator
self.truck = truck
# 获取日志器
self.logger = get_logger("zxt.prio")
def weighted_walk_calc(self):
"""
计算运输路线权重, 权重影响因素:设备优先级, 物料优先级,
:return:
walk_weight: 卸载-装载区 路网权重
park_walk_weight: 备停区-装载区 路网权重
"""
park_num = get_value("park_num")
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")
walk_to_excavator_weight = np.ones((dynamic_dump_num, dynamic_excavator_num))
walk_to_dump_weight = np.ones((dynamic_excavator_num, dynamic_dump_num))
excavator_priority = self.excavator.excavator_priority_coefficient
excavator_material_priority = self.excavator.excavator_material_priority
dump_priority = self.dump.dump_priority_coefficient
dump_material_priority = np.ones(dynamic_dump_num)
park_walk_weight = np.ones((park_num, dynamic_excavator_num))
try:
rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
if not rule6.disabled:
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
walk_to_excavator_weight[dump_index][excavator_inedx] += excavator_priority[excavator_inedx]
walk_to_dump_weight[excavator_inedx][dump_index] += dump_priority[dump_index]
park_walk_weight = park_walk_weight * self.excavator.excavator_priority_coefficient
try:
rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
if not rule7.disabled:
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
walk_to_excavator_weight[dump_index][excavator_inedx] += excavator_material_priority[excavator_inedx]
walk_to_dump_weight[excavator_inedx][dump_index] += dump_material_priority[dump_index]
park_walk_weight = park_walk_weight * self.excavator.excavator_material_priority
try:
walk_to_excavator_weight = walk_to_excavator_weight - (walk_to_excavator_weight.min() - 1)
walk_to_dump_weight = walk_to_dump_weight - (walk_to_dump_weight.min() - 1)
park_walk_weight = park_walk_weight - (park_walk_weight.min() - 1)
except Exception as es:
self.logger.error(es)
self.logger.error("优先级归一化异常")
return walk_to_excavator_weight, walk_to_dump_weight, park_walk_weight
def walk_available_calc(self):
"""
计算路网可通行性(物料, 地图, 分组三者综合)
:return:
walk_available: 路网可通行性(dump_num, excavator_num)
"""
map_walk_available = self.update_map_walk_available()
group_walk_available = self.update_group_walk_available()
material_walk_available = self.update_material_walk_available()
walk_available = map_walk_available * group_walk_available * material_walk_available
return walk_available
def update_group_walk_available(self):
"""
计算调度分组间的路网可通行性, 不同分组间路网不可通行
:return:
group_walk_available: 调度分组路网可通行性矩阵(dump_num, excavator_num)
"""
group_walk_available = np.zeros((get_value("dynamic_dump_num"), get_value("dynamic_excavator_num")))
for dump_id in get_value("dynamic_dump_set"):
for excavator_id in get_value("dynamic_excavator_set"):
try:
item = session_mysql.query(DispatchSetting).filter_by(dump_id=dump_id, exactor_id=excavator_id, isauto=1,
isdeleted=0).first()
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
if item is not None:
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
excavator_index = self.excavator.excavator_uuid_to_index_dict[excavator_id]
group_walk_available[dump_index][excavator_index] = 1
return group_walk_available
def update_material_walk_available(self):
"""
更新物料兼容性下路网可通行性
:return:
walk_available: 物料兼容路网可通行性矩阵(dump_num, excavator_num)
"""
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")
walk_available = np.ones((dynamic_dump_num, dynamic_excavator_num))
try:
for dump_id in dynamic_dump_set:
for excavator_id in dynamic_excavator_set:
dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
# 两设备处理物料不同, 相关路网不可通行
if self.excavator.excavator_material[excavator_id] != self.dump.dump_material[dump_id]:
walk_available[dump_index][excavator_inedx] = 0
except Exception as es:
self.logger.info(es)
self.logger.info("error-12")
return walk_available
def update_map_walk_available(self):
"""
更新物理路网可通行性
:return:
walk_available: 物理路网可通行性矩阵(dump_num, excavator_num)
"""
dynamic_dump_num = get_value("dynamic_dump_num")
dynamic_excavator_num = get_value("dynamic_excavator_num")
walk_available = np.ones((dynamic_dump_num, dynamic_excavator_num))
for dump_index in range(dynamic_dump_num):
for excavator_index in range(dynamic_excavator_num):
if WalkManage.distance_to_excavator[dump_index][excavator_index] > M / 2:
walk_available[dump_index][excavator_index] = 0
return walk_available
from topo_graph import *
import networkx as nx
import matplotlib.pyplot as plt
#
# topo = Topo()
# topo.generate_topo_graph()
# load_G = topo.get_load_G()
# pos = nx.shell_layout(load_G)
# nx.draw(load_G, pos, with_labels=True, node_color='red', edge_color='blue', font_size=18, width=5, node_size=600,
# alpha=0.5)
# plt.show()
......@@ -8,7 +8,7 @@
# 实时调度模块
from para_config import *
from data.para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
......
......@@ -8,7 +8,7 @@
# 实时调度模块
from para_config import *
from data.para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
......
......@@ -8,17 +8,17 @@
from flask import Flask, request
from flask.json import jsonify
from para_config import *
from data.para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.dispatcher import PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
from graph_load import graph_construct
from graph.graph_load import graph_construct
config = {
"DEBUG": True, # some Flask specific configs
......
# from redispatch.topo_graph import *
# from graph.topo_graph import *
# import networkx as nx
# import matplotlib.pyplot as plt
#
......@@ -11,6 +11,127 @@
# # topo.get_unload_target_node_real()
# plt.show()
A = [['309705a0-5ddf-4559-b6c4-ee17a57677ad', 9.04], ['899705a0-5ddf-4559-b6c4-ee17a57677ad', 6.05]]
A = sorted(A, key=lambda item: item[1])
print(A)
\ No newline at end of file
# import numpy as np
#
# arrival_truck_set = ['309705a0-5ddf-4559-b6c4-ee17a57677ad', '899705a0-5ddf-4559-b6c4-ee17a57677ad']
#
# arrival_truck_reach_time = [8.04, 6.05]
# #
# # arrival_truck_set = ['309705a0-5ddf-4559-b6c4-ee17a57677ad']
# #
# # arrival_truck_reach_time = [8.04]
#
# arrival_truck_list = list(zip(np.array(arrival_truck_set), np.array(arrival_truck_reach_time)))
#
# print(arrival_truck_list)
#
# arrival_truck_list = sorted(arrival_truck_list, key=lambda item: item[1])
#
# # print(arrival_truck_list)
# #
# # print(zip(*arrival_truck_list))
#
# for x1, x2 in arrival_truck_list:
# print(x1, x2)
# A = [['309705a0-5ddf-4559-b6c4-ee17a57677ad', 9.04], ['899705a0-5ddf-4559-b6c4-ee17a57677ad', 6.05]]
# A = sorted(A, key=lambda item: item[1])
# print(A)
from graph.topo_graph import *
import networkx as nx
import matplotlib.pyplot as plt
import sqlite3
conn = sqlite3.connect('test.db')
c = conn.cursor()
cursor = c.execute("SELECT * FROM GRAPH_NODE")
node_label = {}
for row in cursor:
node_label[row[1]] = row[2]
print(node_label)
load_G = nx.Graph()
unload_G = nx.Graph()
cursor = c.execute("SELECT * FROM GRAPH_EDGE")
for row in cursor:
# 处理边包含路段
lanes = row[5].split(" ")
lane_info = {}
for item in lanes:
try:
# print(item)
distance = session_postgre.query(Lane).filter_by(Id=item).first().Length
lane_info[item] = list([distance, distance])
except Exception as es:
print(es)
session_postgre.rollback()
# 重构卸载路径拓扑图
if row[4] == 1:
load_G.add_node(row[1], name=node_label[row[1]])
load_G.add_node(row[2], name=node_label[row[2]])
load_G.add_edge(str(row[1]), str(row[2]), real_distance=row[3], lane=lane_info)
# 重构装载路径拓扑图
else:
unload_G.add_node(row[1], name=node_label[row[1]])
unload_G.add_node(row[2], name=node_label[row[2]])
unload_G.add_edge(str(row[1]), str(row[2]), real_distance=row[3], lane=lane_info)
print("数据操作成功")
node_label_load = {}
node_label_unload = {}
for node in load_G.nodes:
if node in node_label:
if node_label[node] == "None":
node_label_load[node] = ''
else:
node_label_load[node] = node_label[node]
else:
node_label_load[node] = ''
for node in unload_G.nodes:
if node in node_label:
if node_label[node] == "None":
node_label_unload[node] = ''
else:
node_label_unload[node] = node_label[node]
else:
node_label_unload[node] = ''
pos1 = nx.spring_layout(load_G)
# nx.draw(load_G, pos1, with_labels=False, node_color='red', edge_color='blue', font_size=30, width=3, node_size=200,
# alpha=0.5)
nx.draw_networkx(load_G, pos=pos1, labels=node_label_load, with_labels=True, node_color='red', \
edge_color='blue', font_size=10, width=1.5, node_size=100, alpha=0.5)
plt.show()
pos2 = nx.spring_layout(unload_G)
# pos2 = nx.shell_layout(unload_G)
# nx.draw(load_G, pos1, with_labels=False, node_color='red', edge_color='blue', font_size=30, width=3, node_size=200,
# alpha=0.5)
nx.draw_networkx(unload_G, pos=pos2, labels=node_label_unload, with_labels=True, node_color='red', \
edge_color='blue', font_size=15, width=3, node_size=200, alpha=0.5)
plt.show()
# topo = Topo()
# topo.load_G = load_G
# topo.unload_G = unload_G
#
# print(topo.load_G.nodes.data('None'))
# print(topo.get_load_target_node_real("6b417083-83b0-4eec-a8bd-2f85f96cb029", "1010cbfe-b134-3ef1-91bb-d746241c975a"))
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/3 10:51
# @Time : 2022/9/7 10:22
# @Author : Opfer
# @Site :
# @File : __init__.py.py
# @File : topo_update_server.py
# @Software: PyCharm
from graph.topo_update import topo_graph_update
from graph.graph_load import graph_construct
# topo_graph_update()
graph_construct()
\ No newline at end of file
#!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
class Traffic_flow(WalkManage):
"""
Traffic flow information class
"""
def __init__(self, dump, excavator, truck):
self.dump = dump
self.excavator = excavator
self.truck = truck
# 驶往挖机的实际车流
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 update_actual_traffic_flow(self):
loading_task_time = self.excavator.get_loading_task_time()
unloading_task_time = self.dump.get_unloading_task_time()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
payload = self.truck.get_payload()
# 设备参数读取
dynamic_dump_num = get_value("dynamic_dump_num")
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_truck_num = get_value("dynamic_truck_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)
)
# 统计路网矿卡数量
for i in range(dynamic_truck_num):
task = truck_current_task[self.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])
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("traffic_flow.goto_dump_truck_num")
logger.info(self.goto_dump_truck_num)
logger.info("traffic_flow.actual_goto_dump_traffic_flow")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("traffic_flow.goto_excavator_truck_num")
logger.info(self.goto_excavator_truck_num)
logger.info("traffic_flow.actual_goto_excavator_traffic_flow")
logger.info(self.actual_goto_excavator_traffic_flow)
logger.info("驶往卸点实际载重")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("驶往卸点实际车流")
logger.info(self.actual_goto_dump_traffic_flow)
logger.info("装载任务时间(含出入场)")
logger.info(loading_task_time)
logger.info("卸载任务时间(含出入场)")
logger.info(unloading_task_time)
# 车流规划类
class Traffic_para(WalkManage):
def __init__(self, num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump, truck):
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 = np.full((1, num_of_dump), 100) # 最小产量约束
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_cal()
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):
unload_area_index_to_uuid_dict = get_value("unload_area_index_to_uuid_dict")
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)):
logger.debug("extract_excavator_info-excavator_index")
logger.debug(excavator_index)
logger.debug("extract_excavator_info-excavator_id")
logger.debug(self.excavator_index_to_uuid_dict[excavator_index])
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("车流规划信息计算异常")
try:
# 车流规划部分矩阵格式与其余两个模块不同
self.cost_to_dump = self.path_planner.cost_to_dump
self.cost_to_excavator = self.path_planner.cost_to_excavator
logger.info("cost_to_dump")
logger.info(self.cost_to_dump)
logger.info("cost_to_excavator")
logger.info(self.cost_to_excavator)
logger.info("self.goto_excavator_factor")
logger.info(self.goto_excavator_factor)
logger.info("self.goto_dump_factor")
logger.info(self.goto_dump_factor)
logger.info("dynamic_dump_num")
logger.info(get_value("dynamic_dump_num"))
logger.info("dynamic_excavator_num")
logger.info(get_value("dynamic_excavator_num"))
# ga
# 路网信息读取
for dump_index in range(get_value("dynamic_dump_num")):
for excavator_index in range(get_value("dynamic_excavator_num")):
self.goto_excavator_factor[dump_index][excavator_index] = \
(self.cost_to_excavator[dump_index][excavator_index] / (empty_speed * 1000)) / self.payload
self.goto_dump_factor[excavator_index][dump_index] = \
(self.cost_to_dump[dump_index][excavator_index] / (heavy_speed * 1000)) / self.payload
# logger.info("self.goto_dump_factor")
# logger.info(self.goto_dump_factor)
# logger.info("self.goto_dump_factor")
# logger.info(self.goto_dump_factor)
except Exception as es:
logger.error("车流规划信息计算异常")
logger.error(es)
# 初始化车流规划类
def Traffic_para_init(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump, truck):
# try:
tra_para = Traffic_para(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump, truck)
tra_para.extract_excavator_info()
tra_para.extract_dump_info()
tra_para.extract_walk_time_info()
truck.update_truck_payload()
tra_para.payload = np.mean(truck.get_payload())
# 动态派车矿卡集合
tra_para.truck_total_num = get_value("dynamic_truck_num")
print("truck.get_dump_hold_truck_num")
print(truck.get_dump_hold_truck_num())
print("truck.get_excavator_hold_truck_num")
print(truck.get_excavator_hold_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]
# 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()))
prob += (pulp.lpDot(flatten(var_x), coefficient_goto_dump.flatten()) + pulp.lpDot(flatten(var_y),
coefficient_goto_excavator.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 j in range(col):
prob += pulp.lpSum(var_y[j]) >= min_throughout[j]
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)
prob += (pulp.lpSum(unload_truck_total_num_array) <= truck_total_num)
prob += (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")
print(excavator_hold_truck_num, i)
prob += (pulp.lpSum((np.array(var_x))[i]) <= excavator_hold_truck_num[i] * 10000 + 0.001)
for j in range(col):
print(dump_hold_truck_num)
print(dump_hold_truck_num, j)
prob += (pulp.lpSum((np.array(var_y))[j]) <= dump_hold_truck_num[j] * 10000 + 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(truck):
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)
dump_num = get_value("dynamic_dump_num")
excavator_num = get_value("dynamic_excavator_num")
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, truck)
# 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 * 100
s_ij = traffic_programme_para.goto_excavator_factor * 100
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
cost_to_excavator = traffic_programme_para.cost_to_excavator
cost_to_dump = traffic_programme_para.cost_to_dump
logger.info("车流规划参数")
logger.info(" ")
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,
cost_to_excavator, cost_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