Gabriel Pérez-Cerezo 2019-12-01 12:09:04 +01:00
commit 0518fbbf3a
5 changed files with 55 additions and 125 deletions

View File

@ -85,9 +85,9 @@ end
--[[ --[[
Distance needed to accelerate from v0 to v1 with constant acceleration a: Distance needed to accelerate from v0 to v1 with constant acceleration a:
v1 - v0 a / v1 - v0 \ 2 v1 - v0 a / v1 - v0 \ 2 v1^2 - v0^2
s = v0 * ------- + - * | ------- | s = v0 * ------- + - * | ------- | = -----------
a 2 \ a / a 2 \ a / 2*a
]] ]]
local function apply_control(id, train) local function apply_control(id, train)
@ -112,8 +112,7 @@ local function apply_control(id, train)
local v0 = train.velocity local v0 = train.velocity
local v1 = it.spd local v1 = it.spd
if v1 and v1 <= v0 then if v1 and v1 <= v0 then
local f = (v1-v0) / a local s = (v1*v1 - v0*v0) / (2*a)
local s = v0*f + a*f*f/2
local st = s + params.ADD_SLOW local st = s + params.ADD_SLOW
if v0 > 3 then if v0 > 3 then

View File

@ -1,48 +1,7 @@
-- occupation.lua -- occupation.lua
--[[ --[[
Collects and manages positions where trains occupy and/or reserve/require space Collects and manages positions where trains occupy and/or reserve/require space
THIS SECTION ABOVE IS OUTDATED, look below
Zone diagram of a train:
|___| |___| --> Direction of travel
oo oo+oo oo
=|=======|===|===========|===|=======|===================|========|===
|SafetyB|CpB| Train |CpF|SafetyF| Brake |Aware |
[1] [2] [3] [4] [5] [6] [7] [8]
ID|Name |Desc
0 Free Zone that was occupied before, which has now been left
1 Train Zone where the train actually is.
2 SafetyB Safety zone behind the train. extends 4m
3 SafetyF Safety zone in front of the train. extends 4m
If a train is about to enter this zone, immediately brake it down to 2
4 CpB Backside coupling zone. If the coupling zones of 2 trains overlap, they can be coupled
5 CpF Frontside coupling zone
6 Brake Brake distance of the train. Extends to the point ~5 nodes in front
of the point where the train would stop if it would regularily brake now.
7 Aware Awareness zone. Extends 10-20 nodes beyond the Brake zone
Whenever any of the non-aware zones of other trains are detected here, the train will start to brake.
Table format:
occ[y][x][z] = {
[1] = train 1 id
[2] = train 1 ZoneID
// [3] = entry seqnum*
...
[2n-1] = train n id
[2n ] = train n ZoneID
// [3n-2] = train n id
// [3n-1] = train n ZoneID
// [3n ] = entry seqnum*
}
occ_chg[n] = {
pos = vector,
train_id,
old_val, (0 when entry did not exist before)
new_val, (0 when entry was deleted)
}
---------------------
It turned out that, especially for the TSS, some more, even overlapping zones are required. It turned out that, especially for the TSS, some more, even overlapping zones are required.
Packing those into a data structure would just become a huge mess! Packing those into a data structure would just become a huge mess!
Instead, this occupation system will store the path indices of positions in the corresponding. Instead, this occupation system will store the path indices of positions in the corresponding.

View File

@ -703,40 +703,6 @@ advtrains.te_register_on_remove(function(id, train)
--atdebug(id,"tnc remove",train.index,train.end_index) --atdebug(id,"tnc remove",train.index,train.end_index)
end) end)
-- Calculates the indices where the window borders of the occupation windows are.
-- TODO adapt this code to new system, probably into a callback (probably only the brake distance code is needed)
local function calc_occwindows(id, train)
local end_index = advtrains.path_get_index_by_offset(train, train.index, -train.trainlen)
train.end_index = end_index
local cpl_b = end_index - COUPLE_ZONE
local safety_b = advtrains.path_get_index_by_offset(train, cpl_b, -SAFETY_ZONE)
local cpl_f = end_index + COUPLE_ZONE
local safety_f = advtrains.path_get_index_by_offset(train, cpl_f, SAFETY_ZONE)
-- calculate brake distance
local acc_all = t_accel_all[1]
local acc_eng = t_accel_eng[1]
local nwagons = #train.trainparts
local acc = acc_all + (acc_eng*train.locomotives_in_train)/nwagons
local vel = train.velocity
local brakedst = (vel*vel) / (2*acc)
local brake_i = math.max(advtrains.path_get_index_by_offset(train, train.index, brakedst + BRAKE_SPACE), safety_f)
local aware_i = advtrains.path_get_index_by_offset(train, brake_i, AWARE_ZONE)
return {
safety_b,
cpl_b,
end_index,
train.index,
cpl_f,
safety_f,
brake_i,
aware_i,
}
end
--returns new id --returns new id
function advtrains.create_new_train_at(pos, connid, ioff, trainparts) function advtrains.create_new_train_at(pos, connid, ioff, trainparts)
local new_id=advtrains.random_id() local new_id=advtrains.random_id()
@ -985,6 +951,7 @@ function advtrains.train_check_couples(train)
if not train.cpl_front then if not train.cpl_front then
-- recheck front couple -- recheck front couple
local front_trains, pos = advtrains.occ.get_occupations(train, atround(train.index) + CPL_CHK_DST) local front_trains, pos = advtrains.occ.get_occupations(train, atround(train.index) + CPL_CHK_DST)
if minetest.get_node_or_nil(pos) then -- if the position is loaded...
for tid, idx in pairs(front_trains) do for tid, idx in pairs(front_trains) do
local other_train = advtrains.trains[tid] local other_train = advtrains.trains[tid]
if not advtrains.train_ensure_init(tid, other_train) then if not advtrains.train_ensure_init(tid, other_train) then
@ -1004,6 +971,7 @@ function advtrains.train_check_couples(train)
end end
end end
end end
end
if train.cpl_back then if train.cpl_back then
if not train.cpl_back:getyaw() then if not train.cpl_back:getyaw() then
-- objectref is no longer valid. reset. -- objectref is no longer valid. reset.
@ -1013,6 +981,7 @@ function advtrains.train_check_couples(train)
if not train.cpl_back then if not train.cpl_back then
-- recheck back couple -- recheck back couple
local back_trains, pos = advtrains.occ.get_occupations(train, atround(train.end_index) - CPL_CHK_DST) local back_trains, pos = advtrains.occ.get_occupations(train, atround(train.end_index) - CPL_CHK_DST)
if minetest.get_node_or_nil(pos) then -- if the position is loaded...
for tid, idx in pairs(back_trains) do for tid, idx in pairs(back_trains) do
local other_train = advtrains.trains[tid] local other_train = advtrains.trains[tid]
if not advtrains.train_ensure_init(tid, other_train) then if not advtrains.train_ensure_init(tid, other_train) then
@ -1031,6 +1000,7 @@ function advtrains.train_check_couples(train)
end end
end end
end end
end
end end
function advtrains.couple_invalidate(train) function advtrains.couple_invalidate(train)

View File

@ -432,17 +432,10 @@ function wagon:on_step(dtime)
end end
end end
if collides then if collides then
if self.collision_count and self.collision_count>10 then -- screw collision mercy
--enable collision mercy to get trains stuck in walls out of walls
--actually do nothing except limiting the velocity to 1
train.velocity=math.min(train.velocity, 1)
else
train.recently_collided_with_env=true train.recently_collided_with_env=true
train.velocity=0 train.velocity=0
self.collision_count=(self.collision_count or 0)+1 advtrains.atc.train_reset_command(train)
end
else
self.collision_count=nil
end end
end end

View File

@ -5,6 +5,9 @@ else
S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
end end
-- length of the steam engine loop sound
local SND_LOOP_LEN = 5
advtrains.register_wagon("newlocomotive", { advtrains.register_wagon("newlocomotive", {
mesh="advtrains_engine_steam.b3d", mesh="advtrains_engine_steam.b3d",
textures = {"advtrains_engine_steam.png"}, textures = {"advtrains_engine_steam.png"},
@ -111,13 +114,19 @@ advtrains.register_wagon("detailed_steam_engine", {
self.object:set_animation({x=1,y=80}, advtrains.abs_ceil(velocity)*15, 0, true) self.object:set_animation({x=1,y=80}, advtrains.abs_ceil(velocity)*15, 0, true)
self.old_anim_velocity=advtrains.abs_ceil(velocity) self.old_anim_velocity=advtrains.abs_ceil(velocity)
end end
if velocity > 0 and not self.sound_loop_handle then end,
self.sound_loop_handle = minetest.sound_play({name="advtrains_steam_loop", gain=2}, {object = self.object, loop=true}) custom_on_step=function(self, dtime)
elseif velocity==0 then if self:train().velocity > 0 then -- First make sure that the train isn't standing
if self.sound_loop_handle then if not self.sound_loop_tmr or self.sound_loop_tmr <= 0 then
minetest.sound_stop(self.sound_loop_handle) -- start the sound if it was never started or has expired
self.sound_loop_handle = nil self.sound_loop_handle = minetest.sound_play({name="advtrains_steam_loop", gain=2}, {object=self.object})
self.sound_loop_tmr = SND_LOOP_LEN
end end
--decrease the sound timer
self.sound_loop_tmr = self.sound_loop_tmr - dtime
else
-- If the train is standing, the sound will be stopped in some time. We do not need to interfere with it.
self.sound_loop_tmr = nil
end end
end, end,
custom_on_activate = function(self, staticdata_table, dtime_s) custom_on_activate = function(self, staticdata_table, dtime_s)