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
c81d437a
Commit
c81d437a
authored
Oct 18, 2022
by
张晓彤
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
代码优化v2
parent
39eaec24
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
520 additions
and
437 deletions
+520
-437
app.py
app.py
+1
-1
dispatcher.py
core/dispatcher.py
+8
-306
group.py
core/group.py
+226
-106
schedule.py
core/schedule.py
+3
-3
submit.py
core/submit.py
+258
-0
dispatchInfo.py
data/dispatchInfo.py
+12
-12
truck.py
equipment/truck.py
+4
-1
topo_graph.py
graph/topo_graph.py
+7
-7
redispatch.py
redispatch/redispatch.py
+1
-1
No files found.
app.py
View file @
c81d437a
...
...
@@ -9,7 +9,7 @@ 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
core.
submit
import
DispatchSubmission
config
=
{
"DEBUG"
:
True
,
# some Flask specific configs
...
...
core/dispatcher.py
View file @
c81d437a
...
...
@@ -5,23 +5,15 @@
# @Site :
# @File : dispatcher.py
# @Software: PyCharm
from
core.submit
import
DispatchSubmission
from
data.dispatchInfo
import
DispatchInfo
from
core.group
import
Group
from
alg.algorithm
import
ExpectedTime
from
settings
import
get_logger
,
redis5
from
tables
import
DispatchSetting
from
data.para_config
import
get_value
from
settings
import
get_logger
from
equipment
import
TruckInfo
,
ExcavatorInfo
,
DumpInfo
from
core.schedule
import
PreSchedule
import
json
import
uuid
from
tables
import
session_mysql
,
session_postgre
from
graph.graph_load
import
graph_construct
from
core.util
import
POST
from
graph.topo_graph
import
Topo
from
core.group
import
CurrentTruck
from
typing
import
List
from
core.group
import
GroupDispatcher
class
Dispatcher
:
...
...
@@ -81,7 +73,11 @@ class Dispatcher:
# try:
truck_dispatch_plan_dict
=
group
.
group_dispatch
(
ExpectedTime
)
# 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
:
self
.
logger
.
error
(
f
'分组 {group.group_id} 调度异常'
)
...
...
@@ -95,297 +91,3 @@ class Dispatcher:
self
.
submission
.
group_dispatch_to_redis
(
group
,
truck_dispatch_plan_dict
)
def
redis_format
(
truck_id
,
group_id
,
dispatch_id
,
item
):
record
=
{
"truckId"
:
truck_id
,
"dispatchId"
:
dispatch_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
[
group_id
]}
return
record
class
DispatchSubmission
:
""" class for the submission calculated dispatch.
Description:
将调度结果按照指定格式传递到云端机群
Attribute:
"""
def
__init__
(
self
,
dump
:
DumpInfo
,
excavator
:
ExcavatorInfo
,
truck
:
TruckInfo
,
topo
:
Topo
):
self
.
logger
=
get_logger
(
"zxt.submission"
)
self
.
dump
=
dump
self
.
excavator
=
excavator
self
.
truck
=
truck
self
.
topo
=
topo
def
truck_dispatch_to_redis
(
self
,
truck_id
:
str
,
truck_info
:
CurrentTruck
,
dispatch_seq
:
List
[
int
],
group_mode
:
int
):
"""
将truck_id对应矿卡派车计划写入redis
:param group_mode: (int)
:param truck_id: (uuid) 矿卡uuid
:param truck_info: (object)
:param dispatch_seq: (List[int]) 矿卡派车计划
:return: None
"""
self
.
logger
.
info
(
f
'调度车辆编号 {get_value("truck_uuid_to_name_dict")[truck_id]} {truck_id}'
)
self
.
logger
.
info
(
f
'车辆任务 {truck_info.get_task()}'
)
self
.
logger
.
info
(
f
'配对挖机 {dispatch_seq[0]}'
)
self
.
logger
.
info
(
f
'配对卸点 {dispatch_seq[1]}'
)
# try:
if
truck_id
not
in
DispatchInfo
.
truck_group_dict
:
group_id
=
None
self
.
logger
.
error
(
f
'调度结果写入异常-读取矿卡 {truck_id} 所在分组信息异常'
)
else
:
group_id
=
DispatchInfo
.
truck_group_dict
[
truck_id
]
record
=
{
"truckId"
:
truck_id
}
# if group_id is None or DispatchInfo.get_group_mode(group_id) is None:
# group_mode = 3
# self.logger.error("调度模式读取异常-设置为固定派车模式")
# else:
# group_mode = DispatchInfo.get_group_mode(group_id)
self
.
logger
.
info
(
f
'调度模式 {group_mode}'
)
if
group_mode
==
3
:
self
.
logger
.
info
(
"固定派车模式"
)
self
.
fixed_dispatch_mode
(
group_id
,
truck_id
)
else
:
self
.
logger
.
info
(
"动态调度模式"
)
self
.
dynamic_dispatch_mode
(
dispatch_seq
,
group_id
,
record
,
truck_info
.
get_sate
(),
truck_info
.
get_task
(),
truck_id
)
# except Exception as es:
# self.logger.error("调度结果写入异常")
# self.logger.error(f"调度结果:{dispatch_seq}")
# self.logger.error(es)
def
dynamic_dispatch_mode
(
self
,
dispatch_seq
,
group_id
,
record
,
state
,
task
,
truck_id
):
"""
write dispatch plan in dynamic dispatch mode.
:param dispatch_seq:
:param group_id:
:param record:
:param state:
:param task:
:param truck_id:
:return:
"""
if
(
task
in
[
1
,
2
])
or
(
task
==
3
and
state
==
2
):
# 车辆位于卸载区,或车辆重载等待
self
.
logger
.
info
(
f
'卸载区内或重载等待,请求装载区 {truck_id}'
)
# 查询车辆相关派车计划 dispatch_seq[next_excavator_id, next_unload_area_id]
if
dispatch_seq
[
1
]
is
None
or
[
dispatch_seq
[
1
]]
not
in
DispatchInfo
.
unload_area_dump_dict
:
# 无法查询到目标卸载点
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
else
:
dump_id
=
DispatchInfo
.
unload_area_dump_dict
[
dispatch_seq
[
1
]]
try
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
dump_id
=
dump_id
,
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
if
item
is
None
:
raise
Exception
(
f
'{truck_id} 无法找到派车计划 {dump_id} {group_id}'
)
if
dispatch_seq
[
0
]
is
None
:
raise
Exception
(
"调度计划挖机与实时监控不匹配"
)
except
Exception
as
es
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
self
.
logger
.
error
(
es
)
# 其余调度信息写入
try
:
redis_format
(
truck_id
,
group_id
,
str
(
uuid
.
uuid1
()),
item
)
# # record["dispatchId"] = item.id
# record["dispatchId"] = str(uuid.uuid1())
# record["exactorId"] = item.exactor_id
# record["loadAreaId"] = item.load_area_id
# record["dumpId"] = item.dump_id
# record["unloadAreaId"] = item.unload_area_id
# record["groupId"] = group_id
# record["isdeleted"] = False
# # record["isTemp"] = False
# record["haulFlag"] = -1
# record["groupName"] = DispatchInfo.group_name[group_id]
if
task
==
3
and
state
==
2
and
self
.
truck
.
get_truck_locate_dict
()[
truck_id
]
in
self
.
topo
.
cross_bf_lanes
:
# try:
# if truck_id in self.truck.truck_is_temp and not self.truck.truck_is_temp[truck_id]:
self
.
logger
.
info
(
"二次调度前往卸载区"
)
record
[
"isTemp"
]
=
True
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
POST
(
truck_id
)
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
# else:
# self.logger.info("车辆已完成二次调度-无需更改派车计划")
# except Exception as es:
# self.logger.error(es)
# self.logger.error("二次调度失败")
# record["isTemp"] = False
# redis5.set(truck_id, str(json.dumps(record)))
else
:
self
.
logger
.
info
(
"调度前往卸载区"
)
record
[
"isTemp"
]
=
False
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
# redis5.set(truck_id, str(json.dumps(record)))
except
Exception
as
es
:
self
.
logger
.
error
(
"调度结果写入异常-矿卡空载"
)
self
.
logger
.
error
(
es
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
# redis5.set(truck_id, str(json.dumps(record)))
# finally:
# redis5.set(truck_id, str(json.dumps(record)))
elif
(
task
in
[
4
,
5
])
or
(
task
==
0
and
state
==
2
):
# 卡车重载或在卸载区出场前, 可变更装载目的地
self
.
logger
.
info
(
f
'调度2 {truck_id}'
)
# 查询车辆相关派车计划
try
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
exactor_id
=
dispatch_seq
[
0
],
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
if
item
is
None
:
raise
Exception
(
"调度计划配置异常"
)
if
dispatch_seq
[
0
]
is
None
:
raise
Exception
(
"调度计划表与实时监控不匹配"
)
except
Exception
as
es
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
self
.
logger
.
error
(
es
)
# 调度信息写入
try
:
# record["dispatchId"] = item.id
record
[
"dispatchId"
]
=
str
(
uuid
.
uuid1
())
record
[
"exactorId"
]
=
item
.
exactor_id
record
[
"loadAreaId"
]
=
item
.
load_area_id
record
[
"dumpId"
]
=
item
.
dump_id
record
[
"unloadAreaId"
]
=
item
.
unload_area_id
record
[
"groupId"
]
=
group_id
record
[
"isdeleted"
]
=
False
# record["isTemp"] = False
record
[
"haulFlag"
]
=
-
1
record
[
"groupName"
]
=
DispatchInfo
.
group_name
[
group_id
]
if
task
==
0
and
state
==
2
and
self
.
truck
.
get_truck_locate_dict
()[
truck_id
]
in
self
.
topo
.
cross_bf_lanes
:
# 车辆停车等待
# try:
# if truck_id in self.truck.truck_is_temp and not self.truck.truck_is_temp[truck_id]:
self
.
logger
.
info
(
"二次调度前往装载区"
)
record
[
"isTemp"
]
=
True
# 若尚未二次调度
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
POST
(
truck_id
)
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
# else:
# self.logger.info("车辆已完成二次调度-无需更改派车计划")
# except Exception as es:
# self.logger.error(es)
# self.logger.error("二次调度失败")
# record["isTemp"] = False
# redis5.set(truck_id, str(json.dumps(record)))
else
:
self
.
logger
.
info
(
"调度前往装载区"
)
record
[
"isTemp"
]
=
False
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
# redis5.set(truck_id, str(json.dumps(record)))
except
Exception
as
es
:
self
.
logger
.
error
(
"调度结果写入异常-矿卡重载"
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
# finally:
# redis5.set(truck_id, str(json.dumps(record)))
elif
task
==
-
2
:
self
.
logger
.
info
(
f
'调度3 {truck_id}'
)
try
:
# 查询车辆相关派车计划
try
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
exactor_id
=
dispatch_seq
[
0
],
group_id
=
group_id
,
isdeleted
=
0
)
.
first
())
if
item
is
None
:
raise
Exception
(
"调度计划配置异常"
)
if
dispatch_seq
[
0
]
is
None
:
raise
Exception
(
"调度计划表与实时监控不匹配"
)
except
Exception
as
es
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
self
.
logger
.
error
(
es
)
# 调度信息写入
# try:
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
record
=
redis_format
(
truck_id
,
group_id
,
str
(
uuid
.
uuid1
()),
item
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
# except Exception as es:
# self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
# self.logger.error(es)
# finally:
# redis5.set(truck_id, str(json.dumps(record)))
except
Exception
as
es
:
self
.
logger
.
error
(
"调度结果写入异常-矿卡故障或备停区"
)
self
.
logger
.
error
(
es
)
else
:
pass
def
fixed_dispatch_mode
(
self
,
group_id
,
truck_id
):
"""
write dispatch plan in fixed dispatch method.
:param group_id:
:param record:
:param truck_id:
:return:
"""
try
:
item
=
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
truck_id
=
truck_id
,
isdeleted
=
0
,
)
.
first
()
except
Exception
as
es
:
item
=
None
self
.
logger
.
error
(
es
)
session_postgre
.
rollback
()
session_mysql
.
rollback
()
if
item
is
None
:
self
.
logger
.
error
(
f
'车辆 {truck_id} 无派车计划-无法执行固定派车'
)
return
record
=
redis_format
(
truck_id
,
group_id
,
item
.
id
,
item
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
def
group_dispatch_to_redis
(
self
,
group
:
Group
,
dispatch_plan_dict
):
"""
Update the dispatch plan in the group to redis
:param group: (Group)
:param dispatch_plan_dict: (Dict)
:return: None
"""
self
.
logger
.
info
(
f
'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}'
)
self
.
logger
.
info
(
f
'组内车辆 {group.truck_set}'
)
self
.
logger
.
info
(
f
'组内挖机 {group.excavator}'
)
self
.
logger
.
info
(
f
'组内卸点 {group.dump}'
)
self
.
logger
.
info
(
f
'调度模式 {group.group_mode}'
)
self
.
logger
.
info
(
"dispatch_plan_dict"
)
self
.
logger
.
info
(
dispatch_plan_dict
)
for
truck_id
,
dispatch_plan
in
dispatch_plan_dict
.
items
():
try
:
self
.
logger
.
info
(
f
'======================================= 调度车辆 ======================================='
)
self
.
truck_dispatch_to_redis
(
truck_id
,
group
.
truck_info_list
[
truck_id
],
dispatch_plan
,
group
.
group_mode
)
self
.
logger
.
info
(
"======================================== 完成写入 ======================================="
)
except
Exception
as
es
:
self
.
logger
.
error
(
"group_dispatch_to_redis_error"
)
self
.
logger
.
error
(
es
)
core/group.py
View file @
c81d437a
...
...
@@ -241,6 +241,13 @@ class Group:
self
.
update_group_road_network
()
self
.
update_device_material
()
class
GroupDispatcher
:
def
__init__
(
self
,
group
:
Group
):
self
.
logger
=
logging
.
getLogger
(
"zxt.GroupDispatcher"
)
self
.
group
=
group
def
group_dispatch
(
self
,
Solver
)
->
Mapping
[
str
,
List
[
str
]]:
"""
Receive a Alg obj. and output dispatch plan for trucks in this group.
...
...
@@ -249,24 +256,24 @@ class Group:
dispatch plan: Dict({truck_id: match_id})
"""
truck_dispatch
=
{}
self
.
truck_info_list
=
{}
self
.
group
.
truck_info_list
=
{}
assert
issubclass
(
Solver
,
AlgorithmBase
)
solver
=
Solver
(
self
,
self
.
truck
,
self
.
pre_sch
)
# solver algorithm init
solver
=
Solver
(
self
.
group
,
self
.
group
.
truck
,
self
.
group
.
pre_sch
)
# solver algorithm init
self
.
logger
.
info
(
f
'分组 {self.group
_name} 调度计算-调度模式 {self
.group_mode}'
)
self
.
logger
.
info
(
f
'分组 {self.group
.group_name} 调度计算-调度模式 {self.group
.group_mode}'
)
for
truck_id
in
list
(
self
.
truck_set
):
for
truck_id
in
list
(
self
.
group
.
truck_set
):
self
.
logger
.
info
(
f
'调度车辆 {truck_id}'
)
# try:
# get truck index from mapping
try
:
if
truck_id
not
in
self
.
truck
.
truck_uuid_to_index_dict
:
if
truck_id
not
in
self
.
group
.
truck
.
truck_uuid_to_index_dict
:
raise
CoreException
(
102
,
f
'truck.truck dict 中不存在 {truck_id}'
)
truck_idx
=
self
.
truck
.
truck_uuid_to_index_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
)
...
...
@@ -274,12 +281,12 @@ class Group:
# get truck trip from truck obj.
try
:
truck_trip_info_list
=
self
.
truck
.
get_truck_current_trip
()
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
.
truck
.
get_truck_current_trip
()[
truck_idx
]
truck_trip
=
self
.
group
.
truck
.
get_truck_current_trip
()[
truck_idx
]
except
CoreException
as
es
:
es
.
with_traceback_info
()
self
.
logger
.
error
(
es
)
...
...
@@ -287,7 +294,7 @@ class Group:
# get truck task from truck obj.
try
:
truck_task_list
=
self
.
truck
.
get_truck_current_task
()
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}'
)
...
...
@@ -300,10 +307,10 @@ class Group:
continue
# Construct a truck obj.
truck_info
=
CurrentTruck
(
truck_id
,
self
.
group_id
,
truck_trip
,
truck_task
,
self
.
truck
.
get_truck_current_state
()[
truck_id
])
truck_info
=
CurrentTruck
(
truck_id
,
self
.
group
.
group
_id
,
truck_trip
,
truck_task
,
self
.
group
.
truck
.
get_truck_current_state
()[
truck_id
])
self
.
truck_info_list
[
truck_id
]
=
truck_info
self
.
group
.
truck_info_list
[
truck_id
]
=
truck_info
# Construct a test case for redispatch
# truck_task = 0
...
...
@@ -318,16 +325,16 @@ class Group:
try
:
# 全智能模式
if
self
.
group_mode
==
1
:
if
self
.
group
.
group
_mode
==
1
:
self
.
logger
.
info
(
"全智能模式调度"
)
self
.
full_dynamic_mode
(
truck_id
,
solver
,
truck_dispatch
,
truck_info
,
truck_task
,
truck_trip
)
# 空车智能模式
elif
self
.
group_mode
==
2
:
elif
self
.
group
.
group
_mode
==
2
:
self
.
logger
.
info
(
"空车智能模式调度"
)
self
.
semi_dynamic_mode
(
truck_id
,
solver
,
truck_dispatch
,
truck_info
,
truck_task
,
truck_trip
)
# 定铲派车
elif
self
.
group_mode
==
3
:
elif
self
.
group
.
group
_mode
==
3
:
self
.
logger
.
info
(
"固定模式调度"
)
try
:
truck_dispatch
[
truck_id
]
=
DispatchInfo
.
get_truck_match
(
truck_id
)
...
...
@@ -336,7 +343,7 @@ class Group:
self
.
logger
.
error
(
es
)
# 分流配比模式
elif
self
.
group_mode
==
4
:
elif
self
.
group
.
group
_mode
==
4
:
self
.
logger
.
info
(
"分流配比模式调度"
)
self
.
ratio_mode
(
truck_id
,
truck_dispatch
,
truck_task
)
...
...
@@ -361,12 +368,12 @@ class Group:
try
:
if
i
in
self
.
truck
.
truck_dump_bind
:
if
i
in
self
.
group
.
truck
.
truck_dump_bind
:
dump_uuid_to_unload_area_uuid_dict
=
get_value
(
"dump_uuid_to_unload_area_uuid_dict"
)
next_unload_area_id
=
dump_uuid_to_unload_area_uuid_dict
[
self
.
truck
.
truck_dump_bind
[
i
]]
next_unload_area_id
=
dump_uuid_to_unload_area_uuid_dict
[
self
.
group
.
truck
.
truck_dump_bind
[
i
]]
else
:
next_unload_area_id
=
DistributionRatio
(
next_exactor_id
,
self
.
truck
)
.
ratio_main
()
next_unload_area_id
=
DistributionRatio
(
next_exactor_id
,
self
.
group
.
truck
)
.
ratio_main
()
except
Exception
as
es
:
...
...
@@ -393,13 +400,13 @@ class Group:
if
truck_task
in
[
-
2
,
3
,
4
,
5
]:
try
:
if
i
in
self
.
truck
.
truck_excavator_bind
:
next_excavator_id
=
self
.
truck
.
truck_excavator_bind
[
i
]
if
i
in
self
.
group
.
truck
.
truck_excavator_bind
:
next_excavator_id
=
self
.
group
.
truck
.
truck_excavator_bind
[
i
]
else
:
next_excavator_value
=
s
.
solve
(
truck_info
)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index
=
np
.
argmin
(
next_excavator_value
)
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
next_excavator_id
=
self
.
group
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
if
truck_task
==
-
2
:
next_unload_area_id
=
"Park"
else
:
...
...
@@ -423,19 +430,19 @@ class Group:
# 车辆停止或者车辆位于卸载区内, 调度车辆前往装载区
if
truck_task
in
[
-
2
,
4
,
5
]:
try
:
if
i
in
self
.
truck
.
truck_excavator_bind
:
if
i
in
self
.
group
.
truck
.
truck_excavator_bind
:
try
:
if
i
not
in
self
.
truck
.
truck_excavator_bind
:
if
i
not
in
self
.
group
.
truck
.
truck_excavator_bind
:
raise
CoreException
(
102
,
f
'truck.excavator bind 中不存在 {i}'
)
except
CoreException
as
es
:
es
.
with_traceback_info
()
self
.
logger
.
error
(
es
)
return
next_excavator_id
=
self
.
truck
.
truck_excavator_bind
[
i
]
next_excavator_id
=
self
.
group
.
truck
.
truck_excavator_bind
[
i
]
else
:
next_excavator_value
=
s
.
solve
(
truck_info
)
min_index
=
np
.
argmin
(
next_excavator_value
)
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
next_excavator_id
=
self
.
group
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
self
.
logger
.
info
(
f
'目标挖机 {min_index} {next_excavator_id}'
)
...
...
@@ -454,28 +461,28 @@ class Group:
try
:
next_excavator_id
=
get_value
(
"excavator_index_to_uuid_dict"
)[
truck_trip
[
-
1
]]
next_unload_area_value
=
s
.
solve
(
truck_info
)
# self.logger.info(f'车辆 {
i
}')
# self.logger.info(f'车辆 {
truck_id
}')
# self.logger.info(f'group distance {self.to_unload_area_distance}')
# self.logger.info(f'walk available {self.group_walk_available}')
#
# self.logger.info(self.unload_area_uuid_index_dict)
# self.logger.info(self.excavator_uuid_index_dict)
if
i
in
self
.
truck
.
truck_dump_bind
:
if
i
in
self
.
group
.
truck
.
truck_dump_bind
:
dump_uuid_to_unload_area_uuid_dict
=
get_value
(
"dump_uuid_to_unload_area_uuid_dict"
)
next_unload_area_id
=
dump_uuid_to_unload_area_uuid_dict
[
self
.
truck
.
truck_dump_bind
[
i
]]
next_unload_area_id
=
dump_uuid_to_unload_area_uuid_dict
[
self
.
group
.
truck
.
truck_dump_bind
[
i
]]
else
:
tmp
=
self
.
group_walk_available
[
self
.
excavator_uuid_index_dict
[
next_excavator_id
],
:]
.
flatten
()
tmp
=
self
.
group
.
group
_walk_available
[
self
.
group
.
excavator_uuid_index_dict
[
next_excavator_id
],
:]
.
flatten
()
# self.logger.info(f'group_walk_available_pick {tmp}')
# self.logger.info(f'next_excavator_id {next_excavator_id}')
# self.logger.info(next_unload_area_value)
next_unload_area_value
*=
self
.
group_walk_available
[
self
.
excavator_uuid_index_dict
[
next_excavator_id
],
:]
.
flatten
()
next_unload_area_value
*=
self
.
group
.
group
_walk_available
[
self
.
group
.
excavator_uuid_index_dict
[
next_excavator_id
],
:]
.
flatten
()
# self.logger.info(next_unload_area_value)
min_index
=
np
.
argmin
(
next_unload_area_value
)
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
min_index
]
next_unload_area_id
=
self
.
group
.
unload_area_uuid_index_dict
.
inverse
[
min_index
]
self
.
logger
.
info
(
f
'目标卸点 {min_index} {next_unload_area_id}'
)
# next_excavator_id = self.excavator_uuid_index_dict.inverse[truck_trip[-1]]
...
...
@@ -489,14 +496,14 @@ class Group:
truck_dispatch
[
i
]
=
[
None
,
None
]
elif
truck_task
==
0
:
try
:
truck_locate
=
self
.
truck
.
get_truck_locate_dict
()[
i
]
truck_locate
=
self
.
group
.
truck
.
get_truck_locate_dict
()[
i
]
except
Exception
as
es
:
self
.
logger
.
error
(
"车辆位置信息丢失"
)
self
.
logger
.
error
(
es
)
self
.
logger
.
info
(
self
.
truck
.
truck_is_temp
)
self
.
logger
.
info
(
self
.
group
.
truck
.
truck_is_temp
)
try
:
truck_is_temp
=
self
.
truck
.
truck_is_temp
[
i
]
truck_is_temp
=
self
.
group
.
truck
.
truck_is_temp
[
i
]
except
Exception
as
es
:
truck_is_temp
=
False
self
.
logger
.
error
(
"车辆临时字段异常"
)
...
...
@@ -505,82 +512,35 @@ class Group:
self
.
logger
.
info
(
"潜在二次调度车辆状态"
)
self
.
logger
.
info
(
f
'车辆 {i}'
)
self
.
logger
.
info
(
f
'车辆位置 {truck_locate}'
)
self
.
logger
.
info
(
f
'车辆状态 {self.truck.truck_current_state[i]}'
)
self
.
logger
.
info
(
f
'车辆状态 {self.
group.
truck.truck_current_state[i]}'
)
self
.
logger
.
info
(
f
'车辆临时 {truck_is_temp} {type(truck_is_temp)}'
)
self
.
logger
.
info
(
self
.
topo
.
cross_bf_lanes
)
self
.
logger
.
info
(
self
.
truck
.
truck_current_state
)
self
.
logger
.
info
(
self
.
group
.
topo
.
cross_bf_lanes
)
self
.
logger
.
info
(
self
.
group
.
truck
.
truck_current_state
)
self
.
logger
.
info
(
truck_is_temp
)
# if (truck_locate in self.topo.cross_bf_lanes) and (self.truck.truck_current_state[
i
] == 2) \
# if (truck_locate in self.topo.cross_bf_lanes) and (self.truck.truck_current_state[
truck_id
] == 2) \
# and (not truck_is_temp):
if
(
truck_locate
in
self
.
topo
.
cross_bf_lanes
)
and
(
self
.
truck
.
truck_current_state
[
i
]
==
2
):
if
(
truck_locate
in
self
.
group
.
topo
.
cross_bf_lanes
)
and
(
self
.
group
.
truck
.
truck_current_state
[
i
]
==
2
):
self
.
logger
.
info
(
"触发二次调度"
)
# 当前绑定卸载区
# 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
self
.
logger
.
info
(
f
'truck_id {i}'
)
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
.
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
,
i
,
load_area_dict
)
next_excavator_id
=
best_excavator_id
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
self
.
logger
.
info
(
f
'二次调度结果 {i}'
)
self
.
logger
.
info
(
truck_dispatch
[
i
])
self
.
redispatch_to_excavator
(
i
,
truck_dispatch
,
truck_locate
)
elif
truck_task
==
3
:
try
:
truck_locate
=
self
.
truck
.
get_truck_locate_dict
()[
i
]
truck_locate
=
self
.
group
.
truck
.
get_truck_locate_dict
()[
i
]
except
Exception
as
es
:
self
.
logger
.
error
(
"车辆位置信息丢失"
)
self
.
logger
.
error
(
es
)
try
:
truck_is_temp
=
self
.
truck
.
truck_is_temp
[
i
]
truck_is_temp
=
self
.
group
.
truck
.
truck_is_temp
[
i
]
except
Exception
as
es
:
truck_is_temp
=
False
self
.
logger
.
error
(
"车辆临时字段异常"
)
self
.
logger
.
error
(
es
)
self
.
logger
.
info
(
f
'车辆位置 {truck_locate}'
)
self
.
logger
.
info
(
f
'车辆状态 {self.truck.truck_current_state[i]}'
)
self
.
logger
.
info
(
f
'车辆状态 {self.
group.
truck.truck_current_state[i]}'
)
self
.
logger
.
info
(
f
'车辆临时 {truck_is_temp} {type(truck_is_temp)}'
)
# 车辆当前位于交叉路口前,且排队等待
if
(
truck_locate
in
self
.
topo
.
cross_bf_lanes
)
and
(
self
.
truck
.
truck_current_state
[
i
]
==
2
)
\
if
(
truck_locate
in
self
.
group
.
topo
.
cross_bf_lanes
)
and
(
self
.
group
.
truck
.
truck_current_state
[
i
]
==
2
)
\
and
(
not
truck_is_temp
):
# 当前绑定装载区
...
...
@@ -597,7 +557,7 @@ class Group:
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
.
topo
.
get_unload_target_node_real
(
truck_locate
,
unload_area_dict
,
unload_area_lane_dict
=
self
.
group
.
topo
.
get_unload_target_node_real
(
truck_locate
,
current_unload_area_id
,
True
)
...
...
@@ -609,11 +569,11 @@ class Group:
# 交叉口下一路段可达的装载区
next_lane_load_area_dict
=
get_lane_reach_load_areas
(
unload_area_lane_dict
,
next_lane_list
)
next_lane_list
)
# 排除下一个路段阻塞的装载区
delete_congestion_load_area
(
congestion_lane_dict
,
unload_area_dict
,
next_lane_load_area_dict
)
next_lane_load_area_dict
)
min_trip_time
=
10000000
best_dump_id
=
current_dump_id
...
...
@@ -626,12 +586,12 @@ class Group:
traveling_time
=
value
[
0
]
/
heavy_speed
now
=
float
(
(
datetime
.
now
()
-
self
.
pre_sch
.
start_time
)
/
timedelta
(
hours
=
0
,
minutes
=
1
,
(
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
.
pre_sch
.
get_dump_avl_time
()[
dump_id
])
-
now
self
.
group
.
pre_sch
.
get_dump_avl_time
()[
dump_id
])
-
now
if
min_trip_time
>
trip_time
:
best_dump_id
=
dump_id
...
...
@@ -640,12 +600,59 @@ class Group:
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
# res = redispatch_request(
i
, 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
'二次调度结果 {i}'
)
self
.
logger
.
info
(
truck_dispatch
[
i
])
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 excavator
...
...
@@ -663,21 +670,21 @@ class Group:
excavator_id
=
DispatchInfo
.
load_excavator_dict
[
load_area
]
else
:
continue
if
value
[
-
1
]
==
1
and
excavator_id
in
self
.
excavator
:
if
value
[
-
1
]
==
1
and
excavator_id
in
self
.
group
.
excavator
:
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
.
pre_sch
.
start_time
)
/
timedelta
(
hours
=
0
,
minutes
=
1
,
seconds
=
0
))
(
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
.
pre_sch
.
get_excavator_avl_time
(
truck_id
=
truck_id
)[
excavator_id
])
-
now
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}'
)
...
...
@@ -693,12 +700,124 @@ class Group:
def
get_congestion_lanes
(
self
):
# 存在车辆拥堵的路段
truck_locate_dict
=
self
.
truck
.
get_truck_locate_dict
()
truck_locate_dict
=
self
.
group
.
truck
.
get_truck_locate_dict
()
congestion_lane_list
=
[]
for
key
,
value
in
truck_locate_dict
.
items
():
if
self
.
truck
.
truck_current_state
[
key
]
==
2
:
if
self
.
group
.
truck
.
truck_current_state
[
key
]
==
2
:
congestion_lane_list
.
append
(
value
)
print
(
"congestion_lane_list"
)
print
(
list
(
set
(
congestion_lane_list
)))
return
list
(
set
(
congestion_lane_list
))
class
ReDispatcher
:
"""
redispatch controller
"""
def
__init__
(
self
,
group
:
Group
):
self
.
logger
=
get_logger
(
"zxt.ReDispatcher"
)
self
.
group
=
group
def
redispatch_to_excavator
(
self
,
truck_id
,
truck_dispatch
,
truck_locate
):
"""
redispatch truck to excavators.
: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 excavator
: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
.
excavator
:
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
))
\ No newline at end of file
core/schedule.py
View file @
c81d437a
...
...
@@ -180,7 +180,7 @@ class PreSchedule:
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.truck_avl_time[int(tmp[
i
][1])] = now
# self.truck_avl_time[int(tmp[
truck_id
][1])] = now
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.excavator_avl_time[excavator_index] = now
...
...
@@ -252,8 +252,8 @@ class PreSchedule:
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.dump_avl_time[dump_index] - now) > 60:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[
i
][1])] - now) > 60:
# self.truck_avl_time[int(tmp[
i
][1])] = now
# if abs(self.truck_avl_time[int(tmp[
truck_id
][1])] - now) > 60:
# self.truck_avl_time[int(tmp[
truck_id
][1])] = now
count
=
0
self
.
logger
.
info
(
"update_dump_avl_time-dump_avl_ls"
)
...
...
core/submit.py
0 → 100644
View file @
c81d437a
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/10/18 12:32
# @Author : Opfer
# @Site :
# @File : submit.py
# @Software: PyCharm
import
json
import
uuid
from
typing
import
List
from
core.group
import
CurrentTruck
,
Group
from
core.util
import
POST
from
data.dispatchInfo
import
DispatchInfo
from
data.para_config
import
get_value
from
equipment
import
DumpInfo
,
ExcavatorInfo
,
TruckInfo
from
graph.topo_graph
import
Topo
from
settings
import
get_logger
,
redis5
from
tables
import
session_mysql
,
DispatchSetting
class
DispatchSubmission
:
""" class for the submission calculated dispatch.
Description:
将调度结果按照指定格式传递到云端机群
Attribute:
"""
def
__init__
(
self
,
dump
:
DumpInfo
,
excavator
:
ExcavatorInfo
,
truck
:
TruckInfo
,
topo
:
Topo
):
self
.
logger
=
get_logger
(
"zxt.submission"
)
self
.
dump
=
dump
self
.
excavator
=
excavator
self
.
truck
=
truck
self
.
topo
=
topo
def
truck_dispatch_to_redis
(
self
,
truck_id
:
str
,
truck_info
:
CurrentTruck
,
dispatch_seq
:
List
[
int
],
group_mode
:
int
):
"""
将truck_id对应矿卡派车计划写入redis
:param group_mode: (int)
:param truck_id: (uuid) 矿卡uuid
:param truck_info: (object)
:param dispatch_seq: (List[int]) 矿卡派车计划
:return: None
"""
self
.
logger
.
info
(
f
'调度车辆编号 {get_value("truck_uuid_to_name_dict")[truck_id]} {truck_id}'
)
self
.
logger
.
info
(
f
'车辆任务 {truck_info.get_task()}'
)
self
.
logger
.
info
(
f
'配对挖机 {dispatch_seq[0]}'
)
self
.
logger
.
info
(
f
'配对卸点 {dispatch_seq[1]}'
)
# try:
if
truck_id
not
in
DispatchInfo
.
truck_group_dict
:
group_id
=
None
self
.
logger
.
error
(
f
'调度结果写入异常-读取矿卡 {truck_id} 所在分组信息异常'
)
else
:
group_id
=
DispatchInfo
.
truck_group_dict
[
truck_id
]
record
=
{
"truckId"
:
truck_id
}
# if group_id is None or DispatchInfo.get_group_mode(group_id) is None:
# group_mode = 3
# self.logger.error("调度模式读取异常-设置为固定派车模式")
# else:
# group_mode = DispatchInfo.get_group_mode(group_id)
self
.
logger
.
info
(
f
'调度模式 {group_mode}'
)
if
group_mode
==
3
:
self
.
logger
.
info
(
"固定派车模式"
)
self
.
fixed_dispatch_mode
(
group_id
,
truck_id
)
else
:
self
.
logger
.
info
(
"动态调度模式"
)
self
.
dynamic_dispatch_mode
(
dispatch_seq
,
group_id
,
record
,
truck_info
.
get_sate
(),
truck_info
.
get_task
(),
truck_id
)
# except Exception as es:
# self.logger.error("调度结果写入异常")
# self.logger.error(f"调度结果:{dispatch_seq}")
# self.logger.error(es)
def
dynamic_dispatch_mode
(
self
,
dispatch_seq
,
group_id
,
record
,
state
,
task
,
truck_id
):
"""
write dispatch plan in dynamic dispatch mode.
:param dispatch_seq:
:param group_id:
:param record:
:param state:
:param task:
:param truck_id:
:return:
"""
if
(
task
in
[
1
,
2
])
or
(
task
==
3
and
state
==
2
):
# 车辆位于装载区,或车辆重载等待
if
task
in
[
1
,
2
]:
self
.
logger
.
info
(
f
'车辆 {truck_id} 装载区调度'
)
else
:
self
.
logger
.
info
(
f
'车辆 {truck_id} 重载二次调度'
)
# 查询车辆相关派车计划 dispatch_seq[next_excavator_id, next_unload_area_id]
if
dispatch_seq
[
1
]
is
None
or
(
dispatch_seq
[
1
]
not
in
DispatchInfo
.
unload_area_dump_dict
):
# 无法查询到目标卸载点
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
else
:
dump_id
=
DispatchInfo
.
unload_area_dump_dict
[
dispatch_seq
[
1
]]
try
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
dump_id
=
dump_id
,
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
if
item
is
None
:
raise
Exception
(
f
'车辆 {truck_id} 无法找到派车计划 {dump_id} {group_id}'
)
if
dispatch_seq
[
0
]
is
None
:
raise
Exception
(
"调度计划挖机与实时监控不匹配"
)
except
Exception
as
es
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
self
.
logger
.
error
(
es
)
# 其余调度信息写入
# try:
record
=
redis_format
(
truck_id
,
group_id
,
str
(
uuid
.
uuid1
()),
item
)
# 车辆重载等待,且前方道路阻塞
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
:
# try:
# if truck_id in self.truck.truck_is_temp and not self.truck.truck_is_temp[truck_id]:
self
.
logger
.
info
(
"二次调度前往卸载区"
)
record
[
"isTemp"
]
=
True
# 避免反复修改
POST
(
truck_id
)
# else:
# self.logger.info("车辆已完成二次调度-无需更改派车计划")
# except Exception as es:
# self.logger.error(es)
# self.logger.error("二次调度失败")
# record["isTemp"] = False
# redis5.set(truck_id, str(json.dumps(record)))
else
:
self
.
logger
.
info
(
"调度前往卸载区"
)
record
[
"isTemp"
]
=
False
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
# self.logger.error("调度结果写入异常-矿卡空载")
elif
(
task
in
[
-
2
,
4
,
5
])
or
(
task
==
0
and
state
==
2
):
# 车辆位于备停区或位于卸载区,或车辆空载等待
if
task
==
-
2
:
self
.
logger
.
info
(
f
'车辆 {truck_id} 备停区调度'
)
elif
task
in
[
4
,
5
]:
self
.
logger
.
info
(
f
'车辆 {truck_id} 卸载区调度'
)
else
:
self
.
logger
.
info
(
f
'车辆 {truck_id} 空载二次调度'
)
# 查询车辆相关派车计划 dispatch_seq[next_excavator_id, next_unload_area_id]
if
dispatch_seq
[
0
]
is
None
:
# 无法查询到目标挖机
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
else
:
excavator_id
=
dispatch_seq
[
0
]
try
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
exactor_id
=
excavator_id
,
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
if
item
is
None
:
raise
Exception
(
f
' 车辆 {truck_id} 无法找到派车计划 {excavator_id} {group_id}'
)
if
dispatch_seq
[
0
]
is
None
:
raise
Exception
(
"调度计划挖机与实时监控不匹配"
)
except
Exception
as
es
:
item
=
(
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
group_id
=
group_id
,
isdeleted
=
0
,
)
.
first
())
self
.
logger
.
error
(
es
)
# 调度信息写入
# try:
record
=
redis_format
(
truck_id
,
group_id
,
str
(
uuid
.
uuid1
()),
item
)
# 车辆重载等待,且前方道路阻塞
if
task
==
0
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
:
# 车辆停车等待
# try:
# if truck_id in self.truck.truck_is_temp and not self.truck.truck_is_temp[truck_id]:
self
.
logger
.
info
(
"二次调度前往装载区"
)
record
[
"isTemp"
]
=
True
# 避免反复修改
POST
(
truck_id
)
# else:
# self.logger.info("车辆已完成二次调度-无需更改派车计划")
# except Exception as es:
# self.logger.error(es)
# self.logger.error("二次调度失败")
# record["isTemp"] = False
# redis5.set(truck_id, str(json.dumps(record)))
else
:
self
.
logger
.
info
(
"调度前往装载区"
)
record
[
"isTemp"
]
=
False
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
# self.logger.error("调度结果写入异常-矿卡重载")
else
:
pass
def
fixed_dispatch_mode
(
self
,
group_id
,
truck_id
):
"""
write dispatch plan in fixed dispatch method.
:param group_id:
:param record:
:param truck_id:
:return:
"""
item
=
session_mysql
.
query
(
DispatchSetting
)
.
filter_by
(
truck_id
=
truck_id
,
isdeleted
=
0
,
)
.
first
()
if
item
is
None
:
self
.
logger
.
error
(
f
'车辆 {truck_id} 无派车计划-无法执行固定派车'
)
return
record
=
redis_format
(
truck_id
,
group_id
,
item
.
id
,
item
)
self
.
logger
.
info
(
f
'redis 注入 {record}'
)
redis5
.
set
(
truck_id
,
str
(
json
.
dumps
(
record
)))
def
group_dispatch_to_redis
(
self
,
group
:
Group
,
dispatch_plan_dict
):
"""
Update the dispatch plan in the group to redis
:param group: (Group)
:param dispatch_plan_dict: (Dict)
:return: None
"""
self
.
logger
.
info
(
f
'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}'
)
self
.
logger
.
info
(
f
'组内车辆 {group.truck_set}'
)
self
.
logger
.
info
(
f
'组内挖机 {group.excavator}'
)
self
.
logger
.
info
(
f
'组内卸点 {group.dump}'
)
self
.
logger
.
info
(
f
'调度模式 {group.group_mode}'
)
self
.
logger
.
info
(
"dispatch_plan_dict"
)
self
.
logger
.
info
(
dispatch_plan_dict
)
print
(
group
.
truck_info_list
)
for
truck_id
,
dispatch_plan
in
dispatch_plan_dict
.
items
():
try
:
self
.
logger
.
info
(
f
'======================================= 调度车辆 ======================================='
)
self
.
truck_dispatch_to_redis
(
truck_id
,
group
.
truck_info_list
[
truck_id
],
dispatch_plan
,
group
.
group_mode
)
self
.
logger
.
info
(
"======================================== 完成写入 ======================================="
)
except
Exception
as
es
:
self
.
logger
.
error
(
"group_dispatch_to_redis_error"
)
self
.
logger
.
error
(
es
)
def
redis_format
(
truck_id
,
group_id
,
dispatch_id
,
item
):
record
=
{
"truckId"
:
truck_id
,
"dispatchId"
:
dispatch_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
[
group_id
]}
return
record
\ No newline at end of file
data/dispatchInfo.py
View file @
c81d437a
...
...
@@ -349,10 +349,10 @@ class DispatchInfo:
# # unload->load distance
# unload_load_distance = np.zeros((len(unload_areas), len(load_areas)))
# for
i
in range(len(unload_areas)):
# for
truck_id
in range(len(unload_areas)):
# for j in range(len(load_areas)):
# distance = int(session_postgre.query(WalkTime).filter_by(unload_area_id=unload_areas[
i
], load_area_id=load_areas[j]).first().to_load_distance)
# unload_load_distance[
i
][j] = distance
# distance = int(session_postgre.query(WalkTime).filter_by(unload_area_id=unload_areas[
truck_id
], load_area_id=load_areas[j]).first().to_load_distance)
# unload_load_distance[
truck_id
][j] = distance
# cls.load_distance[item] = unload_load_distance
...
...
@@ -445,17 +445,17 @@ class DispatchInfo:
# cls.truck_uuid_index_dict = {}
# cls.dump_uuid_index_dict = {}
#
# for
i
in range(len(cls.group_excavator_dict[group_id])):
# cls.excavator_uuid_index_dict[group_id][list(cls.group_excavator_dict[group_id])[
i]] = i
# for
truck_id
in range(len(cls.group_excavator_dict[group_id])):
# cls.excavator_uuid_index_dict[group_id][list(cls.group_excavator_dict[group_id])[
truck_id]] = truck_id
#
# for
i
in range(len(cls.group_unload_area_dict[group_id])):
# cls.unload_area_uuid_index_dict[group_id][list(cls.group_unload_area_dict[group_id])[
i]] = i
# for
truck_id
in range(len(cls.group_unload_area_dict[group_id])):
# cls.unload_area_uuid_index_dict[group_id][list(cls.group_unload_area_dict[group_id])[
truck_id]] = truck_id
#
# for
i
in range(len(cls.group_dump_dict[group_id])):
# cls.dump_uuid_index_dict[group_id][list(cls.group_dump_dict[group_id])[
i]] = i
# for
truck_id
in range(len(cls.group_dump_dict[group_id])):
# cls.dump_uuid_index_dict[group_id][list(cls.group_dump_dict[group_id])[
truck_id]] = truck_id
#
# for
i
in range(len(cls.group_truck_dict[group_id])):
# cls.truck_uuid_index_dict[group_id][list(cls.group_truck_dict[group_id])[
i]] = i
# for
truck_id
in range(len(cls.group_truck_dict[group_id])):
# cls.truck_uuid_index_dict[group_id][list(cls.group_truck_dict[group_id])[
truck_id]] = truck_id
#
# # self.excavator_uuid_index_dict = bidict(DispatchInfo.excavator_uuid_to_index_dict[self.group_id])
# # self.unload_area_uuid_index_dict = bidict(DispatchInfo.unload_area_uuid_to_index_dict[self.group_id])
...
...
@@ -681,7 +681,7 @@ class DispatchInfo:
# @classmethod
# def get_group_road_info(cls,group_id, truck_info):
# if truck_info == 1:
# for
i
in group_excavator():
# for
truck_id
in group_excavator():
# pass
# for j in group_unload_area():
# pass
...
...
equipment/truck.py
View file @
c81d437a
...
...
@@ -148,7 +148,10 @@ class TruckInfo(WalkManage):
# 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
str_to_byte
(
"type"
)
in
key_value_dict
:
device_type
=
int
(
key_value_dict
[
str_to_byte
(
"type"
)])
else
:
continue
if
device_type
==
1
:
if
truck_name_to_uuid_dict
[
item
]
in
self
.
dynamic_truck_set
:
# currentTask = int(key_value_dict[str_to_byte("currentTask")])
...
...
graph/topo_graph.py
View file @
c81d437a
...
...
@@ -163,7 +163,7 @@ class Topo():
# add [start_point, end_point, length, lane_id] to unload_saved_lane
unload_saved_lane
.
append
([
str
(
i_startpoint
),
str
(
i_endpoint
),
float
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
Id
=
i
)
.
first
()
.
Length
),
i
])
# son_lane_num = sum(1 for
i
in session_postgre.query(Lane).filter_by(StartNodeId = i_endpoint).all())
# son_lane_num = sum(1 for
truck_id
in session_postgre.query(Lane).filter_by(StartNodeId = i_endpoint).all())
son_lane_num
=
len
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
StartNodeId
=
i_endpoint
)
.
all
())
# 可以添加的节点:分叉口或终点
...
...
@@ -227,7 +227,7 @@ class Topo():
load_saved_lane
.
append
([
str
(
load_i_startpoint
),
str
(
load_i_endpoint
),
float
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
Id
=
i
)
.
first
()
.
Length
),
i
])
# son_lane_num = sum(1 for
i
in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
# son_lane_num = sum(1 for
truck_id
in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
son_lane_num
=
len
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
StartNodeId
=
load_i_endpoint
)
.
all
())
nodes
=
list
(
self
.
load_G
.
nodes
)
...
...
@@ -239,8 +239,8 @@ class Topo():
lanes
=
{}
for
lane_info
in
load_saved_lane
:
lanes
[
lane_info
[
-
1
]]
=
list
([
lane_info
[
2
],
lane_info
[
2
]])
# lanes.append(
i
[0])
# lanes.append(
i
[1])
# lanes.append(
truck_id
[0])
# lanes.append(
truck_id
[1])
# self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1], real_distance = sum(n[2] for n in load_saved_lane), lane = lanes)
self
.
load_G
.
add_edge
(
load_saved_lane
[
0
][
0
],
load_saved_lane
[
-
1
][
1
],
real_distance
=
sum
(
value
[
0
]
for
value
in
lanes
.
values
()),
...
...
@@ -275,7 +275,7 @@ class Topo():
load_saved_lane
.
append
([
str
(
load_i_startpoint
),
str
(
load_i_endpoint
),
float
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
Id
=
i
)
.
first
()
.
Length
),
i
])
# son_lane_num = sum(1 for
i
in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
# son_lane_num = sum(1 for
truck_id
in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
son_lane_num
=
len
(
session_postgre
.
query
(
Lane
)
.
filter_by
(
StartNodeId
=
load_i_endpoint
)
.
all
())
nodes
=
list
(
self
.
load_G
.
nodes
)
...
...
@@ -287,8 +287,8 @@ class Topo():
lanes
=
{}
for
lane_info
in
load_saved_lane
:
lanes
[
lane_info
[
-
1
]]
=
list
([
lane_info
[
2
],
lane_info
[
2
]])
# lanes.append(
i
[0])
# lanes.append(
i
[1])
# lanes.append(
truck_id
[0])
# lanes.append(
truck_id
[1])
# self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1], real_distance = sum(n[2] for n in load_saved_lane), lane = lanes)
self
.
load_G
.
add_edge
(
load_saved_lane
[
0
][
0
],
load_saved_lane
[
-
1
][
1
],
real_distance
=
sum
(
value
[
0
]
for
value
in
lanes
.
values
()),
...
...
redispatch/redispatch.py
View file @
c81d437a
...
...
@@ -17,7 +17,7 @@ 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
core.
submit
import
DispatchSubmission
from
graph.graph_load
import
graph_construct
config
=
{
...
...
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