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