forked from huuhghhgyg/Container-Terminal-Simulation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathagent.lua
140 lines (121 loc) · 4.88 KB
/
agent.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
function Agent()
local agent = {
speed = {1, 1, 1},
model = nil,
pos = {0, 0, 0}, -- Agent位置,只有init更新,相当于每个任务的Origin
taskstart = nil,
tasks = {},
tasksequence = {},
state = 'idle'
}
agent.type = 'agent'
agent.id = agent.model ~= nil and agent.model.id or nil
agent.timeError = 10e-8 -- 允许的计算时间误差范围
agent.lastpos = agent.pos -- 初始化任务初始位置
-- 原生函数
function agent:setpos(x, y, z)
agent.model:setpos(x, y, z)
end
function agent:delete()
agent.model:delete()
end
-- 任务相关函数
function agent:addtask(name, params)
table.insert(agent.tasksequence, {name, params})
-- 如果是空闲状态,立刻执行
if agent.state ~= 'running' then
agent.state = 'running'
agent.taskstart = coroutine.qtime() -- 记录任务开始时间
print('[' .. agent.type .. agent.id .. '] started at', coroutine.qtime())
coroutine.queue(0, agent.execute, agent)
end
end
function agent:deltask()
-- print('[' .. agent.type .. tostring(agent.id) .. '] 删除任务', agent.tasksequence[1][1], 'at',
-- coroutine.qtime())
table.remove(agent.tasksequence, 1)
-- 如果任务队列为空,进入空闲状态
if #agent.tasksequence == 0 then
agent.state = 'idle'
agent.taskstart = nil
print('[' .. agent.type .. agent.id .. '] stopped at', coroutine.qtime())
return
end
-- 任务推进
-- print('[' .. agent.type .. tostring(agent.id) .. '] 任务:', agent.tasksequence[1][1], 'at', coroutine.qtime())
agent.taskstart = coroutine.qtime()
coroutine.queue(0, agent.execute, agent)
end
-- 更新任务和事件
function agent:execute()
-- 判断任务队列长度
if #agent.tasksequence == 0 then
return
end
local taskname, params = table.unpack(agent.tasksequence[1])
-- 参数验证
if agent.tasks[taskname] == nil then
print(debug.traceback('错误,没有找到任务'))
os.exit()
end
if agent.taskstart == nil then
print(debug.traceback('[' .. agent.type .. agent.id .. '] 错误,任务开始时间为空'))
os.exit()
end
local dt = coroutine.qtime() - agent.taskstart -- 计算仿真时间差
-- 检查任务初始化
if params == nil then
params = {}
end
if not params.init then
agent.taskstart = coroutine.qtime()
if agent.tasks[taskname].init ~= nil then
agent.tasks[taskname].init(params)
end
end
-- 执行刷新。如果任务结束,删除任务
if agent.tasks[taskname].execute ~= nil then
agent.tasks[taskname].execute(dt, params)
end
-- 检测时间推进
if params.dt ~= nil and dt - params.dt > agent.timeError then -- 如果误差时间大于允许计算误差
print(agent.type .. agent.id .. '任务' .. taskname .. '时间推进异常 at ' .. coroutine.qtime())
print('任务预计params.dt=', params.dt, '实际输入dt=', dt, '时间差异=', dt - params.dt)
print(debug.traceback())
os.exit()
end
end
-- params = {x, y, z, ...}
agent.tasks.move2 = {
init = function(params)
print('init move2 at', coroutine.qtime())
local px, py, pz = agent.model:getpos()
agent.lastpos = {px, py, pz}
params.est, params.delta, params.vecE = {}, {}, {}
-- 计算坐标
for i = 1, 3 do
params.delta[i] = params[i] - agent.lastpos[i]
params.vecE[i] = params.delta[i] == 0 and 0 or params.delta[i] / math.abs(params.delta[i])
params.est[i] = params.delta[i] == 0 and 0 or math.abs(params.delta[i]) / agent.speed[i]
end
params.dt = math.max(table.unpack(params.est)) -- 任务所需时间
params.init = true -- 标记完成初始化
coroutine.queue(params.dt, agent.execute, agent) -- 结束时间唤醒execute
end,
execute = function(dt, params)
-- 计算坐标
local position = {table.unpack(agent.lastpos)}
for i = 1, 3 do
position[i] = dt <= params.est[i] and agent.lastpos[i] + agent.speed[i] * dt * params.vecE[i] or
params[i]
end
-- 设置位置
agent:setpos(table.unpack(position))
if dt == params.dt then
agent.pos = position -- 更新位置
agent:deltask() -- 删除任务
end
end
}
return agent
end