-------------------------------------------------------------------------------- -- 81-714 Moscow and SPB electric schemes -------------------------------------------------------------------------------- -- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. -- Contains proprietary code. See license.txt for additional information. -------------------------------------------------------------------------------- Metrostroi.DefineSystem("81_714_Electric") TRAIN_SYSTEM.MVM = 1 TRAIN_SYSTEM.LVZ_1 = 2 TRAIN_SYSTEM.LVZ_2 = 3 TRAIN_SYSTEM.LVZ_3 = 4 TRAIN_SYSTEM.DOT_2 = 5 function TRAIN_SYSTEM:Initialize(typ1,typ2) self.TrainSolver = "81_717" self.ThyristorController = true self.Type = self.Type or self.MVM -- Load all functions from base Metrostroi.BaseSystems["Electric"].Initialize(self) for k,v in pairs(Metrostroi.BaseSystems["Electric"]) do if not self[k] and type(v) == "function" then self[k] = v end end self.SolvePowerCircuits = Metrostroi.BaseSystems["81_717_Electric"].SolvePowerCircuits self.SolveThyristorController = Metrostroi.BaseSystems["81_717_Electric"].SolveThyristorController self.Think = Metrostroi.BaseSystems["81_717_Electric"].Think end if CLIENT then return end function TRAIN_SYSTEM:Inputs(...) return { "Type", "NoRT2", "HaveRO", "GreenRPRKR","X2PS", "HaveVentilation" } end function TRAIN_SYSTEM:Outputs(...) return Metrostroi.BaseSystems["81_717_Electric"].Outputs(self,...) end function TRAIN_SYSTEM:TriggerInput(name,value) if name == "Type" then self.Type = value end if name == "NoRT2" then self.NoRT2 = value > 0 end if name == "HaveRO" then self.HaveRO = value > 0 end if name == "GreenRPRKR" then self.GreenRPRKR = value > 0 end if name == "X2PS" then self.X2PS = value > 0 end if name == "HaveVentilation" then self.Vent = value > 0 end end -- Node values local S = {} -- Converts boolean expression to a number local function C(x) return x and 1 or 0 end local min = math.min local max = math.max function TRAIN_SYSTEM:SolveAllInternalCircuits(Train,dT,firstIter) local P = Train.PositionSwitch local RheostatController = Train.RheostatController local RK = RheostatController.SelectedPosition local B = (Train.Battery.Voltage > 55) and 1 or 0 local BO = B*Train.VB.Value local T = Train.SolverTemporaryVariables local isMVM = self.Type == 1 local isDot2 = self.Type == 5 local Panel = Train.Panel Panel.V1 = T[10] --Поездная часть S["33D"] = T[10]*Train.A54.Value*Train.A84.Value Train:WriteTrainWire(1, S["33D"]*C(Train.RV.Value~=1)) Train:WriteTrainWire(20,S["33D"]*C(Train.RV.Value~=1)) Train:WriteTrainWire(4, S["33D"]*C(Train.RV.Value==2)*Train.Start.Value) Train:WriteTrainWire(5, S["33D"]*C(Train.RV.Value==0)*Train.Start.Value) Train:WriteTrainWire(17,S["33D"]*Train.VozvratRP.Value) if isMVM then Train:WriteTrainWire(71,S["33D"]*Train.OtklBV.Value) end --Вагонная часть S["10A"] = BO*Train.A30.Value S["ZR"] = (1-Train.RRP.Value)+(B*Train.A39.Value*(1-Train.RPvozvrat.Value)*Train.RRP.Value)*-1 S["1A"] = T[1]*Train.A1.Value*Train.IGLA_PCBK.KVC S["6A"] = T[6]*Train.A6.Value Train.TR1:TriggerInput("Set",S["6A"]) --1A-PMU-1T-NR/RPU-1P(6^) S["1P"] = S["1A"]*P.PM*(Train.NR.Value+Train.RPU.Value)+S["6A"]*P.PT --1P-RK1-18-AVT-!RP-RKR-DR1-DR2-1G S["1G"] = S["1P"]*C(1 <= RK and RK <= 18)*Train.AVT.Value*(1-Train.RPvozvrat.Value)*Train.RKR.Value--FIXME S["1L"] = S["1G"]*C(RK==1)*(Train.KSB1.Value+Train.KSH1.Value)*Train.LK2.Value S["1Zh"] = (S["1L"]+S["1G"]*Train.LK3.Value)*S["ZR"] Train.LK1:TriggerInput("Set",S["1Zh"]*P.PM) Train.LK3:TriggerInput("Set",S["1Zh"]) Train.LK4:TriggerInput("Set",S["1Zh"]*Train.LK3.Value) S["3A"] = T[3]*Train.A3.Value S["6G1"] = S["6A"]*P.PT*C(RK==1) self.ThyristorControllerWork = S["6G1"]*(Train.KSB1.Value+Train.KSB2.Value)*Train.LK2.Value S["6G2"] = S["6G1"]*(1-Train.RSU.Value) Train.KSB1:TriggerInput("Set",S["6G2"]) Train.KSB2:TriggerInput("Set",S["6G2"]) --20-A20-20A-Rp-20B S["20A"] = T[20]*Train.A20.Value*Train.IGLA_PCBK.KVC --Train.RPL:TriggerInput("Set",--[[ S["20A"]--]] BO*(1-Train.RPvozvrat.Value)*(Train.DR1.Value+Train.DR2.Value+(1-Train.BV.State))) if not isDot2 then Train.RPL:TriggerInput("Set",S["20A"]*(1-Train.RPvozvrat.Value)*(Train.DR1.Value+Train.DR2.Value+(1-Train.BV.State))) end S["20B"] = S["20A"]*(1-Train.RPvozvrat.Value) S["20K"] = S["20B"]*P.PS Train.LK2:TriggerInput("Set",S["20K"]*S["ZR"]) Train.LK5:TriggerInput("Set",S["20B"]*Train.LK1.Value*S["ZR"]) if self.X2PS then S["1M"] = C(1<=RK and RK<=5)*S["3A"]+S["20A"]*Train.KSH2.Value S["1R"] = (S["1A"]*C(RK==1)+S["1M"]*P.PP)*S["ZR"] Train.KSH1:TriggerInput("Set",S["1R"]) Train.KSH2:TriggerInput("Set",S["1R"]) P:TriggerInput("PP",S["3A"]*Train.LK5.Value*C(RK==18)*S["ZR"])--1A-1D else S["1M"] = C(1<=RK and RK<=5)*S["3A"]+T[10]*Train.KSH2.Value S["1R"] = (S["1A"]*C(RK==1)*P.PS + S["1M"]*P.PP)*S["ZR"] Train.KSH1:TriggerInput("Set",S["1R"]) Train.KSH2:TriggerInput("Set",S["1R"]) P:TriggerInput("PP",S["1A"]*C(RK==18)*S["ZR"])--1A-1D end local Reverser = Train.Reverser S["4A"] = T[4]*Train.A4.Value Reverser:TriggerInput("NZ",S["4A"]*Reverser.VP*(1-Train.LK1.Value)*S["ZR"]) S["5A"] = T[5]*Train.A5.Value Reverser:TriggerInput("VP",S["5A"]*Reverser.NZ*(1-Train.LK1.Value)*S["ZR"]) --Train.RKR:TriggerInput("Set",(S["4A"]*Reverser.NZ+S["5A"]*Reverser.VP)) --81-717.5(м) МСК if isDot2 then Train.RKR:TriggerInput("Set",(S["4A"]*Reverser.NZ+S["5A"]*Reverser.VP)*S["ZR"]) --81-717.5 Харько*S["ZR"]в else Train.RKR:TriggerInput("Set",(S["4A"]*Reverser.NZ+S["5A"]*Reverser.VP)*Train.BV.State*S["ZR"]) --81-717.5 Харько*S["ZR"]в end --+B S["1N"] = C(11<=RK and RK<=18)*(1-Train.LK4.Value) Train.RR:TriggerInput("Set",S["10A"]*S["1N"] + P.PS*Train.LK4.Value) S["5Zh"] = S["10A"]*(1-Train.LK3.Value) P:TriggerInput("PS",S["5Zh"]*(P.PP)) P:TriggerInput("PM",S["5Zh"]*(1-Train.TR1.Value)*Train.KSH2.Value) P:TriggerInput("PT",S["5Zh"]*(P.PM)*(1-Train.KSH2.Value)) --P:TriggerInput("PP",S["5Zh"]*(P.PM)) S["2A"] = (T[2]+T[-2])*Train.A2.Value S["2T"] = S["2A"]*Train.TR1.Value Train.RSU:TriggerInput("Set",S["2T"]*Train.ThyristorBU5_6.Value) Train.RU:TriggerInput("Set",S["2T"]) S["2B"] = S["2A"]*((1-Train.KSB1.Value)*(1-Train.KSB2.Value)+(1-Train.TR1.Value)) S["2Ca"] = P.PS*C(1<=RK and RK<=17)*Train.RR.Value --CHECK S["2Cb"] = P.PP*(C(6<=RK and RK<=18)+C(2<=RK and RK<=5)*Train.KSH1.Value)*(1-Train.RR.Value) --CHECK S["2C"] = S["2B"]*(S["2Ca"]+S["2Cb"])*Train.LK4.Value S["10R"] = S["10A"]*(1-Train.LK3.Value)*C(2<=RK and RK<=18)*(1-Train.LK4.Value) S["2U"] = S["10R"]+S["2C"]*S["ZR"] Train.SR1:TriggerInput("Set",S["2U"]) Train.RV1:TriggerInput("Set",S["2U"]) S["2Zh"] = T[2]*Train.A2.Value*Train.TR1.Value*C(17<=RK and RK<=18) if self.NoRT2 then Train.PneumaticNo1:TriggerInput("Set",S["2Zh"]+T[48]*Train.A72.Value) Train:WriteTrainWire(-2,Train.A2.Value*Train.TR1.Value*C(17<=RK and RK<=18)*T[48]*Train.A72.Value) else Train.PneumaticNo1:TriggerInput("Set",S["2Zh"]+T[48]*Train.A72.Value*(1-Train.RT2.Value)) Train:WriteTrainWire(-2,Train.A2.Value*Train.TR1.Value*C(17<=RK and RK<=18)*T[48]*Train.A72.Value*(1-Train.RT2.Value)) end if isMVM then --UNREALISTIC S["8A"] = T[8]*Train.A8.Value*(1-Train.RV1.Value)*(1-Train.RT2r.Value)*(1-Train.RV3.Value) else S["8A"] = T[8]*Train.A8.Value*(1-Train.RV1.Value)*(1-Train.RT2.Value)*(1-Train.RV3.Value) end Train.PneumaticNo2:TriggerInput("Set",S["8A"]+T[39]*Train.A52.Value) Train.RV3:TriggerInput("Set",T[19]*Train.A19.Value) S["25A"] = T[25]*Train.A25.Value S["10X"] = (--[[ S["1N"]*P.PS+--]] Train.LK4.Value+C(RK==1)*Train.LK2.Value) Train["RRTpod"] = S["10A"]*RheostatController.RKM2*S["10X"] Train["RRTuderzh"] = S["25A"] Train["RUTpod"] = S["10A"]*RheostatController.RKM1*S["10X"] Train["RUTavt"] = Train.A70.Value*B Train.RRT:TriggerInput("Close",Train.RRTuderzh*Train.RRTpod) Train.RRT:TriggerInput("Open",(1-Train.RRTuderzh)) Train.RRP:TriggerInput("Set",T[14]*Train.A14.Value)--14A --СДРК Б+ провод S["10A3"] = BO*Train.A28.Value S["10BG"] = S["10A3"]*(Train.TR1.Value + Train.RV1.Value) RheostatController:TriggerInput("MotorCoilState",min(1,S["10A"]*(S["10BG"]*Train.RR.Value - S["10BG"]*(1-Train.RR.Value)))) Train.RVO:TriggerInput("Set",S["10A3"]*Train.NR.Value) self.ThyristorControllerPower = S["10A3"] --[[ S["10Ra"] = T[10]*RheostatController.RKM1 S["10Rb"] = T[10]*Train.SR1.Value S["10RbA"] = S["10Rb"]*(1-Train.RRT.Value)*(1-Train.RUT.Value)+S["10Ra"] S["10RbB"] = S["10Rb"]*Train.RUT.Value S["10RB"] = S["10RbA"]+S["10RbB"]*Train.RRT.Value+S["10RbB"]*(1-Train.SR1.Value) S["10Rc"] = T[10]*Train.LK3.Value*C(RK>=18 or RK<=1) S["10RS"] = S["10Ra"]+S["10RB"]*(1-RheostatController.RKP)*S["10Rc"]--]] S["10Yu"] = S["10A"]*Train.SR1.Value S["10M"] = S["10Yu"]*(1-Train.RRT.Value)*(1-Train.RUT.Value) S["10N"] = S["10A"]*RheostatController.RKM1+S["10M"] S["10T"] = (Train.RUT.Value+Train.RRT.Value+(1-Train.SR1.Value))*(RheostatController.RKP)+S["10A"]*Train.LK3.Value*C(RK>=18 and RK<=1) RheostatController:TriggerInput("MotorState",S["10N"]+S["10T"]*(-10)) Train.RZ_2:TriggerInput("Set",T[24]*(1-Train.LK4.Value)) S["17A"] = T[17]*Train.A18.Value if not isDot2 then Train.BV:TriggerInput("Power",BO*Train.A80.Value) Train.BV:TriggerInput("Enable",S["17A"]) end if isMVM then Train.BV:TriggerInput("Disable",T[71]*Train.A66.Value) end Train.RPvozvrat:TriggerInput("Open",S["17A"]) --FIXME Mayve more right RP code -- --Вспом цепи Train:WriteTrainWire(10,BO*Train.A56.Value) if self.NoRT2 then Train:WriteTrainWire(48,Train.A72.Value*S["2Zh"]) --FIXME ARS else Train:WriteTrainWire(48,Train.A72.Value*S["2Zh"]*(1-Train.RT2.Value)) --FIXME ARS end Train:WriteTrainWire(22,T[10]*Train.A10.Value*Train.AK.Value) S["UO"] = T[10]*Train.A27.Value Train:WriteTrainWire(27,S["UO"]*Train.L_1.Value) S["36N"] = BO*Train.A45.Value Train:WriteTrainWire(36,S["36N"]*Train.BPSNon.Value) Train:WriteTrainWire(37,S["36N"]*Train.ConverterProtection.Value) if self.GreenRPRKR then S["10AN"] = Train.RPvozvrat.Value+(1-Train.RKR.Value) --81-717 Харьков else S["10AN"] = Train.RPvozvrat.Value --81-717 МСК end S["18A"] = (S["10AN"]*100+(1-Train.LK4.Value))*Train.A38.Value Train:WriteTrainWire(18,S["18A"]) Panel.TW18 = S["18A"] Panel.GreenRP = S["10AN"]*S["UO"] --S["36N"] = BO*Train.A45.Value --Train:WriteTrainWire(37,Train.ConverterProtection.Value) --Train:WriteTrainWire(36,S["36N"]*(1-Train.BPSNon.Value)) --Train:WriteTrainWire(69,T[36]*Train.BPSNon.Value) S["B9"] = B*Train.A53.Value S["B9a"] = S["B9"]*Train.VB.Value Train.KVC:TriggerInput("Set",S["B9a"]) --Train.KUP:TriggerInput("Set",S["B9a"]*Train.A75.Value) S["D4"] = BO*Train.A13.Value Panel.RZP = T[36]*T[61] --[[S["14b"] = S["14a"]*Train.A17.Value S["D1"] = ["10"]*Train.A21.Value*KV["D-D1"]+S["14b"]*KRU["11/3-D1/1"] if isLVZ then Train:WriteTrainWire(16,S["D1"]*(Train.VUD1.Value*Train.VUD2.Value+AVO["16"]*RC2)) else Train:WriteTrainWire(16,S["D1"]*(Train.VUD1.Value*Train.VUD2.Value)) end Train:WriteTrainWire(12,S["D1"]*Train.KRZD.Value) S[31] = S["D1"]*(1-Train.DoorSelect.Value) S[32] = S["D1"]*Train.DoorSelect.Value Train:WriteTrainWire(31,S[31]*(Train.KDL.Value+Train.KDLR.Value+Train.VDL.Value)) Train:WriteTrainWire(32,S[32]*Train.KDP.Value) S["F7"] = T[10]*Train.A29.Value*KV["F-F7"]+S["14b"]*KRU["11/3-FR1"] S["F1"] = S["B9"]*KV["B9-F1"]--]] Train:WriteTrainWire(34,Train.RKTT.Value+Train.DKPT.Value) Train:WriteTrainWire(28,T[-28]*Train.RD.Value) S[64] = S["UO"]*Train.BPT.Value Train:WriteTrainWire(64,S[64]) Panel.BrW = S[64] --Вспом цепи приём if isDot2 then Panel.EmergencyLights = T[11]*Train.A15.Value*(1-Train.KPP.Value) else Panel.EmergencyLights = BO*Train.A49.Value*Train.A15.Value end Train.RPU:TriggerInput("Set",T[37]*Train.A37.Value) S["D6"] = S["D4"]*Train.BD.Value Train.RD:TriggerInput("Set",S["D6"]) Panel.DoorsW = S["D4"]*(1-Train.RD.Value) Train.VDZ:TriggerInput("Set",T[16]*Train.A16.Value*(1-Train.RD.Value)) S["12A"] = T[12]*Train.A12.Value S["31A"] = T[31]*Train.A31.Value S["32A"] = T[32]*Train.A32.Value Train.VDOL:TriggerInput("Set",S["31A"]+S["12A"]) Train.VDOP:TriggerInput("Set",S["32A"]+S["12A"]) Train:WriteTrainWire(31,S["12A"]*Train.A31.Value) Train:WriteTrainWire(32,S["12A"]*Train.A32.Value) S["36A"] = T[36]*Train.A51.Value*Train.RVO.Value--36 Train.KVP:TriggerInput("Set",S["36A"]*Train.KPP.Value) Train.KPP:TriggerInput("Set",S["36A"]*(1-Train.RZP.Value)*Train.KVC.Value) S["27A"] = T[27]*Train.A50.Value Train.KO:TriggerInput("Set",S["27A"]) --S["22A"] = (T[23]*Train.A23.Value+T[22]*Train.A22.Value) --FIXME 714 Train.RV2:TriggerInput("Set",T[23]*Train.A23.Value) Train.KK:TriggerInput("Set",( T[22]*Train.A22.Value*(1-Train.RV2.Value)+ T[23]*Train.A23.Value*Train.RV2.Value )*(1-Train.TRK.Value)) --if isMVM then Panel.AnnouncerPlaying = T[13] Panel.AnnouncerBuzz = T[-13] --end --BPSN local BPSN = Train.PowerSupply Train.Battery:TriggerInput("Charge",BPSN.X2_2*Train.A24.Value*BO) BPSN:TriggerInput("5x2",BO*Train.A65.Value*Train.KVP.Value) Panel.MainLights = BPSN.X6_2*Train.KO.Value Train.RPU:TriggerInput("Set",T[37]*Train.A37.Value) Train.RZP:TriggerInput("Open",T[37]*Train.A37.Value*Train.RPU.Value) Train:WriteTrainWire(61,Train.RZP.Value) if self.Vent then Train.KV1:TriggerInput("Set",T[59]*Train.AV4.Value*Train.RVO.Value) Train.KV2:TriggerInput("Set",T[60]*Train.AV5.Value) Train.KV3:TriggerInput("Set",T[58]*Train.AV6.Value) S["AV2"] = T[10]*Train.AV2.Value Panel.M1_3 = S["AV2"]*Train.KV1.Value Panel.M4_7 = S["AV2"]*Train.KV2.Value+B*Train.AV3.Value*Train.KV3.Value Train.R1:TriggerInput("Set",S["AV2"]*C(Panel.M1_3 > 0.5 and Panel.M4_7 > 0.5)) Train:WriteTrainWire(57,T[59]*(1-Train.R1.Value)) end return S end function TRAIN_SYSTEM:SolveRKInternalCircuits(Train,dT,firstIter) local P = Train.PositionSwitch local RheostatController = Train.RheostatController local RK = RheostatController.SelectedPosition local B = (Train.Battery.Voltage > 55) and 1 or 0 local BO = B*Train.VB.Value local T = Train.SolverTemporaryVariables --Вагонная часть S["10A"] = BO*Train.A30.Value S["ZR"] = (1-Train.RRP.Value)+(B*Train.A39.Value*(1-Train.RPvozvrat.Value)*Train.RRP.Value)*-1 S["1N"] = C(11<=RK and RK<=18)*(1-Train.LK4.Value) Train.RR:TriggerInput("Set",S["10A"]*S["1N"] + P.PS*Train.LK4.Value) S["2A"] = (T[2]+T[-2])*Train.A2.Value S["2B"] = S["2A"]*((1-Train.KSB1.Value)*(1-Train.KSB2.Value)+(1-Train.TR1.Value)) S["2Ca"] = P.PS*C(1<=RK and RK<=17)*Train.RR.Value --CHECK S["2Cb"] = P.PP*(C(6<=RK and RK<=18)+C(2<=RK and RK<=5)*Train.KSH1.Value)*(1-Train.RR.Value) --CHECK S["2C"] = S["2B"]*(S["2Ca"]+S["2Cb"])*Train.LK4.Value S["10R"] = S["10A"]*(1-Train.LK3.Value)*C(2<=RK and RK<=18)*(1-Train.LK4.Value) S["2U"] = (S["10R"]+S["2C"])*S["ZR"] Train.SR1:TriggerInput("Set",S["2U"]) Train.RV1:TriggerInput("Set",S["2U"]) S["25A"] = T[25]*Train.A25.Value S["10X"] = (Train.LK4.Value+C(RK==1)*Train.LK2.Value) Train["RRTpod"] = S["10A"]*RheostatController.RKM2*S["10X"] Train["RRTuderzh"] = S["25A"] Train["RUTpod"] = S["10A"]*RheostatController.RKM1*S["10X"] Train.RRT:TriggerInput("Close",Train.RRTuderzh*Train.RRTpod) Train.RRT:TriggerInput("Open",(1-Train.RRTuderzh)) --СДРК Б+ провод S["10A3"] = BO*Train.A28.Value S["10BG"] = S["10A3"]*(Train.TR1.Value + Train.RV1.Value) RheostatController:TriggerInput("MotorCoilState",min(1,S["10A"]*(S["10BG"]*Train.RR.Value - S["10BG"]*(1-Train.RR.Value)))) S["10Yu"] = S["10A"]*Train.SR1.Value S["10M"] = S["10Yu"]*(1-Train.RRT.Value)*(1-Train.RUT.Value) S["10N"] = S["10A"]*RheostatController.RKM1+S["10M"] S["10T"] = (Train.RUT.Value+Train.RRT.Value+(1-Train.SR1.Value))*(RheostatController.RKP)+S["10A"]*Train.LK3.Value*C(RK>=18 and RK<=1) RheostatController:TriggerInput("MotorState",S["10N"]+S["10T"]*(-10)) return S end local wires = {10,11,1,6,3,20,4,5,-2,2,48,8,39,19,25,13,-13,14,24,17,71,36,-28,37,16,12,31,32,69,27,23,22,23,37,59,60,58,61} function TRAIN_SYSTEM:SolveInternalCircuits(Train,dT,firstIter) local T = Train.SolverTemporaryVariables if not T then T = {} for i,v in ipairs(wires) do T[v] = 0 end Train.SolverTemporaryVariables = T end if firstIter then for i,v in ipairs(wires) do T[v] = min(Train:ReadTrainWire(v),1) end self:SolveAllInternalCircuits(Train,dT) else self:SolveRKInternalCircuits(Train,dT) end end