Recalculate when the tnc_call_approach_callback is called; remove dtime limit
TODO: Fix incorrect behavior with non-zero speed limitsh137
parent
d824198b94
commit
75a948792e
|
@ -477,23 +477,8 @@ minetest.register_globalstep(function(dtime_mt)
|
|||
advtrains.load()
|
||||
end
|
||||
|
||||
local dtime = GENERATE_ATRICIFIAL_LAG and 0.2 or math.min(dtime_mt, 0.2)
|
||||
--[[if GENERATE_ATRICIFIAL_LAG then
|
||||
dtime = 0.2
|
||||
if os.clock()<t then
|
||||
return
|
||||
end
|
||||
|
||||
t = os.clock()+0.2
|
||||
else
|
||||
--limit dtime: if trains move too far in one step, automation may cause stuck and wrongly braking trains
|
||||
dtime=dtime_mt
|
||||
if dtime>0.2 then
|
||||
atprint("Limiting dtime to 0.2!")
|
||||
dtime=0.2
|
||||
end
|
||||
end ]]
|
||||
|
||||
--local dtime = GENERATE_ATRICIFIAL_LAG and 0.2 or math.min(dtime_mt, 0.2)
|
||||
local dtime = GENERATE_ATRICIFIAL_LAG and 0.2 or dtime_mt
|
||||
advtrains.mainloop_trainlogic(dtime)
|
||||
if advtrains_itm_mainloop then
|
||||
advtrains_itm_mainloop(dtime)
|
||||
|
|
|
@ -113,9 +113,9 @@ function advtrains.lzb_get_limit_by_entry(train, lzb, dtime)
|
|||
if train.index + v0*t + getacc(train,4)*t*t/2 <= i then return 4 end
|
||||
i = advtrains.lzb_get_limit_zone(train, lzb, 3, v0)
|
||||
if train.index + v0*t <= i then return 3 end
|
||||
i = advtrains.path_get_index_by_offset(train, i, params.ZONE_HOLD)
|
||||
i = advtrains.path_get_index_by_offset(train, i, -params.ZONE_HOLD)
|
||||
if train.index + v0*t + getacc(train,2)*t*t/2 <= i then return 2 end
|
||||
i = advtrains.path_get_index_by_offset(train, i, params.ZONE_ROLL)
|
||||
i = advtrains.path_get_index_by_offset(train, i, -params.ZONE_ROLL)
|
||||
if train.index + v0*t + getacc(train,1)*t*t/2 <= i then return 1 end
|
||||
return 0
|
||||
end
|
||||
|
@ -123,39 +123,44 @@ end
|
|||
-- Get next LZB restriction with the lowest speed restriction
|
||||
-- The return values include the LZB entry and the speed limit
|
||||
function advtrains.lzb_get_next(train,dtime)
|
||||
if lever == 4 then return nil end
|
||||
-- if lever == 4 then return nil end
|
||||
local lzb = train.lzb
|
||||
local i = 1
|
||||
local ret
|
||||
local a = advtrains.get_acceleration(train, 3) -- Acceleration
|
||||
local ret, retlimit
|
||||
--local a = advtrains.get_acceleration(train, 3) -- Acceleration
|
||||
local v0 = train.velocity
|
||||
-- Remove LZB entries that are no longer valid
|
||||
while i <= #lzb.oncoming do
|
||||
if lzb.oncoming[i].idx < train.index then
|
||||
-- The entry is no longer valid and should be removed
|
||||
local ent = lzb.oncoming[i]
|
||||
if ent.fun then
|
||||
ent.fun(ent.pos, id, train, ent.idx, ent.spd, lzb.data)
|
||||
end
|
||||
table.remove(lzb.oncoming, i)
|
||||
-- This should (hopefully) be faster than table.remove(lzb.oncoming, i)
|
||||
if i == #lzb.oncoming then
|
||||
lzb.oncoming[i] = nil
|
||||
else
|
||||
lzb.oncoming[i] = lzb.oncoming[#lzb.oncoming]
|
||||
lzb.oncoming[#lzb.oncoming] = nil
|
||||
end
|
||||
else
|
||||
-- Check for the speed requirement from this LZB entry instead of putting it into another loop
|
||||
local it = lzb.oncoming[i]
|
||||
local v1 = it.spd
|
||||
if v1 and v1 <= 0 then
|
||||
if not ret then ret = it
|
||||
else
|
||||
local curlimit = advtrains.lzb_get_limit_by_entry(train, it, dtime)
|
||||
if retlimit and retlimit > curlimit then ret = it
|
||||
elseif retlimit == curlimit and it.idx < ret.idx then ret = it
|
||||
end
|
||||
end
|
||||
retlimit = advtrains.lzb_get_limit_by_entry(train, ret, dtime)
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
-- Now run through all the LZB entries and find the one with the lowest speed requirement
|
||||
for _, it in ipairs(lzb.oncoming) do
|
||||
local v1 = it.spd
|
||||
if v1 and v1 <= v0 then
|
||||
if not ret then ret = it
|
||||
else
|
||||
local retlimit = advtrains.lzb_get_limit_by_entry(train,ret,dtime)
|
||||
local curlimit = advtrains.lzb_get_limit_by_entry(train,ret,dtime)
|
||||
if retlimit and retlimit > curlimit then ret=it
|
||||
elseif retlimit == curlimit and it.idx < ret.idx then ret=it
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return ret,advtrains.lzb_get_limit_by_entry(train, ret,dtime)
|
||||
return ret, retlimit
|
||||
end
|
||||
|
||||
local function invalidate(train)
|
||||
|
|
|
@ -191,8 +191,9 @@ local function assertdef(tbl, var, def)
|
|||
end
|
||||
|
||||
function advtrains.get_acceleration(train, lever)
|
||||
local acc_all = t_accel_all[lever]
|
||||
local acc_eng = t_accel_eng[lever]
|
||||
local lvr = lever or train.lever
|
||||
local acc_all = t_accel_all[lvr] or -3 -- assume braking to avoid problems
|
||||
local acc_eng = t_accel_eng[lvr] or 0
|
||||
local nwagons = #train.trainparts
|
||||
if nwagons == 0 then
|
||||
-- empty train! avoid division through zero
|
||||
|
@ -364,24 +365,8 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
if train.ctrl.user then
|
||||
advtrains.atc.train_reset_command(train)
|
||||
else
|
||||
local braketar = train.atc_brake_target
|
||||
local emerg = false -- atc_brake_target==-1 means emergency brake (BB command)
|
||||
if braketar == -1 then
|
||||
braketar = 0
|
||||
emerg = true
|
||||
end
|
||||
--[[
|
||||
if braketar and braketar>=trainvelocity then
|
||||
train.atc_brake_target=nil
|
||||
braketar = nil
|
||||
end
|
||||
]]
|
||||
--if train.tarvelocity and train.velocity==train.tarvelocity then
|
||||
-- train.tarvelocity = nil
|
||||
--end
|
||||
--[[
|
||||
if train.atc_wait_finish then
|
||||
if not train.atc_brake_target and (not train.tarvelocity or train.velocity==train.tarvelocity) then
|
||||
if (not train.ctrl.atc) or (train.ctrl.atc<3 and train.tarvelocity>=train.velocity) or (train.ctrl.atc==3) or (train.ctrl.atc>3 and train.velocity>=train.tarvelocity) then
|
||||
train.atc_wait_finish=nil
|
||||
end
|
||||
end
|
||||
|
@ -394,8 +379,12 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
elseif train.atc_delay then
|
||||
train.atc_delay = nil
|
||||
end
|
||||
]]
|
||||
|
||||
local braketar = train.atc_brake_target
|
||||
local emerg = false -- atc_brake_target==-1 means emergency brake (BB command)
|
||||
if braketar == -1 then
|
||||
braketar = 0
|
||||
emerg = true
|
||||
end
|
||||
train.ctrl.atc = nil
|
||||
if train.tarvelocity then train.ctrl.atc = 3 end
|
||||
if train.tarvelocity and train.tarvelocity>trainvelocity then
|
||||
|
@ -412,20 +401,6 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
train.ctrl.atc=2
|
||||
end
|
||||
end
|
||||
if train.atc_wait_finish then
|
||||
if (not train.ctrl.atc) or (train.ctrl.atc<3 and train.tarvelocity>=train.velocity) or (train.ctrl.atc==3) or (train.ctrl.atc>3 and train.velocity>=train.tarvelocity) then
|
||||
train.atc_wait_finish=nil
|
||||
end
|
||||
end
|
||||
if train.atc_command then
|
||||
if (not train.atc_delay or train.atc_delay<=0) and not train.atc_wait_finish then
|
||||
advtrains.atc.execute_atc_command(id, train)
|
||||
else
|
||||
train.atc_delay=train.atc_delay-dtime
|
||||
end
|
||||
elseif train.atc_delay then
|
||||
train.atc_delay = nil
|
||||
end
|
||||
end
|
||||
|
||||
--if tarvel_cap and train.tarvelocity and tarvel_cap<train.tarvelocity then
|
||||
|
@ -452,8 +427,9 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
local a = advtrains.get_acceleration(train, tmp_lever)
|
||||
local v0 = train.velocity
|
||||
local v1 = a*dtime+v0
|
||||
v1 = math.min(v1, (tarvel_cap or train.max_speed or 10))
|
||||
v1 = math.min(v1, train.max_speed or 10)
|
||||
v1 = math.max(v1, 0)
|
||||
if tarvel_cap then v1 = math.min(v1, tarvel_cap) end
|
||||
if tmp_lever == 4 and train.tarvelocity then v1=math.min(train.tarvelocity,v1) end
|
||||
local s
|
||||
if a == 0 then s = v1*dtime
|
||||
|
@ -464,16 +440,35 @@ function advtrains.train_step_b(id, train, dtime)
|
|||
end
|
||||
s = math.max(s,0)
|
||||
--- 4b. Move train and update train properties ---
|
||||
local idx_floor = math.floor(train.index)
|
||||
local pdist = train.path_dist[idx_floor+1] - train.path_dist[idx_floor]
|
||||
local distance = pdist == 0 and s or s / pdist
|
||||
train.lever = tmp_lever
|
||||
train.velocity = v1
|
||||
train.acceleration = a==0 and 0 or (v1-v0)/dtime
|
||||
local idx_floor = math.floor(train.index)
|
||||
local pdist
|
||||
if train.path_dist[idx_floor+1] and train.path_dist[idx_floor] then
|
||||
pdist = train.path_dist[idx_floor+1] - train.path_dist[idx_floor]
|
||||
else
|
||||
local lifloor
|
||||
if train.lastcalc then lifloor = math.floor(train.lastcalc.index) end
|
||||
if lifloor and train.path_dist[lifloor+1] and train.path_dist[lifloor] then
|
||||
pdist = train.path_dist[lifloor+1] - train.path_dist[lifloor]
|
||||
else
|
||||
pdist = 1
|
||||
end
|
||||
end
|
||||
local distance = pdist > 0 and s/pdist or s
|
||||
|
||||
--debugging code
|
||||
--train.debug = atdump(train.ctrl).."step_dist: "..math.floor(distance*1000)
|
||||
|
||||
train.lastcalc = {
|
||||
["index"] = train.index,
|
||||
["v0"] = v0,
|
||||
["v1"] = v1,
|
||||
["lever"] = tmp_lever,
|
||||
["t"] = dtime,
|
||||
["trainparts"] = trainparts,
|
||||
}
|
||||
train.index=train.index+distance
|
||||
|
||||
recalc_end_index(train)
|
||||
|
@ -579,6 +574,56 @@ function advtrains.train_step_c(id, train, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
local function recalc_train_index(id, train, index)
|
||||
-- check for necessary data
|
||||
if not train.lastcalc then return end
|
||||
|
||||
local trainparts = train.lastcalc.trainparts
|
||||
local last_index = train.lastcalc.index
|
||||
local last_v0 = train.lastcalc.v0
|
||||
local last_v1 = train.lastcalc.v1
|
||||
local last_lever = train.lastcalc.lever
|
||||
local last_t = train.lastcalc.t
|
||||
local last_acc = advtrains.get_acceleration(train, last_lever)
|
||||
local v0 -- Since we are recalculating, the speed when the train reached here would become v0
|
||||
local idiff = index - last_index
|
||||
local time_to_here, t
|
||||
|
||||
if train.trainparts~=trainparts then return end
|
||||
|
||||
local sa
|
||||
if last_acc==0 then
|
||||
sa = 0
|
||||
else
|
||||
sa = (last_v1*last_v1 - last_v0*last_v0)/2/last_acc
|
||||
end
|
||||
if idiff <= 0 then return end
|
||||
if sa < 0 then return end
|
||||
if idiff < sa then
|
||||
-- v = sqrt(v0^2+2*s*a)
|
||||
local v0sq = last_v0*last_v0+2*idiff*last_acc
|
||||
if v0sq<0 then return end
|
||||
v0 = math.sqrt(v0sq)
|
||||
time_to_here = (last_v1-last_v0)/last_acc
|
||||
else
|
||||
v0 = last_v1
|
||||
if last_acc == 0 then
|
||||
time_to_here = 0
|
||||
else
|
||||
time_to_here = (last_v1-last_v0)/last_acc
|
||||
end
|
||||
if v0~=0 then time_to_here = time_to_here + (idiff-sa)/last_v1 end
|
||||
end
|
||||
|
||||
t = last_t - time_to_here
|
||||
if t<0 then return end
|
||||
train.index = index
|
||||
train.velocity = v0
|
||||
train.acceleration = advtrains.get_acceleration(train)
|
||||
|
||||
advtrains.train_step_b(id, train, t)
|
||||
end
|
||||
|
||||
-- Default occupation callbacks for node callbacks
|
||||
-- (remember, train.end_index is set separately because callbacks are
|
||||
-- asserted to rely on this)
|
||||
|
|
Loading…
Reference in New Issue