mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
367 lines
12 KiB
Lua
367 lines
12 KiB
Lua
--------------------------------------------------------------------------------
|
||
-- АРС-АЛС (модифицированная версия для составов Еж)
|
||
--------------------------------------------------------------------------------
|
||
Metrostroi.DefineSystem("ARS_EZh3")
|
||
TRAIN_SYSTEM.DontAccelerateSimulation = true
|
||
|
||
function TRAIN_SYSTEM:Initialize()
|
||
self.Train:LoadSystem("ALSCoil")
|
||
self.Train:LoadSystem("EPKContacts","Relay","",{close_time = 3})
|
||
self.Alarm = false
|
||
-- Internal state
|
||
self.SpeedLimit = 0
|
||
self.NextLimit = 0
|
||
self.Ring = false
|
||
self.Overspeed = false
|
||
self.ElectricBrake = false
|
||
self.PneumaticBrake1 = false
|
||
self.PneumaticBrake2 = true
|
||
self.AttentionPedal = false
|
||
self.KVT = false
|
||
self.LN = false
|
||
self.IgnoreThisARS = false
|
||
|
||
-- ARS wires
|
||
self["33D"] = 0
|
||
self["33G"] = 0
|
||
self["33Zh"] = 0
|
||
self["2"] = 0
|
||
self["6"] = 0
|
||
self["8"] = 0
|
||
self["20"] = 0
|
||
--self["21"] = 0
|
||
self["29"] = 0
|
||
self["31"] = 0
|
||
self["32"] = 0
|
||
|
||
-- Lamps
|
||
---self.LKT = false
|
||
self.LVD = false
|
||
end
|
||
|
||
function TRAIN_SYSTEM:Outputs()
|
||
return { "2", "8", "20", "29", "33D", "33G", "33Zh",--"31", "32",
|
||
"Speed", "SpeedLimit", "Ring"}
|
||
end
|
||
|
||
function TRAIN_SYSTEM:Inputs()
|
||
return { "IgnoreThisARS","AttentionPedal","Ring" }
|
||
end
|
||
|
||
function TRAIN_SYSTEM:TriggerInput(name,value)
|
||
local Train = self.Train
|
||
if name == "AttentionPedal" then
|
||
self.AttentionPedal = value > 0.5
|
||
if Train and Train.PB then
|
||
Train.PB:TriggerInput("Set",value)
|
||
end
|
||
end
|
||
if name == "IgnoreThisARS" then
|
||
self.IgnoreThisARS = value > 0.5
|
||
end
|
||
if name == "Ring" then
|
||
self.RingOverride = value > 0.5
|
||
end
|
||
end
|
||
|
||
|
||
|
||
function TRAIN_SYSTEM:Think(dT)
|
||
local Train = self.Train
|
||
local ALS = Train.ALSCoil
|
||
local speed = ALS.Speed
|
||
--if GetConVarNumber("metrostroi_ars_printnext") == Train:EntIndex() then print(Train:ReadCell(49165)) end
|
||
|
||
|
||
-- ALS, ARS state
|
||
local power = Train.VB.Value > 0
|
||
local KRUEnabled = Train.KRU and Train.KRU["14/1-B3"] > 0
|
||
local RVForward = power and (Train.KV["D4-15"] > 0 or KRUEnabled)
|
||
local EnableARS = Train.VB.Value == 1.0 and Train.ARS.Value == 1.0 and RVForward
|
||
local EnableALS = Train.VB.Value == 1.0 and Train.ALS.Value == 1.0 and RVForward
|
||
if EnableALS ~= (ALS.Enabled==1) then
|
||
ALS:TriggerInput("Enable",EnableALS and 1 or 0)
|
||
end
|
||
|
||
self.EnableARS = EnableARS
|
||
self.EnableALS = EnableALS
|
||
local EPKActivated = Train.EPK and Train.EPK.Value > 0.5 and Train.DriverValveBLDisconnect.Value > 0.5
|
||
-- Pedal state
|
||
local PB = Train.PB.Value > 0.5 or Train.KB.Value > 0.5
|
||
self.KVT = Train.KVT.Value > 0.5
|
||
if PB and not self.AttentionPedal then
|
||
self.AttentionPedal = true
|
||
end
|
||
if not PB and self.AttentionPedal then
|
||
self.AttentionPedal = false
|
||
end
|
||
|
||
-- Ignore pedal
|
||
if self.IgnorePedal and self.AttentionPedal then
|
||
self.AttentionPedal = false
|
||
else
|
||
self.IgnorePedal = false
|
||
end
|
||
-- Speed check and update speed data
|
||
if CurTime() - (self.LastSpeedCheck or 0) > 0.5 then
|
||
self.LastSpeedCheck = CurTime()
|
||
--self.Speed = (Train.Speed or 0) --FIXME
|
||
end
|
||
--if RVForward then
|
||
self.NoFreq = ALS.NoFreq
|
||
self.F1 = ALS.F1*(1-self.NoFreq)
|
||
self.F2 = ALS.F2*(1-self.NoFreq)
|
||
self.F3 = ALS.F3*(1-self.NoFreq)
|
||
self.F4 = ALS.F4*(1-self.NoFreq)
|
||
self.F5 = ALS.F5*(1-self.NoFreq)
|
||
self.F6 = ALS.F6*(1-self.NoFreq)
|
||
self.RealF5 = self.F5*(1-(self.F4+self.F3+self.F2+self.F1))
|
||
if EnableARS then self.NoFreq = self.NoFreq + (1-math.min(1,self.F5+self.F4+self.F3+self.F2+self.F1+self.NoFreq)) end
|
||
--end
|
||
|
||
|
||
if EnableALS then
|
||
local V = math.floor(speed +0.05)
|
||
local Vlimit = 20
|
||
local VLimit2
|
||
if self.F4 > 0 then Vlimit = 40 end
|
||
if self.F3 > 0 then Vlimit = 60 end
|
||
if self.F2 > 0 then Vlimit = 70 end
|
||
if self.F1 > 0 then Vlimit = 80 end
|
||
|
||
--if ( self.KVT) and (Vlimit ~= 0) and (V > Vlimit) then self.Overspeed = true end
|
||
--if ( self.KVT) and (Vlimit == 0) and (V > 20) then self.Overspeed = true end
|
||
--if (not self.KVT) and (V > Vlimit) and (V > (self.RealNoFreq and 0 or 3)) then self.Overspeed = true end
|
||
--if ( self.KVT) and (Vlimit == 0) and self.Train.ARSType and self.Train.ARSType == 3 and not self.Train["PA-KSD"].VRD then self.Overspeed = true end
|
||
--self.Ring = self.Overspeed and (speed > 5)
|
||
|
||
-- Determine next limit and current limit
|
||
self.SpeedLimit = VLimit2 or Vlimit--+0.5
|
||
else
|
||
local V = math.floor(speed +0.05)
|
||
self.SpeedLimit = 0
|
||
end
|
||
|
||
|
||
if EnableARS then
|
||
if self.EnableARS ~= EnableARS then Train.EPKContacts:TriggerInput("Set",Train.EPKContacts.Value) end
|
||
local SpeedLimit = self.SpeedLimit
|
||
if self.AttentionPedal then SpeedLimit = 20 end
|
||
|
||
-- Check absolute stop
|
||
if self.NoFreq > 0 and not self.PrevNoFreq then --and Train:ReadTrainWire(6) < 1 then
|
||
self.IgnorePedal = true
|
||
end
|
||
if self.F5 > 0 and not self.PrevF5 then --and Train:ReadTrainWire(6) < 1 then
|
||
self.IgnorePedal = self.PrevNoFreq
|
||
end
|
||
self.PrevNoFreq = self.NoFreq > 0
|
||
self.PrevF5 = self.F5 > 0
|
||
-- Check overspeed
|
||
if speed > SpeedLimit and not self.ElectricBrake then
|
||
self.ElectricBrake = true
|
||
self.BSpeedLimit = SpeedLimit
|
||
self.RVV = nil
|
||
end
|
||
if self.BSpeedLimit and speed < self.BSpeedLimit-4 and self.ElectricBrake and not self.ARSBrake then
|
||
self.ElectricBrake = false
|
||
self.RVV = CurTime()
|
||
end
|
||
if self.RVV and CurTime()-self.RVV > 8 then
|
||
self.ARSBrake = true
|
||
self.ElectricBrake = true
|
||
self.RVV = nil
|
||
end
|
||
if speed < SpeedLimit and self.ElectricBrake and not self.ARSBrake and self.KVT then
|
||
self.RVV = nil
|
||
self.ElectricBrake = false
|
||
end
|
||
if self.KVT and self.RVV then
|
||
self.RVV = nil
|
||
end
|
||
|
||
if self.BSpeedLimit and SpeedLimit < self.BSpeedLimit then self.BSpeedLimit = SpeedLimit end
|
||
|
||
if (not self.BSpeedLimit or speed < self.BSpeedLimit) and self.ElectricBrake and self.KVT then
|
||
self.ARSBrake = false
|
||
self.ElectricBrake = false
|
||
self.PneumaticBrake2 = false
|
||
end
|
||
if (Train.KV["10AS-33"] > 0 and self.AntiRolling or Train:ReadTrainWire(31)> 0 or Train:ReadTrainWire(32) > 0 or Train:ReadTrainWire(12) > 0) and speed < 10 then
|
||
self.AntiRolling = false
|
||
self.RO = true
|
||
self.ROBlock = Train.KV["10AS-33"] > 0
|
||
end
|
||
if self.ROBlock and Train.KV["10AS-33"] <= 0 then self.ROBlock = false end
|
||
--[[
|
||
if self.Speed <= 5.5 and not self.AntiRolling and not self.RO then
|
||
self.AntiRolling = CurTime()
|
||
end
|
||
if self.Speed < 3 and Train:ReadTrainWire(6) > 0 and not self.RO and not self.AntiRolling then
|
||
self.AntiRolling = CurTime()-8
|
||
end]]
|
||
if speed < 3 and not self.RO and not self.AntiRolling and self.NoFreq == 0 then
|
||
self.AntiRolling = CurTime()-8
|
||
end
|
||
if self.AntiRolling and speed > 5.5 then
|
||
self.AntiRolling = false
|
||
end
|
||
if not self.ROBlock and (Train.KV["10AS-33"] > 0 or self.AttentionPedal and not self.AttentionPedalRO) and self.RO == true then
|
||
self.PneumaticBrake1 = false
|
||
self.AttentionPedalRO = true
|
||
self.RO = CurTime()
|
||
if self.AntiRolling and CurTime()-self.AntiRolling > 8 then self.AntiRolling = false end
|
||
end
|
||
if self.AttentionPedalRO and not self.AttentionPedal then self.AttentionPedalRO = false end
|
||
if self.RO and self.RO ~= true and (speed > 5.5 or CurTime()-self.RO > 7 or self.NoFreq > 0) then
|
||
self.AntiRolling = speed <= 5.5 and CurTime()-8 or false
|
||
if not self.ElectricBrake and not self.PneumaticBrake2 and self.AntiRolling and not self.AttentionPedal then
|
||
Train.EPKContacts:TriggerInput("Open",1)
|
||
end
|
||
self.RO = false
|
||
end
|
||
if self.RO and self.RO ~= true and self.AttentionPedal then self.RO = false end
|
||
if self.AntiRolling and self.AttentionPedal then self.AntiRolling = false end
|
||
--[[
|
||
-- Check use of valve #1 during overspeed
|
||
--self.PV1Timer = self.PV1Timer or -1e9
|
||
if self.PV1Timer and ((CurTime() - self.PV1Timer) >= 1) then
|
||
if self.Overspeed then
|
||
self.ElectricBrake = true
|
||
if self.Speed <= 5 then
|
||
self.PneumaticBrake2 = true
|
||
end
|
||
else
|
||
self.PneumaticBrake1 = false
|
||
end
|
||
self.PV1Timer = nil
|
||
end]]
|
||
local ElectricBrake = (self.ElectricBrake or self.AntiRolling and CurTime()-self.AntiRolling > 8)
|
||
|
||
if (ElectricBrake or self.PN2Timer == false) and not self.PN2Timer then
|
||
self.PN2Timer = CurTime()
|
||
elseif not ElectricBrake and self.PN2Timer then
|
||
self.PN2Timer = nil
|
||
end
|
||
local delay
|
||
if 60 < speed then
|
||
delay = 3.6--3.2
|
||
elseif 30 < speed then
|
||
delay = 4.2--3.9
|
||
elseif 20 < speed then
|
||
delay = 5.2
|
||
else
|
||
delay = 7.9
|
||
end
|
||
if (ElectricBrake or speed < 0.2 and not self.AttentionPedal) and Train:ReadTrainWire(34) == 0 then
|
||
if not self.EPKTimer then self.EPKTimer = CurTime() end
|
||
else
|
||
self.EPKTimer = nil
|
||
end
|
||
if self.EPKTimer and CurTime()-self.EPKTimer > delay then Train.EPKContacts:TriggerInput("Open",1) end
|
||
-- ARS signals
|
||
local Ebrake, Abrake, Pbrake1,Pbrake2 =
|
||
(ElectricBrake and 1 or 0),
|
||
((ElectricBrake or self.RO==true) and 1 or 0),
|
||
--((self.SpeedLimit == 0 and not self.KVT and not self.ARSBrake) and 1 or 0),
|
||
(self.RO == true and 1 or 0),
|
||
((self.PneumaticBrake2 or self.PN2Timer and CurTime()-self.PN2Timer > 2.7 or SpeedLimit <= 20.5 and not self.AttentionPedal) and 1 or 0)
|
||
-- Apply ARS system commands
|
||
self["33D"] = (1 - Abrake)
|
||
self["33G"] = Ebrake
|
||
self["33Zh"] = (1 - Abrake)
|
||
self["2"] = Ebrake
|
||
self["20"] = Ebrake
|
||
self["29"] = Pbrake1
|
||
self["8"] = Pbrake2
|
||
--print(self.ElectricBrake , self.AntiRolling,self.ARSBrake,self.RO,self.BSpeedLimit,Train:ReadTrainWire(2),Train:ReadTrainWire(8))
|
||
self.LVD = math.min(1,self.LVD+self["33G"])
|
||
if Train:ReadTrainWire(6) < 1 and self["33G"] < 0.5 then self.LVD = 0 end
|
||
self.Ring = self.ARSBrake and 1 or 0
|
||
--[[
|
||
торможении от АРС ЭПВ имеет 4 ступени задержки по времени на срабатывание:
|
||
80-60 км/ч - 3с (округлённо)
|
||
60-30 км/ч - 4с
|
||
30-20 км/ч - 5с
|
||
менее 10 км/ч - 8с
|
||
if self.ElectricBrake or self.PneumaticBrake2 then
|
||
if not self.LKT and not self.EPKTimer then
|
||
self.EPKTimer = CurTime() + ((10 <= self.Speed and self.Speed <= 30) and 5.5 or 3.3)
|
||
elseif self.LKT then
|
||
self.EPKTimer = nil
|
||
end
|
||
else
|
||
self.EPKTimer = nil
|
||
end
|
||
--if self.BPSActive then self.AntiRolling = false end
|
||
if EPKActivated and not self.LKT and self.Speed < 0.05 and Train:ReadTrainWire(1) == 0 then -- or (self.AntiRolling and Train:ReadTrainWire(1) > 0) then
|
||
if not self.EPKTimer2 then
|
||
self.EPKTimer2 = CurTime()+1
|
||
end
|
||
if self.EPKTimer2 and CurTime() - self.EPKTimer2 > 0 and not Train.Pneumatic.EmergencyValveEPK then
|
||
Train.Pneumatic.EmergencyValveEPK = true
|
||
|
||
RunConsoleCommand("say","EPV braking (LKT off when stopped)",Train:GetDriverName())
|
||
self.BeOffARS = nil
|
||
end
|
||
else
|
||
self.EPKTimer2 = nil
|
||
end]]
|
||
else
|
||
if Train.EPK.Value == 0 then Train.EPKContacts:TriggerInput("Set",1) end
|
||
self.ElectricBrake = true
|
||
self.ARSBrake = true
|
||
self.RO = true
|
||
self.PneumaticBrake2 = false
|
||
self.AntiRolling = false
|
||
self.BSpeedLimit = nil
|
||
self.PN2Timer = false
|
||
self["33D"] = 0
|
||
self["33Zh"] = 1
|
||
self["8"] = KRUEnabled and (1-Train.RPB.Value) or 0
|
||
self["33G"] = 0
|
||
self["2"] = 0
|
||
self["20"] = 0
|
||
self["29"] = 0
|
||
|
||
---self.LKT = false
|
||
self.LVD = 0
|
||
self.Ring = 0
|
||
end
|
||
-- ARS signalling train wires
|
||
if EnableARS then
|
||
self.Train:WriteTrainWire(21,self.LVD)-----self.LKT and 1 or 0)
|
||
else--if not EnableUOS then
|
||
self.Train:WriteTrainWire(21,0)
|
||
end
|
||
-- RC1 operation
|
||
if self.Train.RC1.Value == 0 then
|
||
self["33D"] = 1
|
||
self["33G"] = 0
|
||
self["33Zh"] = 1--KAH
|
||
--
|
||
self["2"] = 0
|
||
self["20"] = 0
|
||
self["29"] = 0
|
||
--
|
||
self["31"] = 0
|
||
self["32"] = 0
|
||
self["8"] = KRUEnabled and (1-Train.RPB.Value) or 0
|
||
end
|
||
if Train.RV_2 then Train.RV_2:TriggerInput("Set",EnableARS and 1 or 0) end
|
||
if (Train.Pneumatic and Train.Pneumatic.EmergencyValve) or self.UAVAContacts then self["33D"] = 0 end
|
||
if Train.UAVAContact.Value > 0.5 and not Train.Pneumatic.EmergencyValve and self.UAVAContacts then
|
||
self.UAVAContacts = nil
|
||
Train:PlayOnce("uava_reset","bass",1)
|
||
end
|
||
local EPKActivated = Train.Pneumatic.EPKEnabled or Train.RC1.Value == 0
|
||
if not EPKActivated or Train.EPKContacts.Value == 0 then
|
||
self["33D"] = 0
|
||
end
|
||
--self.Ring = self.Ring and 1 or 0
|
||
if Train.Rp8 then Train.Rp8:TriggerInput("Set",self["8"] + (1-self.Train.RC1.Value)*(1-self["33D"]))end
|
||
--self.Ring = self.RingOverride or self.Ring
|
||
Train.RPB:TriggerInput("Set",(self.Train.PB.Value + self.Train.KVT.Value + self.Train.RV_2.Value)*self.Train.VB.Value)
|
||
Train:WriteTrainWire(34,Train.RKTT.Value+Train.DKPT.Value)
|
||
end
|