Files
maszyna/McZapkie/_mover.pas

7597 lines
292 KiB
ObjectPascal

unit _mover; {fizyka ruchu dla symulatora lokomotywy}
(*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Maciej Czapkiewicz and others
*)
(*
(C) McZapkie v.2004.02
Co brakuje:
6. brak pantografow itp 'Nie do konca, juz czesc zrobiona - Winger
7. brak efektu grzania oporow rozruchowych, silnika, osi
9. ulepszyc sprzeg sztywny oraz automatyczny
10. klopoty z EN57
...
n. Inne lokomotywy oprocz elektrowozu pradu stalego
*)
(*
Zrobione:
1. model szeregowego silnika elektrycznego sterowanego reostatem
2. fizyka ruchu - sily oporu, nachylenia, przyspieszenia styczne i normalne,
przyczepnosc/poslizg przy hamowaniu i rozruchu
3. docisk klockow hamulcowych -hamulec reczny oraz pomocniczy hamulec pneumatyczny
4. ubytki cisnienia wskutek hamowania, kompresor - ladowanie zbiornika
5. niektore uszkodzenia i awarie - logika rozmyta
a) silnik elektryczny - za duzy prad, napiecie, obroty
b) sprzegi - zerwanie gdy zbyt duze sily
6. flagi niektorych dzwiekow
7. hamulec zasadniczy - elektropneumatyczny (impulsowanie), pneumatyczny - zmiany cisnienia
zwiekszenie nacisku przy duzych predkosciach w hamulcach Oerlikona
8. sprzegi - sila, tlumiennosc
9. lok. el. - wylacznik glowny, odlacznik uszkodzonych silnikow
10. parametry trakcji
11. opoznienia w zalaczaniu stycznikow
12. trakcja wielokrotna
13. informacja na temat zrodla mocy dla silnikow trakcyjnych, ogrzewania, oswietlenia
14. dumb - uproszczony model lokomotywy (tylko dla AI)
15. ladunki - ilosc, typ, szybkosc na- i rozladunku, funkcje przetestowac!
16. ulepszony model fizyczny silnika elektrycznego (hamowanie silnikiem, ujemne napiecia)
17. poprawione hamulce - parametry cylindrow itp
18. ulepszone hamulce - napelnianie uderzeniowe, stopnie hamowania
19. poprawione hamulce - wyszczegolnenie cisnienia dla stopni hamowania
20. poprawione hamulce elektropneumatyczne
21. poprawione hamowanie przeciwposlizgowe i odluzniacz
22. dodany model mechanicznego napedu recznego (drezyna)
23. poprawiona szybkosc hamowania pomocniczego i przeciwposlizgowego, odlaczanie silnikow, odlaczanie bocznikow
24. wprowadzone systemy zabezpieczenia: SHP, Czuwak, sygnalizacja kabinowa (nie dzialaja w DebugMode).
25. poprawiona predkosc propagacji fali cisnienia (normalizacja przez kwadrat dlugosci) //to jest zdeka liniowe
26. uwzgledniona masa ladunku, przesuniecie w/m toru ruchu
27. lampy/sygnaly przednie/tylne
28. wprowadzona pozycja odciecia hamulca (yB: tja, ale oerlikona....)
29. rozne poprawki: slizganie, wykolejanie itp
30. model silnika spalinowego z przekladnia mechaniczna
31. otwieranie drzwi, sprezarka, przetwornica
32. wylaczanie obliczen dla nieruchomych wagonow
33. Zbudowany model rozdzielacza powietrza roznych systemow
34. Poprawiona pozycja napelniania uderzeniowego i hamulec EP
35. Dodane baterie akumulatorow (KURS90)
36. Hamowanie elektrodynamiczne w ET42 i poprawione w EP09
37. jednokierunkowosc walu kulakowego w EZT (nie do konca)
38. wal kulakowy w ET40
39. poprawiona blokada nastawnika w ET40
...
*)
interface uses mctools,sysutils,hamulce,Oerlikon_ESt;
CONST
Go=true;
Hold=false; {dla CheckLocomotiveParameters}
ResArraySize=64; {dla silnikow elektrycznych}
MotorParametersArraySize=10;
maxcc=4; {max. ilosc odbierakow pradu}
LocalBrakePosNo=10; {ilosc nastaw hamulca pomocniczego}
MainBrakeMaxPos=10; {max. ilosc nastaw hamulca zasadniczego}
ManualBrakePosNo=20; {ilosc nastaw hamulca recznego}
LightsSwitchPosNo=16;
{uszkodzenia toru}
dtrack_railwear=2;
dtrack_freerail=4;
dtrack_thinrail=8;
dtrack_railbend=16;
dtrack_plants=32;
dtrack_nomove=64;
dtrack_norail=128;
{uszkodzenia taboru}
dtrain_thinwheel=1; {dla lokomotyw}
dtrain_loadshift=1; {dla wagonow}
dtrain_wheelwear=2;
dtrain_bearing=4;
dtrain_coupling=8;
dtrain_ventilator=16; {dla lokomotywy el.}
dtrain_loaddamage=16; {dla wagonow}
dtrain_engine=32; {dla lokomotyw}
dtrain_loaddestroyed=32;{dla wagonow}
dtrain_axle=64;
dtrain_out=128; {wykolejenie}
{wagi prawdopodobienstwa dla funkcji FuzzyLogic}
p_elengproblem = 0.01;
p_elengdamage = 0.1;
p_coupldmg = 0.02;
p_derail=0.001;
p_accn=0.1;
p_slippdmg=0.001;
{typ sprzegu}
ctrain_virtual=0; //gdy pojazdy na tym samym torze się widzą wzajemnie
ctrain_coupler=1; //sprzeg fizyczny
ctrain_pneumatic=2; //przewody hamulcowe
ctrain_controll=4; //przewody sterujące (ukrotnienie)
ctrain_power=8; //przewody zasilające (WN)
ctrain_passenger=16; //mostek przejściowy
ctrain_scndpneumatic=32; //przewody 8 atm (żółte; zasilanie powietrzem)
ctrain_heating=64; //przewody ogrzewania WN
ctrain_depot=128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna
{typ hamulca elektrodynamicznego}
dbrake_none=0;
dbrake_passive=1;
dbrake_switch=2;
dbrake_reversal=4;
dbrake_automatic=8;
{status czuwaka/SHP}
//hunter-091012: rozdzielenie alarmow, dodanie testu czuwaka
s_waiting=1; //działa
s_aware=2; //czuwak miga
s_active=4; //SHP świeci
s_CAalarm=8; //buczy
s_SHPalarm=16; //buczy
s_CAebrake=32; //hamuje
s_SHPebrake=64; //hamuje
s_CAtest=128;
{dzwieki}
sound_none=0;
sound_loud=1;
sound_couplerstretch=2;
sound_bufferclamp=4;
sound_bufferbump=8;
sound_relay=16;
sound_manyrelay=32;
sound_brakeacc=64;
PhysicActivationFlag: boolean=false;
//szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType
//zamienione na flagi bitowe, aby szybko wybierać grupę (np. EZT+SZT)
dt_Default=0;
dt_EZT=1;
dt_ET41=2;
dt_ET42=4;
dt_PseudoDiesel=8;
dt_ET22=$10; //używane od Megapacka
dt_SN61=$20; //nie używane w warunkach, ale ustawiane z CHK
dt_EP05=$40;
dt_ET40=$80;
dt_181=$100;
//stałe dla asynchronów
eimc_s_dfic=0;
eimc_s_dfmax=1;
eimc_s_p=2;
eimc_s_cfu=3;
eimc_s_cim=4;
eimc_s_icif=5;
eimc_f_Uzmax=7;
eimc_f_Uzh=8;
eimc_f_DU=9;
eimc_f_I0=10;
eimc_f_cfu=11;
eimc_p_F0=13;
eimc_p_a1=14;
eimc_p_Pmax=15;
eimc_p_Fh=16;
eimc_p_Ph=17;
eimc_p_Vh0=18;
eimc_p_Vh1=19;
eimc_p_Imax=20;
eimc_p_abed=21;
eimc_p_eped=22;
//zmienne dla asynchronów
eimv_FMAXMAX=0;
eimv_Fmax=1;
eimv_ks=2;
eimv_df=3;
eimv_fp=4;
eimv_U=5;
eimv_pole=6;
eimv_Ic=7;
eimv_If=8;
eimv_M=9;
eimv_Fr=10;
eimv_Ipoj=11;
eimv_Pm=12;
eimv_Pe=13;
eimv_eta=14;
eimv_fkr=15;
eimv_Uzsmax=16;
eimv_Pmax=17;
eimv_Fzad=18;
eimv_Imax=19;
eimv_Fful=20;
bom_PS = 1;
bom_PN = 2;
bom_EP = 4;
bom_MED = 8;
TYPE
{ogolne}
TLocation = record
X,Y,Z: real; {lokacja}
end;
TRotation = record
Rx,Ry,Rz: real; {rotacja}
end;
TDimension= record
W,L,H: real; {wymiary}
end;
TCommand = record
Command: string; {komenda}
Value1,Value2: real; {argumenty komendy}
Location: TLocation;
end;
{tory}
TTrackShape= record {ksztalt odcinka - promien, dlugosc, nachylenie, przechylka}
R, Len, dHtrack, dHrail: real;
end;
TTrackParam= record {parametry odcinka - szerokosc, tarcie statyczne, kategoria, obciazalnosc w t/os, uszkodzenia}
Width, friction: real;
CategoryFlag, QualityFlag, DamageFlag: byte;
Velmax:real; {dla uzytku maszynisty w ai_driver}
end;
TTractionParam= record
TractionVoltage: real; {napiecie}
TractionFreq: real; {czestotliwosc}
TractionMaxCurrent: real; {obciazalnosc}
TractionResistivity: real; {rezystancja styku}
end;
{powyzsze parametry zwiazane sa z torem po ktorym aktualnie pojazd jedzie}
{typy hamulcow zespolonych}
TBrakeSystem = (Individual, Pneumatic, ElectroPneumatic);
{podtypy hamulcow zespolonych}
TBrakeSubSystem = (ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako);
TBrakeValve = (NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss, Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other);
TBrakeHandle = (NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113, MHZ_P, MHZ_T, MHZ_EN57);
{typy hamulcow indywidualnych}
TLocalBrake = (NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake);
TBrakeDelayTable= array[1..4] of real;
{dla osob/towar: opoznienie hamowania/odhamowania}
TBrakePressure= record
PipePressureVal: real;
BrakePressureVal: real;
FlowSpeedVal: real;
BrakeType: TBrakeSystem;
end;
TBrakePressureTable= array[-2..MainBrakeMaxPos] of TBrakePressure;
{typy napedow}
TEngineTypes = (None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric);
{postac dostarczanej energii}
TPowerType = (NoPower, BioPower, MechPower, ElectricPower, SteamPower);
{rodzaj paliwa}
TFuelType = (Undefined, Coal, Oil);
{rodzaj rusztu}
TGrateType = record
FuelType: TFuelType;
GrateSurface: real;
FuelTransportSpeed: real;
IgnitionTemperature: real;
MaxTemperature: real;
end;
{rodzaj kotla}
TBoilerType = record
BoilerVolume: real;
BoilerHeatSurface: real;
SuperHeaterSurface: real;
MaxWaterVolume,MinWaterVolume: real;
MaxPressure: real;
end;
{rodzaj odbieraka pradu}
TCurrentCollector = record
CollectorsNo: longint; //musi być tu, bo inaczej się kopie
MinH,MaxH: real; //zakres ruchu pantografu, nigdzie nie używany
CSW: real; //szerokość części roboczej (styku) ślizgacza
MinV,MaxV: real; //minimalne i maksymalne akceptowane napięcie
OVP: real; //czy jest przekaznik nadnapieciowy
InsetV: real; //minimalne napięcie wymagane do załączenia
MinPress: real; //minimalne ciśnienie do załączenia WS
MaxPress: real; //maksymalne ciśnienie za reduktorem
end;
{typy źródeł mocy}
TPowerSource = (NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater);
{parametry źródeł mocy}
TPowerParameters = record
MaxVoltage: real;
MaxCurrent: real;
IntR: real;
case SourceType: TPowerSource of
NotDefined,InternalSource : (PowerType: TPowerType);
Transducer : (InputVoltage: real);
Generator : (GeneratorEngine: TEngineTypes);
Accumulator: (RAccumulator:record MaxCapacity:real; RechargeSource:TPowerSource end);
CurrentCollector: (CollectorParameters: TCurrentCollector);
PowerCable : (RPowerCable:record PowerTrans:TPowerType; SteamPressure:real end);
Heater : (RHeater:record Grate:TGrateType; Boiler:TBoilerType end);
end;
{dla lokomotyw elektrycznych:}
TScheme= record
Relay: byte; {numer pozycji rozruchu samoczynnego}
R: real; {opornik rozruchowy} {dla dizla napelnienie}
Bn,Mn:byte; {ilosc galezi i silnikow w galezi} {dla dizla Mn: czy luz czy nie}
AutoSwitch: boolean; {czy dana pozycja nastawniana jest recznie czy autom.}
ScndAct: byte; {jesli ma bocznik w nastawniku, to ktory bocznik na ktorej pozycji}
end;
TSchemeTable = array[0..ResArraySize] of TScheme; {tablica rezystorow rozr.}
TDEScheme= record
RPM: real; {obroty diesla}
GenPower: real; {moc maksymalna}
Umax: real; {napiecie maksymalne}
Imax: real; {prad maksymalny}
end;
TDESchemeTable = array[0..32] of TDEScheme; {tablica rezystorow rozr.}
TShuntScheme = record
Umin: real;
Umax: real;
Pmin: real;
Pmax: real;
end;
TShuntSchemeTable = array[0..32] of TShuntScheme;
TMPTRelay = record {lista przekaznikow bocznikowania}
Iup: real;
Idown: real;
end;
TMPTRelayTable = array[0..7] of TMPTRelay;
TMotorParameters = record
mfi,mIsat,mfi0:real; // aproksymacja M(I) silnika} {dla dizla mIsat=przekladnia biegu
fi,Isat,fi0: real; // aproksymacja E(n)=fi*n} {dla dizla fi, mfi: predkosci przelozenia biegu <->
AutoSwitch: boolean;
end;
TSecuritySystem= record
SystemType:byte; {0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa}
AwareDelay:real; //czas powtarzania czuwaka
AwareMinSpeed:real; //minimalna prędkość załączenia czuwaka, normalnie 10% Vmax
SoundSignalDelay,EmergencyBrakeDelay:real;
Status: byte; {0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne}
//SystemTimer, SystemSoundTimer, SystemBrakeTimer: real;
SystemTimer, SystemSoundCATimer, SystemSoundSHPTimer, SystemBrakeCATimer, SystemBrakeSHPTimer, SystemBrakeCATestTimer: real; //hunter-091012
VelocityAllowed, NextVelocityAllowed: integer; {predkosc pokazywana przez sygnalizacje kabinowa}
RadioStop:boolean; //czy jest RadioStop
end;
//Ra: to oddzielnie, bo się kompilatorowi miesza
TTransmision=
record //liczba zebow przekladni}
NToothM, NToothW : byte;
Ratio: real; {NToothW/NToothM}
end;
{sprzegi}
TCouplerType=(NoCoupler,Articulated,Bare,Chain,Screw,Automatic);
//Ra: T_MoverParameters jako klasa jest już wskaźnikiem na poziomie Pascala
//P_MoverParameters=^T_MoverParameters
T_MoverParameters=class;
TCoupling = record
{parametry}
SpringKB,SpringKC,beta:real; {stala sprezystosci zderzaka/sprzegu, %tlumiennosci }
DmaxB,FmaxB,DmaxC,FmaxC: real; {tolerancja scisku/rozciagania, sila rozerwania}
CouplerType: TCouplerType; {typ sprzegu}
{zmienne}
CouplingFlag : byte; {0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy}
AllowedFlag : Integer; //Ra: znaczenie jak wyżej, maska dostępnych
Render: boolean; {ABu: czy rysowac jak zaczepiony sprzeg}
CoupleDist: real; {ABu: optymalizacja - liczenie odleglosci raz na klatkę, bez iteracji}
Connected: T_MoverParameters; {co jest podlaczone}
ConnectedNr: byte; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył
CForce: real; {sila z jaka dzialal}
Dist: real; {strzalka ugiecia zderzaków}
CheckCollision: boolean; {czy sprawdzac sile czy pedy}
end;
//TCouplers= array[0..1] of TCoupling;
//TCouplerNr= array[0..1] of byte; //ABu: nr sprzegu z ktorym polaczony; Ra: wrzucić do TCoupling
{----------------------------------------------}
{glowny obiekt}
T_MoverParameters = class(TObject) //Ra: dodana kreska w celu zrobienia wrappera
dMoveLen:real;
filename:string;
{---opis lokomotywy, wagonu itp}
{--opis serii--}
CategoryFlag: byte; {1 - pociag, 2 - samochod, 4 - statek, 8 - samolot}
{--sekcja stalych typowych parametrow}
TypeName: string; {nazwa serii/typu}
//TrainType: string; {typ: EZT/elektrowoz - Winger 040304}
TrainType: integer; {Ra: powinno być szybciej niż string}
EngineType: TEngineTypes; {typ napedu}
EnginePowerSource: TPowerParameters; {zrodlo mocy dla silnikow}
SystemPowerSource: TPowerParameters; {zrodlo mocy dla systemow sterowania/przetwornic/sprezarek}
HeatingPowerSource: TPowerParameters; {zrodlo mocy dla ogrzewania}
AlterHeatPowerSource: TPowerParameters; {alternatywne zrodlo mocy dla ogrzewania}
LightPowerSource: TPowerParameters; {zrodlo mocy dla oswietlenia}
AlterLightPowerSource: TPowerParameters;{alternatywne mocy dla oswietlenia}
Vmax,Mass,Power: real; {max. predkosc kontrukcyjna, masa wlasna, moc}
Mred: real; {Ra: zredukowane masy wirujące; potrzebne do obliczeń hamowania}
TotalMass:real; {wyliczane przez ComputeMass}
HeatingPower, LightPower: real; {moc pobierana na ogrzewanie/oswietlenie}
BatteryVoltage: real; {Winger - baterie w elektrykach}
Battery: boolean; {Czy sa zalavzone baterie}
EpFuse: boolean; {Czy sa zalavzone baterie}
Signalling: boolean; {Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu}
DoorSignalling: boolean; {Czy jest zalaczona sygnalizacja blokady drzwi}
Radio: boolean; {Czy jest zalaczony radiotelefon}
NominalBatteryVoltage: real; {Winger - baterie w elektrykach}
Dim: TDimension; {wymiary}
Cx: real; {wsp. op. aerodyn.}
Floor: real; //poziom podłogi dla ładunków
WheelDiameter : real; {srednica kol napednych}
WheelDiameterL : real; //Ra: srednica kol tocznych przednich
WheelDiameterT : real; //Ra: srednica kol tocznych tylnych
TrackW: real; {nominalna szerokosc toru [m]}
AxleInertialMoment: real; {moment bezwladnosci zestawu kolowego}
AxleArangement : string; {uklad osi np. Bo'Bo' albo 1'C}
NPoweredAxles : byte; {ilosc osi napednych liczona z powyzszego}
NAxles : byte; {ilosc wszystkich osi j.w.}
BearingType: byte; {lozyska: 0 - slizgowe, 1 - toczne}
ADist, BDist: real; {odlegosc osi oraz czopow skretu}
{hamulce:}
NBpA : byte; {ilosc el. ciernych na os: 0 1 2 lub 4}
SandCapacity: integer; {zasobnik piasku [kg]}
BrakeSystem: TBrakeSystem;{rodzaj hamulca zespolonego}
BrakeSubsystem: TBrakeSubsystem;
BrakeValve: TBrakeValve;
BrakeHandle: TBrakeHandle;
BrakeLocHandle: TBrakeHandle;
MBPM: real; {masa najwiekszego cisnienia}
Hamulec: TBrake;
Handle: THandle;
LocHandle: THandle;
Pipe, Pipe2: TReservoir;
LocalBrake: TLocalBrake; {rodzaj hamulca indywidualnego}
BrakePressureTable: TBrakePressureTable; {wyszczegolnienie cisnien w rurze}
BrakePressureActual: TBrakePressure; //wartości ważone dla aktualnej pozycji kranu
ASBType: byte; {0: brak hamulca przeciwposlizgowego, 1: reczny, 2: automat}
TurboTest: byte;
MaxBrakeForce: real; {maksymalna sila nacisku hamulca}
MaxBrakePress: array[0..4] of real; //pomocniczy, proz, sred, lad, pp
P2FTrans: real;
TrackBrakeForce: real; {sila nacisku hamulca szynowego}
BrakeMethod: byte; {flaga rodzaju hamulca}
{max. cisnienie w cyl. ham., stala proporcjonalnosci p-K}
HighPipePress,LowPipePress,DeltaPipePress: real;
{max. i min. robocze cisnienie w przewodzie glownym oraz roznica miedzy nimi}
CntrlPipePress: real; //ciśnienie z zbiorniku sterującym
BrakeVolume, BrakeVVolume, VeselVolume: real;
{pojemnosc powietrza w ukladzie hamulcowym, w ukladzie glownej sprezarki [m^3] }
BrakeCylNo: integer; {ilosc cylindrow ham.}
BrakeCylRadius, BrakeCylDist: real;
BrakeCylMult: array[0..2] of real;
LoadFlag: byte;
{promien cylindra, skok cylindra, przekladnia hamulcowa}
BrakeCylSpring: real; {suma nacisku sprezyn powrotnych, kN}
BrakeSlckAdj: real; {opor nastawiacza skoku tloka, kN}
BrakeRigEff: real; {sprawnosc przekladni dzwigniowej}
RapidMult: real; {przelozenie rapidu}
BrakeValveSize: integer;
BrakeValveParams: string;
Spg: real;
MinCompressor,MaxCompressor,CompressorSpeed:real;
{cisnienie wlaczania, zalaczania sprezarki, wydajnosc sprezarki}
BrakeDelay: TBrakeDelayTable; {opoznienie hamowania/odhamowania t/o}
BrakeCtrlPosNo:byte; {ilosc pozycji hamulca}
{nastawniki:}
MainCtrlPosNo: byte; {ilosc pozycji nastawnika}
ScndCtrlPosNo: byte;
LightsPosNo, LightsDefPos: byte;
LightsWrap: boolean;
Lights: array [0..1] of array [1..16] of byte;
ScndInMain: boolean; {zaleznosc bocznika od nastawnika}
MBrake: boolean; {Czy jest hamulec reczny}
StopBrakeDecc: real;
SecuritySystem: TSecuritySystem;
{-sekcja parametrow dla lokomotywy elektrycznej}
RList: TSchemeTable; {lista rezystorow rozruchowych i polaczen silnikow, dla dizla: napelnienia}
RlistSize: integer;
MotorParam: array[0..MotorParametersArraySize] of TMotorParameters;
{rozne parametry silnika przy bocznikowaniach}
{dla lokomotywy spalinowej z przekladnia mechaniczna: przelozenia biegow}
Transmision : TTransmision;
// record {liczba zebow przekladni}
// NToothM, NToothW : byte;
// Ratio: real; {NToothW/NToothM}
// end;
NominalVoltage: real; {nominalne napiecie silnika}
WindingRes : real;
u: real; //wspolczynnik tarcia yB wywalic!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
CircuitRes : real; {rezystancje silnika i obwodu}
IminLo,IminHi: integer; {prady przelacznika automatycznego rozruchu, uzywane tez przez ai_driver}
ImaxLo,ImaxHi: integer; {maksymalny prad niskiego i wysokiego rozruchu}
nmax: real; {maksymalna dop. ilosc obrotow /s}
InitialCtrlDelay, {ile sek. opoznienia po wl. silnika}
CtrlDelay: real; { -//- -//- miedzy kolejnymi poz.}
CtrlDownDelay: real; { -//- -//- przy schodzeniu z poz.} {hunter-101012}
FastSerialCircuit: byte;{0 - po kolei zamyka styczniki az do osiagniecia szeregowej, 1 - natychmiastowe wejscie na szeregowa} {hunter-111012}
AutoRelayType: byte; {0 -brak, 1 - jest, 2 - opcja}
CoupledCtrl: boolean; {czy mainctrl i scndctrl sa sprzezone}
//CouplerNr: TCouplerNr; {ABu: nr sprzegu podlaczonego w drugim obiekcie}
IsCoupled: boolean; {czy jest sprzezony ale jedzie z tylu}
DynamicBrakeType: byte; {patrz dbrake_*}
RVentType: byte; {0 - brak, 1 - jest, 2 - automatycznie wlaczany}
RVentnmax: real; {maks. obroty wentylatorow oporow rozruchowych}
RVentCutOff: real; {rezystancja wylaczania wentylatorow dla RVentType=2}
CompressorPower: integer; {0: bezp. z obwodow silnika, 1: z przetwornicy, reczne, 2: w przetwornicy, stale, 5: z silnikowego}
SmallCompressorPower: integer; {Winger ZROBIC}
Trafo: boolean; {pojazd wyposażony w transformator}
{-sekcja parametrow dla lokomotywy spalinowej z przekladnia mechaniczna}
dizel_Mmax, dizel_nMmax, dizel_Mnmax, dizel_nmax, dizel_nominalfill: real;
{parametry aproksymacji silnika spalinowego}
dizel_Mstand: real; {moment oporow ruchu silnika dla enrot=0}
{ dizel_auto_min, dizel_auto_max: real; {predkosc obrotowa przelaczania automatycznej skrzyni biegow}
dizel_nmax_cutoff: real; {predkosc obrotowa zadzialania ogranicznika predkosci}
dizel_nmin: real; {najmniejsza dopuszczalna predkosc obrotowa}
dizel_minVelfullengage: real; {najmniejsza predkosc przy jezdzie ze sprzeglem bez poslizgu}
dizel_AIM: real; {moment bezwladnosci walu itp}
dizel_engageDia, dizel_engageMaxForce, dizel_engagefriction: real; {parametry sprzegla}
{- dla lokomotyw spalinowo-elektrycznych -}
AnPos: real; // pozycja sterowania dokladnego (analogowego)
AnalogCtrl: boolean; //
AnMainCtrl: boolean; //
ShuntModeAllow: boolean;
ShuntMode: boolean;
Flat: boolean;
Vhyp: real;
DElist: TDESchemeTable;
Vadd: real;
MPTRelay: TMPTRelayTable;
RelayType: byte;
SST: TShuntSchemeTable;
PowerCorRatio: real; //Wspolczynnik korekcyjny
{- dla uproszczonego modelu silnika (dumb) oraz dla drezyny}
Ftmax:real;
{- dla lokomotyw z silnikami indukcyjnymi -}
eimc: array [0..25] of real;
{-dla wagonow}
MaxLoad: longint; {masa w T lub ilosc w sztukach - ladownosc}
LoadAccepted, LoadQuantity: string; {co moze byc zaladowane, jednostki miary}
OverLoadFactor: real; {ile razy moze byc przekroczona ladownosc}
LoadSpeed,UnLoadSpeed: real;{szybkosc na- i rozladunku jednostki/s}
DoorOpenCtrl,DoorCloseCtrl: byte; {0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)}
DoorStayOpen: real; {jak dlugo otwarte w przypadku DoorCloseCtrl=2}
DoorClosureWarning: boolean; {czy jest ostrzeganie przed zamknieciem}
DoorOpenSpeed, DoorCloseSpeed: real; {predkosc otwierania i zamykania w j.u. }
DoorMaxShiftL,DoorMaxShiftR,DoorMaxPlugShift: real;{szerokosc otwarcia lub kat}
DoorOpenMethod: byte; {sposob otwarcia - 1: przesuwne, 2: obrotowe, 3: trójelementowe}
PlatformSpeed: real; {szybkosc stopnia}
PlatformMaxShift: real; {wysuniecie stopnia}
PlatformOpenMethod: byte; {sposob animacji stopnia}
ScndS: boolean; {Czy jest bocznikowanie na szeregowej}
{--sekcja zmiennych}
{--opis konkretnego egzemplarza taboru}
Loc: TLocation; //pozycja pojazdów do wyznaczenia odległości pomiędzy sprzęgami
Rot: TRotation;
Name: string; {nazwa wlasna}
Couplers: array[0..1] of TCoupling; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
HVCouplers: array[0..1] of array[0..1] of real; //przewod WN
ScanCounter: integer; {pomocnicze do skanowania sprzegow}
EventFlag: boolean; {!o true jesli cos nietypowego sie wydarzy}
SoundFlag: byte; {!o patrz stale sound_ }
DistCounter: real; {! licznik kilometrow }
V: real; //predkosc w [m/s] względem sprzęgów (dodania gdy jedzie w stronę 0)
Vel: real; //moduł prędkości w [km/h], używany przez AI
AccS: real; //efektywne przyspieszenie styczne w [m/s^2] (wszystkie siły)
AccN: real; //przyspieszenie normalne w [m/s^2]
AccV: real;
nrot: real;
{! rotacja kol [obr/s]}
EnginePower: real; {! chwilowa moc silnikow}
dL, Fb, Ff : real; {przesuniecie, sila hamowania i tarcia}
FTrain,FStand: real; {! sila pociagowa i oporow ruchu}
FTotal: real; {! calkowita sila dzialajaca na pojazd}
UnitBrakeForce: real; {!s siła hamowania przypadająca na jeden element}
Ntotal: real; {!s siła nacisku klockow}
SlippingWheels,SandDose: boolean; {! poslizg kol, sypanie piasku}
Sand: real; {ilosc piasku}
BrakeSlippingTimer:real; {pomocnicza zmienna do wylaczania przeciwposlizgu}
dpBrake,dpPipe,dpMainValve,dpLocalValve: real;
{! przyrosty cisnienia w kroku czasowym}
ScndPipePress: real; {cisnienie w przewodzie zasilajacym}
BrakePress:real; {!o cisnienie w cylindrach hamulcowych}
LocBrakePress:real; {!o cisnienie w cylindrach hamulcowych z pomocniczego}
PipeBrakePress:real; {!o cisnienie w cylindrach hamulcowych z przewodu}
PipePress: real; {!o cisnienie w przewodzie glownym}
EqvtPipePress: real; {!o cisnienie w przewodzie glownym skladu}
Volume: real; {objetosc spr. powietrza w zbiorniku hamulca}
CompressedVolume:real; {objetosc spr. powietrza w ukl. zasilania}
PantVolume:real; {objetosc spr. powietrza w ukl. pantografu}
Compressor: real; {! cisnienie w ukladzie zasilajacym}
CompressorFlag: boolean; {!o czy wlaczona sprezarka}
PantCompFlag: boolean; {!o czy wlaczona sprezarka pantografow}
CompressorAllow: boolean; {! zezwolenie na uruchomienie sprezarki NBMX}
ConverterFlag: boolean; {! czy wlaczona przetwornica NBMX}
ConverterAllow: boolean; {zezwolenie na prace przetwornicy NBMX}
BrakeCtrlPos:integer; {nastawa hamulca zespolonego}
BrakeCtrlPosR:real; {nastawa hamulca zespolonego - plynna dla FV4a}
BrakeCtrlPos2:real; {nastawa hamulca zespolonego - kapturek dla FV4a}
LocalBrakePos:byte; {nastawa hamulca indywidualnego}
ManualBrakePos:byte; {nastawa hamulca recznego}
LocalBrakePosA: real;
BrakeStatus: byte; {0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R}
EmergencyBrakeFlag: boolean; {hamowanie nagle}
BrakeDelayFlag: byte; {nastawa opoznienia ham. osob/towar/posp/exp 0/1/2/4}
BrakeDelays: byte; {nastawy mozliwe do uzyskania}
BrakeOpModeFlag: byte; {nastawa trybu pracy PS/PN/EP/MED 1/2/4/8}
BrakeOpModes: byte; {nastawy mozliwe do uzyskania}
DynamicBrakeFlag: boolean; {czy wlaczony hamulec elektrodymiczny}
// NapUdWsp: integer;
LimPipePress: real; {stabilizator cisnienia}
ActFlowSpeed: real; {szybkosc stabilizatora}
DamageFlag: byte; //kombinacja bitowa stalych dtrain_* }
EngDmgFlag: byte; //kombinacja bitowa stalych usterek}
DerailReason: byte; //przyczyna wykolejenia
//EndSignalsFlag: byte; {ABu 060205: zmiany - koncowki: 1/16 - swiatla prz/tyl, 2/31 - blachy prz/tyl}
//HeadSignalsFlag: byte; {ABu 060205: zmiany - swiatla: 1/2/4 - przod, 16/32/63 - tyl}
CommandIn: TCommand;
{komenda przekazywana przez PutCommand}
{i wykonywana przez RunInternalCommand}
CommandOut: string; {komenda przekazywana przez ExternalCommand}
CommandLast: string; //Ra: ostatnio wykonana komenda do podglądu
ValueOut: real; {argument komendy która ma byc przekazana na zewnatrz}
RunningShape:TTrackShape;{geometria toru po ktorym jedzie pojazd}
RunningTrack:TTrackParam;{parametry toru po ktorym jedzie pojazd}
OffsetTrackH, OffsetTrackV: real; {przesuniecie poz. i pion. w/m osi toru}
{-zmienne dla lokomotyw}
Mains: boolean; {polozenie glownego wylacznika}
MainCtrlPos: byte; {polozenie glownego nastawnika}
ScndCtrlPos: byte; {polozenie dodatkowego nastawnika}
LightsPos: byte;
ActiveDir: integer; //czy lok. jest wlaczona i w ktorym kierunku:
//względem wybranej kabiny: -1 - do tylu, +1 - do przodu, 0 - wylaczona
CabNo: integer; //numer kabiny, z której jest sterowanie: 1 lub -1; w przeciwnym razie brak sterowania - rozrzad
DirAbsolute: integer; //zadany kierunek jazdy względem sprzęgów (1=w strone 0,-1=w stronę 1)
ActiveCab: integer; //numer kabiny, w ktorej jest obsada (zwykle jedna na skład)
LastSwitchingTime: real; {czas ostatniego przelaczania czegos}
//WarningSignal: byte; {0: nie trabi, 1,2: trabi}
DepartureSignal: boolean; {sygnal odjazdu}
InsideConsist: boolean;
{-zmienne dla lokomotywy elektrycznej}
RunningTraction:TTractionParam;{parametry sieci trakcyjnej najblizej lokomotywy}
enrot, Im, Itot,IHeating,ITraction, TotalCurrent, Mm, Mw, Fw, Ft: real;
{ilosc obrotow, prad silnika i calkowity, momenty, sily napedne}
//Ra: Im jest ujemny, jeśli lok jedzie w stronę sprzęgu 1
//a ujemne powinien być przy odwróconej polaryzacji sieci...
//w wielu miejscach jest używane abs(Im)
Imin,Imax: integer; {prad przelaczania automatycznego rozruchu, prad bezpiecznika}
Voltage: real; {aktualne napiecie sieci zasilajacej}
MainCtrlActualPos: byte; {wskaznik RList}
ScndCtrlActualPos: byte; {wskaznik MotorParam}
DelayCtrlFlag: boolean; //czy czekanie na 1. pozycji na załączenie?
LastRelayTime: real; {czas ostatniego przelaczania stycznikow}
AutoRelayFlag: boolean; {mozna zmieniac jesli AutoRelayType=2}
FuseFlag: boolean; {!o bezpiecznik nadmiarowy}
ConvOvldFlag: boolean; {! nadmiarowy przetwornicy i ogrzewania}
StLinFlag: boolean; {!o styczniki liniowe}
ResistorsFlag: boolean; {!o jazda rezystorowa}
RventRot: real; {!s obroty wentylatorow rozruchowych}
UnBrake: boolean; {w EZT - nacisniete odhamowywanie}
PantPress: real; {Cisnienie w zbiornikach pantografow}
s_CAtestebrake: boolean; //hunter-091012: zmienna dla testu ca
{-zmienne dla lokomotywy spalinowej z przekladnia mechaniczna}
dizel_fill: real; {napelnienie}
dizel_engagestate: real; {sprzeglo skrzyni biegow: 0 - luz, 1 - wlaczone, 0.5 - wlaczone 50% (z poslizgiem)}
dizel_engage: real; {sprzeglo skrzyni biegow: aktualny docisk}
dizel_automaticgearstatus: real; {0 - bez zmiany, -1 zmiana na nizszy +1 zmiana na wyzszy}
dizel_enginestart: boolean; {czy trwa rozruch silnika}
dizel_engagedeltaomega: real; {roznica predkosci katowych tarcz sprzegla}
{- zmienne dla lokomotyw z silnikami indukcyjnymi -}
eimv: array [0..20] of real;
{-zmienne dla drezyny}
PulseForce :real; {przylozona sila}
PulseForceTimer: real;
PulseForceCount: integer;
{dla drezyny, silnika spalinowego i parowego}
eAngle: real;
{-dla wagonow}
Load: longint; {masa w T lub ilosc w sztukach - zaladowane}
LoadType: string; {co jest zaladowane}
LoadStatus: byte; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
LastLoadChangeTime: real; //raz (roz)ładowania
DoorBlocked: boolean; //Czy jest blokada drzwi
DoorLeftOpened: boolean; //stan drzwi
DoorRightOpened: boolean;
PantFrontUp: boolean; //stan patykow 'Winger 160204
PantRearUp: boolean;
PantFrontSP: boolean; //dzwiek patykow 'Winger 010304
PantRearSP: boolean;
PantFrontStart: integer; //stan patykow 'Winger 160204
PantRearStart: integer;
PantFrontVolt: real; //pantograf pod napieciem? 'Winger 160404
PantRearVolt: real;
PantSwitchType: string;
ConvSwitchType: string;
Heating: boolean; //ogrzewanie 'Winger 020304
DoubleTr: integer; //trakcja ukrotniona - przedni pojazd 'Winger 160304
PhysicActivation: boolean;
{ABu: stale dla wyznaczania sil (i nie tylko) po optymalizacji}
FrictConst1: real;
FrictConst2s: real;
FrictConst2d: real;
TotalMassxg : real; {TotalMass*g}
{--funkcje}
function GetTrainsetVoltage: real;
function Physic_ReActivation: boolean;
{ function BrakeRatio: real; }
function LocalBrakeRatio: real;
function ManualBrakeRatio: real;
function PipeRatio: real; {ile napelniac}
function RealPipeRatio: real; {jak szybko}
function BrakeVP: real;
function DynamicBrakeSwitch(Switch:boolean):boolean;
{! przesylanie komend sterujacych}
function SendCtrlBroadcast(CtrlCommand:string; ctrlvalue:real):boolean;
function SendCtrlToNext(CtrlCommand:string;ctrlvalue,dir:real):boolean;
function CabActivisation:boolean;
function CabDeactivisation:boolean;
{! funkcje zwiekszajace/zmniejszajace nastawniki}
{! glowny nastawnik:}
function IncMainCtrl(CtrlSpeed:integer): boolean;
function DecMainCtrl(CtrlSpeed:integer): boolean;
{! pomocniczy nastawnik:}
function IncScndCtrl(CtrlSpeed:integer): boolean;
function DecScndCtrl(CtrlSpeed:integer): boolean;
function AddPulseForce(Multipler:integer): boolean; {dla drezyny}
{wlacza/wylacza sypanie piasku}
function SandDoseOn : boolean;
{! zbijanie czuwaka/SHP}
function SecuritySystemReset:boolean;
{test czuwaka/SHP}
procedure SecuritySystemCheck(dt:real);
function BatterySwitch(State:boolean):boolean;
function EpFuseSwitch(State:boolean):boolean;
{! stopnie hamowania - hamulec zasadniczy}
function IncBrakeLevelOld:boolean;
function DecBrakeLevelOld:boolean;
{! stopnie hamowania - hamulec pomocniczy}
function IncLocalBrakeLevel(CtrlSpeed:byte):boolean;
function DecLocalBrakeLevel(CtrlSpeed:byte):boolean;
{! ABu 010205: - skrajne polozenia ham. pomocniczego}
function IncLocalBrakeLevelFAST:boolean;
function DecLocalBrakeLevelFAST:boolean;
{! stopnie hamowania - hamulec reczny}
function IncManualBrakeLevel(CtrlSpeed:byte):boolean;
function DecManualBrakeLevel(CtrlSpeed:byte):boolean;
{! hamulec bezpieczenstwa}
function EmergencyBrakeSwitch(Switch:boolean): boolean;
{hamulec przeciwposlizgowy}
function AntiSlippingBrake: boolean;
{odluzniacz}
function BrakeReleaser(state: byte):boolean;
function SwitchEPBrake(state: byte):boolean;
{! reczny wlacznik urzadzen antyposlizgowych}
function AntiSlippingButton: boolean;
{funkcje dla ukladow pneumatycznych}
function IncBrakePress(var brake:real;PressLimit,dp:real):boolean;
function DecBrakePress(var brake:real;PressLimit,dp:real):boolean;
function BrakeDelaySwitch(BDS:byte): boolean; {! przelaczanie nastawy opoznienia}
function IncBrakeMult(): boolean; {przelaczanie prozny/ladowny}
function DecBrakeMult(): boolean;
{pomocnicze funkcje dla ukladow pneumatycznych}
procedure UpdateBrakePressure(dt: real);
procedure UpdatePipePressure(dt:real);
procedure CompressorCheck(dt:real); {wlacza, wylacza kompresor, laduje zbiornik}
procedure UpdateScndPipePressure(dt:real);
//procedure UpdateBatteryVoltage(dt:real);
function GetDVc(dt:real):real;
{! funkcje laczace/rozlaczajace sprzegi}
//Ra: przeniesione do C++
{funkcje obliczajace sily}
procedure ComputeConstans; //ABu: wczesniejsze wyznaczenie stalych dla liczenia sil
//procedure SetCoupleDist; //ABu: wyznaczenie odleglosci miedzy wagonami
function ComputeMass:real;
function Adhesive(staticfriction:real): real;
function TractionForce(dt:real):real;
function FrictionForce(R:real;TDamage:byte):real;
function BrakeForce(Track:TTrackParam):real;
function CouplerForce(CouplerN:byte; dt:real):real;
procedure CollisionDetect(CouplerN:byte; dt:real);
{obrot kol uwzgledniajacy poslizg}
function ComputeRotatingWheel(WForce,dt,n:real): real;
{komendy}
function SetInternalCommand(NewCommand:string; NewValue1,NewValue2:real):boolean;
{! do wpisywania komend przez zewnetrzne zdarzenia}
function GetExternalCommand(var Command:string):real;
function RunCommand(command:string; CValue1,CValue2:real):boolean;
function RunInternalCommand:boolean;
procedure PutCommand(NewCommand:string; NewValue1,NewValue2:real; NewLocation:TLocation);
{--funkcje dla lokomotyw}
{! kierunek ruchu}
//function DirectionForward: boolean;
function DirectionBackward: boolean;
{! wylacznik glowny}
function MainSwitch(State:boolean): boolean;
// procedure SwitchMainKey;
{! zmiana kabiny i resetowanie ustawien}
//function ChangeCab(direction:integer): boolean;
{! wl/wyl przetwornicy}
function ConverterSwitch(State:boolean):boolean;
{! wl/wyl sprezarki}
function CompressorSwitch(State:boolean):boolean;
{ function SmallCompressorSwitch(State:boolean):boolean;}
{procedure ConverterCheck; ->C++}
{-funkcje typowe dla lokomotywy elektrycznej}
{! wlaczanie bezpiecznika nadmiarowego}
function FuseOn: boolean;
function FuseFlagCheck: boolean; {sprawdzanei flagi nadmiarowego}
procedure FuseOff; {wywalanie bezpiecznika nadmiarowego}
{!o pokazuje bezwgl. wartosc pradu na wybranym amperomierzu}
function ShowCurrent(AmpN:byte): integer;
{!o pokazuje bezwgl. wartosc obrotow na obrotomierzu jednego z 3 pojazdow}
{function ShowEngineRotation(VehN:byte): integer; //Ra 2014-06: przeniesione do C++}
{funkcje uzalezniajace sile pociagowa od predkosci: v2n, n2r, current, momentum}
function v2n:real;
function current(n,U:real): real;
function Momentum(I:real): real;
function MomentumF(I, Iw :real; SCP:byte ): real;
{! odlaczanie uszkodzonych silnikow}
function CutOffEngine: boolean;
{! przelacznik pradu wysokiego rozruchu}
function MaxCurrentSwitch(State:boolean):boolean;
{sprawdzanie kontrolki rezystorow rozrochowych NBMX}
function ResistorsFlagCheck: boolean;
{! przelacznik pradu automatycznego rozruchu}
function MinCurrentSwitch(State:boolean):boolean;
{! przelacznik automatycznego rozruchu}
function AutoRelaySwitch(State:boolean):boolean;
{symulacja automatycznego rozruchu}
function AutoRelayCheck: boolean;
{-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna}
function dizel_EngageSwitch(state: real): boolean;
function dizel_EngageChange(dt: real): boolean;
function dizel_AutoGearCheck: boolean;
function dizel_fillcheck(mcp:byte): real;
{ function dizel_rotateengine(Momentum,dt,n,engage:real): real; }
function dizel_Momentum(dizel_fill,n,dt:real): real;
function dizel_Update(dt:real): boolean;
{-funkcje dla wagonow}
function LoadingDone(LSpeed: real; LoadInit:string):boolean;
{! WAZNA FUNKCJA - oblicza sile wypadkowa}
procedure ComputeTotalForce(dt: real; dt1: real; FullVer: boolean);
{! BARDZO WAZNA FUNKCJA - oblicza przesuniecie lokomotywy lub wagonu}
function ComputeMovement(dt:real; dt1:real; Shape:TTrackShape; var Track:TTrackParam; var ElectricTraction:TTractionParam; NewLoc:TLocation; var NewRot:TRotation):real;
{dt powinno byc 10ms lub mniejsze}
{NewRot na wejsciu daje aktualna orientacje pojazdu, na wyjsciu daje dodatkowe wychylenia od tej orientacji}
{! JESZCZE WAZNIEJSZA FUNKCJA - ABu: - mocno zoptymalizowanana ComputeMovement}
function FastComputeMovement(dt:real; Shape:TTrackShape; var Track:TTrackParam; NewLoc:TLocation; var NewRot:TRotation):real; //Shape:TTrackShape; var Track:TTrackParam; var ElectricTraction:TTractionParam; NewLoc:TLocation; var NewRot:TRotation):real;
{dt powinno byc 10ms lub mniejsze}
{NewRot na wejsciu daje aktualna orientacje pojazdu, na wyjsciu daje dodatkowe wychylenia od tej orientacji}
{dla samochodow}
function ChangeOffsetH(DeltaOffset:real): boolean;
{! procedury I/O}
constructor Init(//LocInitial:TLocation; RotInitial:TRotation;
VelInitial:real; TypeNameInit, NameInit: string; LoadInitial:longint; LoadTypeInitial: string; Cab:integer);
{wywolac najpierw to}
function LoadChkFile(chkpath:string):Boolean; {potem zaladowac z pliku}
function CheckLocomotiveParameters(ReadyFlag:boolean;Dir:longint): boolean; {a nastepnie sprawdzic}
function EngineDescription(what:integer): string; {opis stanu lokomotywy}
{obsluga drzwi}
function DoorLeft(State: Boolean): Boolean; {obsluga dzwi lewych}
function DoorRight(State: Boolean): Boolean;
function DoorBlockedFlag: Boolean; //czy blokada drzwi jest aktualnie załączona
{obsluga pantografow - Winger 160204}
function PantFront(State: Boolean): Boolean;
function PantRear(State: Boolean): Boolean;
{ogrzewanie - Winger 020304}
//function Heating(State: Boolean): Boolean;
//private
//function TotalMass:real;
{ function GetFTotal(CN:byte): real;
function GetMass(CN:byte): real;
procedure SendAVL(AccS,AccN,V,dL:real; CN:byte); }
end; {ufff}
function Distance(Loc1,Loc2: TLocation; Dim1,Dim2:TDimension) : real;
{----------------------------------------------------------------}
{========================McZapkie'2001===========================}
{----------------------------------------------------------------}
implementation
const
Steel2Steel_friction=0.15; {tarcie statyczne}
g=9.81; {przyspieszenie ziemskie}
SandSpeed=0.1; {ile kg/s}
RVentSpeed=0.4; {rozpedzanie sie wentylatora obr/s^2}
RVentMinI=50.0; {przy jakim pradzie sie wylaczaja}
CouplerTune:real=0.1; {skalowanie tlumiennosci}
Pirazy2=Pi*2;
{------------------------------------------}
{funkcje pomocnicze}
function s2NPW(s:string):byte;
{wylicza ilosc osi napednych ze stringu opisujacego uklad osi}
{np. 2'A' daje 1, Bo'Bo' daje 4, 1'E daje 5 itp}
const A=ord('A')-1;
var k,NPW:byte;
begin
NPW:=0;
for k:=1 to Length(s) do
begin
if s[k] in ['A'..'Z'] then
NPW:=NPW+Ord(s[k])-A;
end;
s2NPW:=NPW;
end;
function s2NNW(s:string):byte;
{wylicza ilosc osi nienapednych ze stringu opisujacego uklad osi}
{np. 2'A' daje 2, Bo'Bo' daje 0, 1'E daje 1 itp}
const Zero=ord('0');
var k,NNW:byte;
begin
NNW:=0;
for k:=1 to Length(s) do
begin
if s[k] in ['1'..'9'] then
NNW:=NNW+Ord(s[k])-Zero;
end;
s2NNW:=NNW;
end;
function Distance(Loc1,Loc2:TLocation;Dim1,Dim2:TDimension):real;
//zwraca odległość pomiędzy pojazdami (Loc1) i (Loc2) z uwzględnieneim ich długości (kule!)
var Dist:real;
begin
Dist:=SQRT(SQR(Loc2.x-Loc1.x)+SQR(Loc1.y-Loc2.y));
Distance:=Dist-Dim2.L/2.0-Dim1.L/2.0;
{ Distance:=Hypot(Loc2.x-Loc1.x,Loc2.y-Loc1.y)-(Dim2.L+Dim1.L)/2; }
end;
{oblicza zmiane predkosci i przyrost pedu wskutek kolizji}
function ComputeCollision(var v1,v2:real; m1,m2,beta:real;vc:boolean):real;
var CCP,w1,w2,m1m2:real;
begin
if (v1<v2) and vc then
CCP:=0
else
begin
m1m2:=m1+m2;
w1:=((m1-m2)*v1+2*m2*v2)/m1m2;
w2:=((m2-m1)*v2+2*m1*v1)/m1m2;
v1:=w1*sqrt(1-beta); {niejawna zmiana predkosci wskutek zderzenia}
v2:=w2*sqrt(1-beta);
CCP:=m1*(w2-w1)*(1-beta);
end;
ComputeCollision:=CCP;
end;
{-----zderzaki,sprzegi----}
{poprawka dla liczenia sil przy ustawieniu przeciwnym obiektow:}
function DirPatch(Coupler1:byte; Coupler2:byte): real;
begin
if (Coupler1<>Coupler2) then DirPatch:=1
else DirPatch:=-1;
end;
function DirF(CouplerN:byte): real;
begin
case CouplerN of
0: DirF:=-1;
1: DirF:=1
else DirF:=0;
end;
end;
{yB: funkcje dodatkowe hamulcowe}
function PR(p1,p2:real): real;
var ph,pl:real;
begin
ph:=Max0R(p1,p2)+0.1;
pl:=p1+p2-ph+0.2;
PR:=(ph-pl)/(1.13*ph-pl);
end;
function SPR(ph,pl:real): real;
begin
SPR:=0.674*(ph-pl)/(1.13*ph-pl+0.013);
end;
{---------rozwiniecie deklaracji metod obiektu T_MoverParameters--------}
(*
function T_MoverParameters.GetTrainsetVoltage: real;
//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
var volt: real;
begin
volt:=0.0;
if Couplers[1].Connected<>nil then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_power)) then //czy jest sprzęg WN
begin //najczęściej silnikowy jest z tyłu
if (Couplers[1].Connected.PantFrontVolt<>0.0) then
volt:=Couplers[1].Connected.PantFrontVolt
else
if (Couplers[1].Connected.PantRearVolt<>0.0) then
volt:=Couplers[1].Connected.PantRearVolt;
end;
if (volt=0.0) then
if Couplers[0].Connected<>nil then
if (TestFlag(Couplers[0].CouplingFlag,ctrain_power)) then //czy jest sprzęg WN
begin
if (Couplers[0].Connected.PantFrontVolt<>0.0) then
volt:=Couplers[0].Connected.PantFrontVolt
else
if (Couplers[0].Connected.PantRearVolt<>0.0) then
volt:=Couplers[0].Connected.PantRearVolt;
end;
GetTrainsetVoltage:=volt;
end;
*)
function T_MoverParameters.GetTrainsetVoltage: real;
//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
//var volt: real;
begin
GetTrainsetVoltage:=Max0R(HVCouplers[1][1],HVCouplers[0][1]);
end;
function T_MoverParameters.Physic_ReActivation: boolean;
begin
if PhysicActivation then
Physic_Reactivation:=false
else
begin
PhysicActivation:=true;
LastSwitchingTime:=0;
Physic_Reactivation:=true;
end;
end;
{stosunek obecnego nastawienia sily hamowania do maksymalnej nastawy}
{
function T_MoverParameters.BrakeRatio: real;
begin
if BrakeCtrlPosNo>0 then
begin
if BrakeCtrlPos<0 then
BrakeRatio:=1
else
BrakeRatio:=1-BrakeCtrlPos/BrakeCtrlPosNo
end
else
BrakeRatio:=0;
end;
}
function T_MoverParameters.LocalBrakeRatio: real;
var LBR:real;
begin
if BrakeHandle=MHZ_EN57 then
if (BrakeOpModeFlag>=bom_EP) then
LBR:=(Handle as TMHZ_EN57).GetEP(BrakeCtrlPosR)
else
LBR:=0
else
if LocalBrakePosNo>0 then
LBR:=LocalBrakePos/LocalBrakePosNo
else
LBR:=0;
// if TestFlag(BrakeStatus,b_antislip) then
// LBR:=Max0R(LBR,PipeRatio)+0.4;
LocalBrakeRatio:=LBR;
end;
function T_MoverParameters.ManualBrakeRatio: real;
var MBR:real;
begin
if ManualBrakePosNo>0 then
MBR:=ManualBrakePos/ManualBrakePosNo
else
MBR:=0;
ManualBrakeRatio:=MBR;
end;
function T_MoverParameters.PipeRatio: real;
var pr:real;
begin
if DeltaPipePress>0 then
if (false) then //SPKS!!
begin
if (3*PipePress)>(HighPipePress+LowPipePress+LowPipePress) then
pr:=(HighPipePress-Min0R(HighPipePress,PipePress))/(DeltaPipePress*4.0/3.0)
else
pr:=(HighPipePress-1.0/3.0*DeltaPipePress-Max0R(LowPipePress,PipePress))/(DeltaPipePress*2.0/3.0);
// if (not TestFlag(BrakeStatus,b_Ractive)) and (BrakeMethod and 1 = 0) and TestFlag(BrakeDelays,bdelay_R) and (Power<1) and (BrakeCtrlPos<1) then
// pr:=Min0R(0.5,pr);
//if (Compressor>0.5) then
// pr:=pr*1.333; //dziwny rapid wywalamy
end
else
pr:=(HighPipePress-Max0R(LowPipePress,Min0R(HighPipePress,PipePress)))/DeltaPipePress
else
pr:=0;
PipeRatio:=pr;
end;
function T_MoverParameters.RealPipeRatio: real;
var rpp:real;
begin
if DeltaPipePress>0 then
rpp:=(CntrlPipePress-PipePress)/(DeltaPipePress)
else
rpp:=0;
RealPipeRatio:=rpp;
end;
function T_MoverParameters.BrakeVP: real;
begin
if BrakeVVolume>0 then
BrakeVP:=Volume/(10.0*BrakeVVolume)
else BrakeVP:=0;
end;
{reczne przelaczanie hamulca elektrodynamicznego}
function T_MoverParameters.DynamicBrakeSwitch(Switch:boolean):boolean;
var b:byte;
begin
if (DynamicBrakeType=dbrake_switch) and (MainCtrlPos=0) then
begin
DynamicBrakeFlag:=Switch;
DynamicBrakeSwitch:=true;
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
Connected.DynamicBrakeFlag:=DynamicBrakeFlag;
{end;
if (DynamicBrakeType=dbrake_passive) and (TrainType=dt_ET42) then
begin
DynamicBrakeFlag:=false;
DynamicBrakeSwitch:=false;}
end
else
DynamicBrakeSwitch:=false;
end;
function T_MoverParameters.SendCtrlBroadcast(CtrlCommand:string;ctrlvalue:real):boolean;
var b:byte; OK:boolean;
begin
OK:=((CtrlCommand<>CommandIn.Command) and (ctrlvalue<>CommandIn.Value1));
if OK then
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected.SetInternalCommand(CtrlCommand,ctrlvalue,DirF(b)) then
OK:=Connected.RunInternalCommand or OK;
SendCtrlBroadcast:=OK;
end;
function T_MoverParameters.SendCtrlToNext(CtrlCommand:string;ctrlvalue,dir:real):boolean;
//wysłanie komendy w kierunku dir (1=przod,-1=tył) do kolejnego pojazdu (jednego)
var
OK:Boolean;
d:Integer; //numer sprzęgu w kierunku którego wysyłamy
begin
//Ra: był problem z propagacją, jeśli w składzie jest pojazd wstawiony odwrotnie
//Ra: problem jest również, jeśli AI będzie na końcu składu
OK:=(dir<>0); // and Mains;
d:=(1+Sign(dir)) div 2; //dir=-1=>d=0, dir=1=>d=1 - wysyłanie tylko w tył
if OK then //musi być wybrana niezerowa kabina
with Couplers[d] do //własny sprzęg od strony (d)
if TestFlag(CouplingFlag,ctrain_controll) then
if ConnectedNr<>d then //jeśli ten nastpęny jest zgodny z aktualnym
begin
if Connected.SetInternalCommand(CtrlCommand,ctrlvalue,dir) then
OK:=Connected.RunInternalCommand and OK; //tu jest rekurencja
end
else //jeśli następny jest ustawiony przeciwnie, zmieniamy kierunek
if Connected.SetInternalCommand(CtrlCommand,ctrlvalue,-dir) then
OK:=Connected.RunInternalCommand and OK; //tu jest rekurencja
SendCtrlToNext:=OK;
end;
function T_MoverParameters.CabActivisation:boolean;
//załączenie rozrządu
var OK:boolean;
begin
OK:=(CabNo=0); //numer kabiny, z której jest sterowanie
if (OK) then
begin
CabNo:=ActiveCab; //sterowanie jest z kabiny z obsadą
DirAbsolute:=ActiveDir*CabNo;
SendCtrlToNext('CabActivisation',1,CabNo);
end;
CabActivisation:=OK;
end;
function T_MoverParameters.CabDeactivisation:boolean;
//wyłączenie rozrządu
var OK:boolean;
begin
OK:=(CabNo=ActiveCab); //o ile obsada jest w kabinie ze sterowaniem
if (OK) then
begin
CabNo:=0;
DirAbsolute:=ActiveDir*CabNo;
DepartureSignal:=false; //nie buczeć z nieaktywnej kabiny
SendCtrlToNext('CabActivisation',0,ActiveCab); //CabNo==0!
end;
CabDeactivisation:=OK;
end;
{
procedure MainCtrlBroadcast(Couplers:TCouplers; MainCtrlPos,MainCtrlActualPos:byte);
var b:byte;
begin
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
begin
Connected^.MainCtrlPos:=MainCtrlPos;
Connected^.MainCtrlActualPos:=MainCtrlActualPos;
end;
poprawic to!!!
end;
procedure ScndCtrlBroadcast(Couplers:TCouplers; ScndCtrlPos,ScndCtrlActualPos:byte);
var b:byte;
begin
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
begin
Connected^.ScndCtrlPos:=ScndCtrlPos;
Connected^.ScndCtrlActualPos:=ScndCtrlActualPos;
end;
end;
}
{funkcje zwiekszajace/zmniejszajace nastawniki}
function T_MoverParameters.IncMainCtrl(CtrlSpeed:integer): boolean;
var //b:byte;
OK:boolean;
begin
OK:=false;
if (MainCtrlPosNo>0) and (CabNo<>0) then
begin
if MainCtrlPos<MainCtrlPosNo then
begin
if (TrainType<>dt_ET22) or ((TrainType=dt_ET22) and (ScndCtrlPos=0)) then //w ET22 nie da się kręcić nastawnikiem przy włączonym boczniku
case EngineType of
None, Dumb, DieselElectric, ElectricInductionMotor:
if ((CtrlSpeed=1) and (TrainType<>dt_EZT)) or ((CtrlSpeed=1) and (TrainType=dt_EZT)and (activedir<>0)) then
begin //w EZT nie da się załączyć pozycji bez ustawienia kierunku
inc(MainCtrlPos);
OK:=true;
end
else
if ((CtrlSpeed>1) and (TrainType<>dt_EZT)) or ((CtrlSpeed>1) and (TrainType=dt_EZT)and (activedir<>0)) then
OK:=IncMainCtrl(1) and IncMainCtrl(CtrlSpeed-1);
ElectricSeriesMotor:
if (CtrlSpeed=1) and (ActiveDir<>0) then
begin
inc(MainCtrlPos);
OK:=true;
if Imax=ImaxHi then
if RList[MainCtrlPos].Bn>1 then
begin
if(TrainType=dt_ET42)then
begin
dec(MainCtrlPos);
OK:=false;
end;
if MaxCurrentSwitch(false) then
SetFlag(SoundFlag,sound_relay); {wylaczanie wysokiego rozruchu}
{ if (EngineType=ElectricSeriesMotor) and (MainCtrlPos=1) then
MainCtrlActualPos:=1;
}
end;
if (CtrlSpeed=1) and (ActiveDir=-1) and (RList[MainCtrlPos].Bn>1) and (TrainType<>dt_pseudodiesel) then
begin //blokada wejścia na równoległą podczas jazdy do tyłu
dec(MainCtrlPos);
OK:=false;
end;
{if (TrainType='et40') then
if Abs(Im)>IminHi then
begin
dec(MainCtrlPos); //Blokada nastawnika po przekroczeniu minimalnego pradu
OK:=false;
end; }
if(DynamicBrakeFlag)then
if(TrainType=dt_ET42)then
if MainCtrlPos>20 then
begin
dec(MainCtrlPos);
OK:=false;
end;
end
else
if (CtrlSpeed>1) and (ActiveDir<>0) {and (ScndCtrlPos=0)} and (TrainType<>dt_ET40) then
begin //szybkie przejście na bezoporową
while (RList[MainCtrlPos].R>0) and IncMainCtrl(1) do ;
//OK:=true ; {takie chamskie, potem poprawie} <-Ra: kto miał to poprawić i po co?
if ActiveDir=-1 then
while (RList[MainCtrlPos].Bn>1) and IncMainCtrl(1) do
dec(MainCtrlPos);
OK:=false;
{if (TrainType=dt_ET40) then
while Abs (Im)>IminHi do
dec(MainCtrlPos);
OK:=false ; }
if(DynamicBrakeFlag)then
if(TrainType=dt_ET42)then
while(MainCtrlPos>20)do
dec(MainCtrlPos);
OK:=false;
end;
DieselEngine:
if CtrlSpeed=1 then
begin
inc(MainCtrlPos);
OK:=true;
if MainCtrlPos>0 then
CompressorAllow:=true
else
CompressorAllow:=false;
end
else
if CtrlSpeed>1 then
begin
while (MainCtrlPos<MainCtrlPosNo) do
IncMainCtrl(1);
OK:=true;
end;
WheelsDriven:
OK:=AddPulseForce(CtrlSpeed);
end //case EngineType of
end
else //MainCtrlPos>=MainCtrlPosNo
if (CoupledCtrl) then //wspólny wał nastawnika jazdy i bocznikowania
begin
if (ScndCtrlPos<ScndCtrlPosNo) then //3<3 -> false
begin
inc(ScndCtrlPos);
OK:=true;
end
else OK:=false;
end;
if OK then
begin
{OK:=}SendCtrlToNext('MainCtrl',MainCtrlPos,CabNo); {???}
{OK:=}SendCtrlToNext('ScndCtrl',ScndCtrlPos,CabNo);
end;
end
else {nie ma sterowania}
OK:=false;
//if OK then LastRelayTime:=0;
//hunter-101012: poprawka
//poprzedni warunek byl niezbyt dobry, bo przez to przy trzymaniu +
//styczniki tkwily na tej samej pozycji (LastRelayTime byl caly czas 0 i rosl
//po puszczeniu plusa)
if OK then
begin
if (DelayCtrlFlag) then
begin
if (LastRelayTime>=InitialCtrlDelay)and(MainCtrlPos=1) then
LastRelayTime:=0
end
else if (LastRelayTime>CtrlDelay) then
LastRelayTime:=0;
end;
IncMainCtrl:=OK;
end;
function T_MoverParameters.DecMainCtrl(CtrlSpeed:integer): boolean;
var //b:byte;
OK:boolean;
begin
OK:=false;
if (MainCtrlPosNo>0) and (CabNo<>0) then
begin
if MainCtrlPos>0 then
begin
if ((TrainType<>dt_ET22) or (ScndCtrlPos=0)) then //Ra: ET22 blokuje nastawnik przy boczniku
begin
if CoupledCtrl and (ScndCtrlPos>0) then
begin
dec(ScndCtrlPos); {wspolny wal}
OK:=true;
end
else
case EngineType of
None, Dumb, DieselElectric, ElectricInductionMotor:
if ((CtrlSpeed=1) and {(ScndCtrlPos=0) and} (EngineType<>DieselElectric)) or ((CtrlSpeed=1)and(EngineType=DieselElectric))then
begin
dec(MainCtrlPos);
OK:=true;
end
else
if CtrlSpeed>1 then
OK:=DecMainCtrl(1) and DecMainCtrl(2); //CtrlSpeed-1);
ElectricSeriesMotor:
if (CtrlSpeed=1) {and (ScndCtrlPos=0)} then
begin
dec(MainCtrlPos);
// if (MainCtrlPos=0) and (ScndCtrlPos=0) and (TrainType<>dt_ET40)and(TrainType<>dt_EP05) then
// StLinFlag:=false;
// if (MainCtrlPos=0) and (TrainType<>dt_ET40) and (TrainType<>dt_EP05) then
// MainCtrlActualPos:=0; //yBARC: co to tutaj robi? ;)
OK:=true;
end
else
if (CtrlSpeed>1) {and (ScndCtrlPos=0)} then
begin
OK:=true;
if (RList[MainCtrlPos].R=0)
then DecMainCtrl(1);
while (RList[MainCtrlPos].R>0) and DecMainCtrl(1) do ; {takie chamskie, potem poprawie}
end;
DieselEngine:
if CtrlSpeed=1 then
begin
dec(MainCtrlPos);
OK:=true;
end
else
if CtrlSpeed>1 then
begin
while (MainCtrlPos>0) or (RList[MainCtrlPos].Mn>0) do
DecMainCtrl(1);
OK:=true;
end;
end;
end;
end
else
if EngineType=WheelsDriven then
OK:=AddPulseForce(-CtrlSpeed)
else
OK:=false;
if OK then
begin
{OK:=}SendCtrlToNext('MainCtrl',MainCtrlPos,CabNo); {hmmmm...???!!!}
{OK:=}SendCtrlToNext('ScndCtrl',ScndCtrlPos,CabNo);
end;
end
else
OK:=false;
//if OK then LastRelayTime:=0;
//hunter-101012: poprawka
if OK then
begin
if DelayCtrlFlag then
begin
if (LastRelayTime>=InitialCtrlDelay) then
LastRelayTime:=0;
end
else if (LastRelayTime>CtrlDownDelay) then
LastRelayTime:=0;
end;
DecMainCtrl:=OK;
end;
function T_MoverParameters.IncScndCtrl(CtrlSpeed:integer): boolean;
var //b:byte;
OK:boolean;
begin
if (MainCtrlPos=0)and(CabNo<>0)and(TrainType=dt_ET42)and(ScndCtrlPos=0)and(DynamicBrakeFlag)then
begin
OK:=DynamicBrakeSwitch(false);
end
else
if (ScndCtrlPosNo>0) and (CabNo<>0) and not ((TrainType=dt_ET42)and((Imax=ImaxHi)or((DynamicBrakeFlag)and(MainCtrlPos>0)))) then
begin
{ if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos<ScndCtrlPosNo) and (not CoupledCtrl) then}
if (ScndCtrlPos<ScndCtrlPosNo) and (not CoupledCtrl) and ((EngineType<>DieselElectric) or (not AutoRelayFlag)) then
begin
if CtrlSpeed=1 then
begin
inc(ScndCtrlPos);
end
else
if CtrlSpeed>1 then
begin
ScndCtrlPos:=ScndCtrlPosNo; {takie chamskie, potem poprawie}
end;
OK:=true;
end
else {nie mozna zmienic}
OK:=false;
if OK then
begin
{OK:=}SendCtrlToNext('MainCtrl',MainCtrlPos,CabNo); {???}
{OK:=}SendCtrlToNext('ScndCtrl',ScndCtrlPos,CabNo);
end;
end
else {nie ma sterowania}
OK:=false;
//if OK then LastRelayTime:=0;
//hunter-101012: poprawka
if OK then
if (LastRelayTime>CtrlDelay) then
LastRelayTime:=0;
if (OK) and (EngineType=ElectricInductionMotor) then
if (Vmax<250) then
ScndCtrlActualPos:=Round(Vel+0.5)
else
ScndCtrlActualPos:=Round(Vel/2+0.5);
IncScndCtrl:=OK;
end;
function T_MoverParameters.DecScndCtrl(CtrlSpeed:integer): boolean;
var //b:byte;
OK:boolean;
begin
if (MainCtrlPos=0)and(CabNo<>0)and(TrainType=dt_ET42)and(ScndCtrlPos=0)and not(DynamicBrakeFlag)and(CtrlSpeed=1)then
begin
//Ra: AI wywołuje z CtrlSpeed=2 albo gdy ScndCtrlPos>0
OK:=DynamicBrakeSwitch(true);
end
else
if (ScndCtrlPosNo>0) and (CabNo<>0) then
begin
if (ScndCtrlPos>0) and (not CoupledCtrl) and ((EngineType<>DieselElectric) or (not AutoRelayFlag))then
begin
if CtrlSpeed=1 then
begin
dec(ScndCtrlPos);
end
else
if CtrlSpeed>1 then
begin
ScndCtrlPos:=0; {takie chamskie, potem poprawie}
end;
OK:=true;
end
else
OK:=false;
if OK then
begin
{OK:=}SendCtrlToNext('MainCtrl',MainCtrlPos,CabNo); {???}
{OK:=}SendCtrlToNext('ScndCtrl',ScndCtrlPos,CabNo);
end;
end
else
OK:=false;
//if OK then LastRelayTime:=0;
//hunter-101012: poprawka
if OK then
if (LastRelayTime>CtrlDownDelay) then
LastRelayTime:=0;
if (OK) and (EngineType=ElectricInductionMotor) then
ScndCtrlActualPos:=0;
DecScndCtrl:=OK;
end;
function T_MoverParameters.DirectionBackward: boolean;
begin
if (ActiveDir=1) and (MainCtrlPos=0) and (TrainType=dt_EZT) then
if MinCurrentSwitch(false) then
begin
DirectionBackward:=true; //
Exit;
end;
if (MainCtrlPosNo>0) and (ActiveDir>-1) and (MainCtrlPos=0) then
begin
if EngineType=WheelsDriven then
dec(CabNo);
{ else}
dec(ActiveDir);
DirAbsolute:=ActiveDir*CabNo;
if (DirAbsolute<>0) then
if (Battery) then //jeśli bateria jest już załączona
BatterySwitch(true); //to w ten oto durny sposób aktywuje się CA/SHP
DirectionBackward:=true;
SendCtrltoNext('Direction',ActiveDir,CabNo);
end
else
DirectionBackward:=false;
end;
function T_MoverParameters.MainSwitch(State:boolean): boolean;
begin
MainSwitch:=false; //Ra: przeniesione z końca
if ((Mains<>State) and (MainCtrlPosNo>0)) then
begin
if (State=false) or ({(MainCtrlPos=0) and} (ScndCtrlPos=0) and ((ConvOvldFlag=false)or(TrainType=dt_EZT)) and (LastSwitchingTime>CtrlDelay) and not TestFlag(DamageFlag,dtrain_out) and not TestFlag(EngDmgFlag,1)) then
begin
if Mains then //jeśli był załączony
SendCtrlToNext('MainSwitch',ord(State),CabNo); //wysłanie wyłączenia do pozostałych?
Mains:=State;
if Mains then //jeśli został załączony
SendCtrlToNext('MainSwitch',ord(State),CabNo); //wyslanie po wlaczeniu albo przed wylaczeniem
MainSwitch:=true; //wartość zwrotna
LastSwitchingTime:=0;
if (EngineType=DieselEngine) and Mains then
begin
dizel_enginestart:=State;
end;
if ((TrainType=dt_EZT)and(not State)) then
ConvOvldFlag:=true;
//if (State=false) then //jeśli wyłączony
// begin
//SetFlag(SoundFlag,sound_relay); //hunter-091012: przeniesione do Train.cpp, zeby sie nie zapetlal
// if (SecuritySystem.Status<>12) then
// SecuritySystem.Status:=0; //deaktywacja czuwaka; Ra: a nie baterią?
// end
//else
//if (SecuritySystem.Status<>12) then
// SecuritySystem.Status:=s_waiting; //aktywacja czuwaka
end
end
//else MainSwitch:=false;
end;
function T_MoverParameters.BatterySwitch(State:boolean):boolean;
begin
//Ra: ukrotnienie załączania baterii jest jakąś fikcją...
if (Battery<>State) then
begin
Battery:=State;
end;
if (Battery=true) then SendCtrlToNext('BatterySwitch',1,CabNo)
else SendCtrlToNext('BatterySwitch',0,CabNo);
BatterySwitch:=true;
if (Battery) and (ActiveCab<>0) {or (TrainType=dt_EZT)} then
SecuritySystem.Status:=SecuritySystem.Status or s_waiting //aktywacja czuwaka
else
SecuritySystem.Status:=0; //wyłączenie czuwaka
end;
function T_MoverParameters.EpFuseSwitch(State:boolean):boolean;
begin
if (EpFuse<>State) then
begin
EpFuse:=State;
EpFuseSwitch:=true;
end
else
EpFuseSwitch:=false;
// if (EpFuse=true) then SendCtrlToNext('EpFuseSwitch',1,CabNo)
// else SendCtrlToNext('EpFuseSwitch',0,CabNo);
end;
{wl/wyl przetwornicy}
function T_MoverParameters.ConverterSwitch(State:boolean):boolean;
begin
ConverterSwitch:=false; //Ra: normalnie chyba false?
if (ConverterAllow<>State) then
begin
ConverterAllow:=State;
ConverterSwitch:=true;
if CompressorPower=2 then
CompressorAllow:=ConverterAllow;
end;
if (ConverterAllow=true) then SendCtrlToNext('ConverterSwitch',1,CabNo)
else SendCtrlToNext('ConverterSwitch',0,CabNo)
end;
{wl/wyl sprezarki}
function T_MoverParameters.CompressorSwitch(State:boolean):boolean;
begin
CompressorSwitch:=false; //Ra: normalnie chyba tak?
// if State=true then
// if ((CompressorPower=2) and (not ConverterAllow)) then
// State:=false; //yB: to juz niepotrzebne
if (CompressorAllow<>State)and(CompressorPower<2)then
begin
CompressorAllow:=State;
CompressorSwitch:=true;
end;
if (CompressorAllow=true) then SendCtrlToNext('CompressorSwitch',1,CabNo)
else SendCtrlToNext('CompressorSwitch',0,CabNo)
end;
{wl/wyl malej sprezarki}
{function T_MoverParameters.SmallCompressorSwitch(State:boolean):boolean;
begin
if State=true then
if ((SmallCompressorPower=1) then
State:=false;
if (SmallCompressorAllow<>State) then
begin
SmallCompressorAllow:=State;
SmallCompressorSwitch:=true;
end;
end;
}
{sypanie piasku}
function T_MoverParameters.SandDoseOn : boolean;
begin
if (SandCapacity>0) then
begin
SandDoseOn:=true;
if SandDose then
SandDose:=false
else
if Sand>0 then SandDose:=true;
if CabNo<>0 then
SendCtrlToNext('SandDoseOn',1,CabNo);
end
else
SandDoseOn:=false;
end;
(*
//Ra: to jest do przejrzenia i uporządkowania
function T_MoverParameters.SecuritySystemReset : boolean;
//zbijanie czuwaka/SHP
procedure Reset;
begin
with SecuritySystem do
if not(TestFlag(SystemType,2) and TestFlag(Status,s_active)) then
SecuritySystem.SystemTimer:=0;
SecuritySystem.SystemBrakeTimer:=0;
SecuritySystem.SystemSoundTimer:=0;
SecuritySystem.Status:=s_waiting; //aktywacja czuwaka
SecuritySystem.VelocityAllowed:=-1;
end;
procedure ResetSHP;
begin
SecuritySystem.SystemBrakeTimer:=0;
SecuritySystem.SystemSoundTimer:=0;
SecuritySystem.VelocityAllowed:=-1;
SecuritySystem.Status:=s_waiting;
end;
begin
with SecuritySystem do
begin
if (Status=3) or (Status=2) or (Status=11) or (Status=26)or(Status=27) then
begin
SecuritySystemReset:=true;
if (Status<s_ebrake) then
Reset
else
if EmergencyBrakeSwitch(false) then
Reset;
end;
if (Status=5) or (Status=13) or (Status=29) or (Status=4) or ((Status=12) and (activedir<>0)) or (Status=28) then {Wlaczone tylko SHP}
{ begin
SecuritySystemReset:=true;
if (Status<s_ebrake) then
ResetSHP
else
if EmergencyBrakeSwitch(false) then
ResetSHP;
end;
if (Status=7) or (Status=15) or (Status=30) or (Status=31) then {Wlaczone SHP i CA}
{ begin
SecuritySystemReset:=true;
if (Status<s_ebrake) then
begin
ResetSHP;
SecuritySystem.Status:=3;
end
else
if EmergencyBrakeSwitch(false) then
ResetSHP;
end
else
SecuritySystemReset:=false;
end;
// SendCtrlToNext('SecurityReset',0,CabNo);
end;
function T_MoverParameters.SecuritySystemReset : boolean;
//zbijanie czuwaka/SHP
procedure Reset;
begin
SecuritySystem.SystemTimer:=0;
if TestFlag(SecuritySystem.Status,s_aware) then
begin
SecuritySystem.SystemBrakeCATimer:=0;
SecuritySystem.SystemSoundCATimer:=0;
SetFlag(SecuritySystem.Status,-s_aware);
SetFlag(SecuritySystem.Status,-s_CAalarm);
SetFlag(SecuritySystem.Status,-s_CAebrake);
EmergencyBrakeFlag:=false;
SecuritySystem.VelocityAllowed:=-1;
end
else if TestFlag(SecuritySystem.Status,s_active) then
begin
SecuritySystem.SystemBrakeSHPTimer:=0;
SecuritySystem.SystemSoundSHPTimer:=0;
SetFlag(SecuritySystem.Status,-s_active);
SetFlag(SecuritySystem.Status,-s_SHPalarm);
SetFlag(SecuritySystem.Status,-s_SHPebrake);
EmergencyBrakeFlag:=false;
SecuritySystem.VelocityAllowed:=-1;
end;
end;
begin
with SecuritySystem do
if (SystemType>0) and (Status>0) and ((status<>12) or ((status=12) and (activedir<>0))) then
//if (SystemType>0) and (Status>0) then
begin
SecuritySystemReset:=true;
if not (ActiveDir=0) then
if not TestFlag(Status,s_CAebrake) or not TestFlag(Status,s_SHPebrake) then
Reset;
//else
// if EmergencyBrakeSwitch(false) then
// Reset;
end
else
SecuritySystemReset:=false;
// SendCtrlToNext('SecurityReset',0,CabNo);
end;
{testowanie czuwaka/SHP}
procedure T_MoverParameters.SecuritySystemCheck(dt:real);
begin
with SecuritySystem do
begin
if (SystemType>0) and (Status>0) then
begin
SystemTimer:=SystemTimer+dt;
if TestFlag(Status,s_aware) or TestFlag(Status,s_active) then //jeśli świeci albo miga
SystemSoundTimer:=SystemSoundTimer+dt;
if TestFlag(Status,s_alarm) then //jeśli buczy
SystemBrakeTimer:=SystemBrakeTimer+dt;
if TestFlag(SystemType,1) then
if (SystemTimer>AwareDelay) and (AwareDelay>=0) then {-1 blokuje}
if not SetFlag(Status,s_aware) then {juz wlaczony sygnal swietlny}
if (SystemSoundTimer>SoundSignalDelay) and (SoundSignalDelay>=0) then
if not SetFlag(Status,s_alarm) then {juz wlaczony sygnal dzwiekowy}
if (SystemBrakeTimer>EmergencyBrakeDelay) and (EmergencyBrakeDelay>=0) then
SetFlag(Status,s_ebrake); {przeterminowanie czuwaka, hamowanie awaryjne}
if TestFlag(SystemType,2) and TestFlag(Status,s_active) then
if (Vel>VelocityAllowed) and (VelocityAllowed>=0) then
SetFlag(Status,s_ebrake)
else
if ((SystemSoundTimer>SoundSignalDelay) and (SoundSignalDelay>=0)) or ((Vel>NextVelocityAllowed) and (NextVelocityAllowed>=0)) then
if not SetFlag(Status,s_alarm) then {juz wlaczony sygnal dzwiekowy}
if (SystemBrakeTimer>EmergencyBrakeDelay) and (EmergencyBrakeDelay>=0) then
SetFlag(Status,s_ebrake);
if TestFlag(Status,s_ebrake) then
if not EmergencyBrakeFlag then
EmergencyBrakeSwitch(true);
end;
end;
end;
*)
//hunter-091012: rozbicie alarmow, dodanie testu czuwaka
function T_MoverParameters.SecuritySystemReset : boolean;
//zbijanie czuwaka/SHP
procedure Reset;
begin
SecuritySystem.SystemTimer:=0;
if TestFlag(SecuritySystem.Status,s_aware) then
begin
SecuritySystem.SystemBrakeCATimer:=0;
SecuritySystem.SystemSoundCATimer:=0;
SetFlag(SecuritySystem.Status,-s_aware);
SetFlag(SecuritySystem.Status,-s_CAalarm);
SetFlag(SecuritySystem.Status,-s_CAebrake);
// EmergencyBrakeFlag:=false; //YB-HN
SecuritySystem.VelocityAllowed:=-1;
end
else if TestFlag(SecuritySystem.Status,s_active) then
begin
SecuritySystem.SystemBrakeSHPTimer:=0;
SecuritySystem.SystemSoundSHPTimer:=0;
SetFlag(SecuritySystem.Status,-s_active);
SetFlag(SecuritySystem.Status,-s_SHPalarm);
SetFlag(SecuritySystem.Status,-s_SHPebrake);
// EmergencyBrakeFlag:=false; //YB-HN
SecuritySystem.VelocityAllowed:=-1;
end;
end;
begin
with SecuritySystem do
if (SystemType>0) and (Status>0) then
begin
SecuritySystemReset:=true;
if ((TrainType=dt_EZT)or(ActiveDir<>0)) then //Ra 2014-03: w EZT nie trzeba ustawiać kierunku
if not TestFlag(Status,s_CAebrake) or not TestFlag(Status,s_SHPebrake) then
Reset;
//else
// if EmergencyBrakeSwitch(false) then
// Reset;
end
else
SecuritySystemReset:=false;
// SendCtrlToNext('SecurityReset',0,CabNo);
end;
procedure T_MoverParameters.SecuritySystemCheck(dt:real);
begin
//Ra: z CA/SHP w EZT jest ten problem, że w rozrządczym nie ma kierunku, a w silnikowym nie ma obsady
//poza tym jest zdefiniowany we wszystkich 3 członach EN57
with SecuritySystem do
begin
if (not Radio) then
EmergencyBrakeSwitch(false);
if (SystemType>0) and (Status>0) and (Battery) then //Ra: EZT ma teraz czuwak w rozrządczym
begin
//CA
if (Vel>=AwareMinSpeed) then //domyślnie predkość większa od 10% Vmax, albo podanej jawnie w FIZ
begin
SystemTimer:=SystemTimer+dt;
if TestFlag(SystemType,1) and TestFlag(Status,s_aware) then //jeśli świeci albo miga
SystemSoundCATimer:=SystemSoundCATimer+dt;
if TestFlag(SystemType,1) and TestFlag(Status,s_CAalarm) then //jeśli buczy
SystemBrakeCATimer:=SystemBrakeCATimer+dt;
if TestFlag(SystemType,1) then
if (SystemTimer>AwareDelay) and (AwareDelay>=0) then {-1 blokuje}
if not SetFlag(Status,s_aware) then {juz wlaczony sygnal swietlny}
if (SystemSoundCATimer>SoundSignalDelay) and (SoundSignalDelay>=0) then
if not SetFlag(Status,s_CAalarm) then {juz wlaczony sygnal dzwiekowy}
if (SystemBrakeCATimer>EmergencyBrakeDelay) and (EmergencyBrakeDelay>=0) then
SetFlag(Status,s_CAebrake);
//SHP
if TestFlag(SystemType,2) and TestFlag(Status,s_active) then //jeśli świeci albo miga
SystemSoundSHPTimer:=SystemSoundSHPTimer+dt;
if TestFlag(SystemType,2) and TestFlag(Status,s_SHPalarm) then //jeśli buczy
SystemBrakeSHPTimer:=SystemBrakeSHPTimer+dt;
if TestFlag(SystemType,2) and TestFlag(Status,s_active) then
if (Vel>VelocityAllowed) and (VelocityAllowed>=0) then
SetFlag(Status,s_SHPebrake)
else
if ((SystemSoundSHPTimer>SoundSignalDelay) and (SoundSignalDelay>=0)) or ((Vel>NextVelocityAllowed) and (NextVelocityAllowed>=0)) then
if not SetFlag(Status,s_SHPalarm) then {juz wlaczony sygnal dzwiekowy}
if (SystemBrakeSHPTimer>EmergencyBrakeDelay) and (EmergencyBrakeDelay>=0) then
SetFlag(Status,s_SHPebrake);
end; //else SystemTimer:=0;
//TEST CA
if TestFlag(Status,s_CAtest) then //jeśli świeci albo miga
SystemBrakeCATestTimer:=SystemBrakeCATestTimer+dt;
if TestFlag(SystemType,1) then
if TestFlag(Status,s_CAtest) then {juz wlaczony sygnal swietlny}
if (SystemBrakeCATestTimer>EmergencyBrakeDelay) and (EmergencyBrakeDelay>=0) then
s_CAtestebrake:=true;
//wdrazanie hamowania naglego
// if TestFlag(Status,s_SHPebrake) or TestFlag(Status,s_CAebrake) or (s_CAtestebrake=true) then
// EmergencyBrakeFlag:=true; //YB-HN
end
else if not (Battery) then
begin //wyłączenie baterii deaktywuje sprzęt
EmergencyBrakeSwitch(false);
//SecuritySystem.Status:=0; //deaktywacja czuwaka
end;
end;
end;
{nastawy hamulca}
function T_MoverParameters.IncBrakeLevelOld:boolean;
//var b:byte;
begin
if (BrakeCtrlPosNo>0) {and (LocalBrakePos=0)} then
begin
if BrakeCtrlPos<BrakeCtrlPosNo then
begin
inc(BrakeCtrlPos);
// BrakeCtrlPosR:=BrakeCtrlPos;
//youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie poszczegolne pozycje;
// wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba wspolapracowac
{
if (BrakeSystem=ElectroPneumatic) then
if (BrakePressureActual.BrakeType=ElectroPneumatic) then
begin
// BrakeStatus:=ord(BrakeCtrlPos>0);
SendCtrlToNext('BrakeCtrl',BrakeCtrlPos,CabNo);
end
else SendCtrlToNext('BrakeCtrl',-2,CabNo);
// else
// if not TestFlag(BrakeStatus,b_dmg) then
// BrakeStatus:=b_on;}
//youBy: EP po nowemu
IncBrakeLevelOld:=true;
if (BrakePressureActual.PipePressureVal<0)and(BrakePressureTable[BrakeCtrlPos-1].PipePressureVal>0) then
LimPipePress:=PipePress;
if (BrakeSystem=ElectroPneumatic) then
if (BrakeSubSystem<>ss_K) then
begin
if (BrakeCtrlPos*BrakeCtrlPos)=1 then
begin
// SendCtrlToNext('Brake',BrakeCtrlPos,CabNo);
// SetFlag(BrakeStatus,b_epused);
end
else
begin
// SendCtrlToNext('Brake',0,CabNo);
// SetFlag(BrakeStatus,-b_epused);
end;
end;
end
else
begin
IncBrakeLevelOld:=false;
{ if BrakeSystem=Pneumatic then
EmergencyBrakeSwitch(true); }
end;
end
else
IncBrakeLevelOld:=false;
end;
function T_MoverParameters.DecBrakeLevelOld:boolean;
//var b:byte;
begin
if (BrakeCtrlPosNo>0) {and (LocalBrakePos=0)} then
begin
if (BrakeCtrlPos>-1-Byte(BrakeHandle=FV4a)) then
begin
dec(BrakeCtrlPos);
// BrakeCtrlPosR:=BrakeCtrlPos;
//// if EmergencyBrakeFlag then //yB: czy to jest potrzebne?
//// begin
//// EmergencyBrakeFlag:=false; {!!!}
//// SendCtrlToNext('Emergency_brake',0,CabNo);
//// end;
//youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie poszczegolne pozycje;
// wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba wspolapracowac
{
if (BrakeSystem=ElectroPneumatic) then
if BrakePressureActual.BrakeType=ElectroPneumatic then
begin
// BrakeStatus:=ord(BrakeCtrlPos>0);
SendCtrlToNext('BrakeCtrl',BrakeCtrlPos,CabNo);
end
else SendCtrlToNext('BrakeCtrl',-2,CabNo);
// else}
// if (not TestFlag(BrakeStatus,b_dmg) and (not TestFlag(BrakeStatus,b_release))) then
// BrakeStatus:=b_off; {luzowanie jesli dziala oraz nie byl wlaczony odluzniacz}
//youBy: EP po nowemu
DecBrakeLevelOld:=true;
// if (BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0)and(BrakePressureTable[BrakeCtrlPos+1].PipePressureVal>0) then
// LimPipePress:=PipePress;
if (BrakeSystem=ElectroPneumatic) then
if (BrakeSubSystem<>ss_K) then
begin
if (BrakeCtrlPos*BrakeCtrlPos)=1 then
begin
// SendCtrlToNext('Brake',BrakeCtrlPos,CabNo);
// SetFlag(BrakeStatus,b_epused);
end
else
begin
// SendCtrlToNext('Brake',0,CabNo);
// SetFlag(BrakeStatus,-b_epused);
end;
end;
(* for b:=0 to 1 do {poprawic to!}
with Couplers[b] do
if CouplingFlag and ctrain_controll=ctrain_controll then
Connected^.BrakeCtrlPos:=BrakeCtrlPos;
*)
end
else
DecBrakeLevelOld:=false;
end
else
DecBrakeLevelOld:=false;
end;
function T_MoverParameters.IncLocalBrakeLevelFAST:boolean;
begin
if (LocalBrakePos<LocalBrakePosNo) then
begin
LocalBrakePos:=LocalBrakePosNo;
IncLocalBrakeLevelFAST:=true;
end
else
IncLocalBrakeLevelFAST:=false;
UnBrake:=true;
end;
function T_MoverParameters.IncLocalBrakeLevel(CtrlSpeed:byte):boolean;
begin
if (LocalBrakePos<LocalBrakePosNo) {and (BrakeCtrlPos<1)} then
begin
while (LocalBrakePos<LocalBrakePosNo) and (CtrlSpeed>0) do
begin
inc(LocalBrakePos);
dec(CtrlSpeed);
end;
IncLocalBrakeLevel:=true;
end
else
IncLocalBrakeLevel:=false;
UnBrake:=true;
end;
function T_MoverParameters.IncManualBrakeLevel(CtrlSpeed:byte):boolean;
begin
if (ManualBrakePos<ManualBrakePosNo) {and (BrakeCtrlPos<1)} then
begin
while (ManualBrakePos<ManualBrakePosNo) and (CtrlSpeed>0) do
begin
inc(ManualBrakePos);
dec(CtrlSpeed);
end;
IncManualBrakeLevel:=true;
end
else
IncManualBrakeLevel:=false;
end;
function T_MoverParameters.DecLocalBrakeLevelFAST():boolean;
begin
if LocalBrakePos>0 then
begin
LocalBrakePos:=0;
DecLocalBrakeLevelFAST:=true;
end
else
DecLocalBrakeLevelFAST:=false;
UnBrake:=true;
end;
function T_MoverParameters.DecLocalBrakeLevel(CtrlSpeed:byte):boolean;
begin
if LocalBrakePos>0 then
begin
while (CtrlSpeed>0) and (LocalBrakePos>0) do
begin
dec(LocalBrakePos);
dec(CtrlSpeed);
end;
DecLocalBrakeLevel:=true;
end
else
DecLocalBrakeLevel:=false;
UnBrake:=true;
end;
function T_MoverParameters.DecManualBrakeLevel(CtrlSpeed:byte):boolean;
begin
if ManualBrakePos>0 then
begin
while (CtrlSpeed>0) and (ManualBrakePos>0) do
begin
dec(ManualBrakePos);
dec(CtrlSpeed);
end;
DecManualBrakeLevel:=true;
end
else
DecManualBrakeLevel:=false;
end;
function T_MoverParameters.EmergencyBrakeSwitch(Switch:boolean): boolean;
begin
if (BrakeSystem<>Individual) and (BrakeCtrlPosNo>0) then
begin
if (not EmergencyBrakeFlag) and Switch then
begin
EmergencyBrakeFlag:=Switch;
EmergencyBrakeSwitch:=true;
end
else
begin
if (Abs(V)<0.1) and (Switch=false) then {odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu}
begin
EmergencyBrakeFlag:=Switch;
EmergencyBrakeSwitch:=true;
end
else
EmergencyBrakeSwitch:=false;
end;
end
else
EmergencyBrakeSwitch:=false; {nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp.}
end;
function T_MoverParameters.AntiSlippingBrake: boolean;
begin
AntiSlippingBrake:=false; //Ra: przeniesione z końca
if ASBType=1 then
begin
AntiSlippingBrake:=true; //SPKS!!
Hamulec.ASB(1);
BrakeSlippingTimer:=0;
end
end;
function T_MoverParameters.AntiSlippingButton: boolean;
var OK:boolean;
begin
OK:=SandDoseOn;
AntiSlippingButton:=(AntiSlippingBrake or OK);
end;
function T_MoverParameters.BrakeDelaySwitch(BDS:byte): boolean;
begin
// if BrakeCtrlPosNo>0 then
if BrakeHandle=MHZ_EN57 then
begin
if (BDS<>BrakeOpModeFlag) and ((BDS and BrakeOpModes) > 0) then
begin
BrakeOpModeFlag:=BDS;
BrakeDelaySwitch:=true;
end
else
BrakeDelaySwitch:=false;
end
else if Hamulec.SetBDF(BDS) then
begin
BrakeDelayFlag:=BDS;
BrakeDelaySwitch:=true;
BrakeStatus:=(BrakeStatus and 191);
//kopowanie nastawy hamulca do kolejnego czlonu - do przemyślenia
if CabNo<>0 then
SendCtrlToNext('BrakeDelay',BrakeDelayFlag,CabNo);
end
else
BrakeDelaySwitch:=false;
end;
function T_MoverParameters.IncBrakeMult(): boolean;
begin
if (LoadFlag>0) and (MBPM<2) and (LoadFlag<3) then
begin
if (MaxBrakePress[2]>0) and (LoadFlag=1) then
LoadFlag:=2
else
LoadFlag:=3;
IncBrakeMult:=true;
if BrakeCylMult[2]>0 then BrakeCylMult[0]:=BrakeCylMult[2];
end
else
IncBrakeMult:=false;
end;
function T_MoverParameters.DecBrakeMult(): boolean;
begin
if (LoadFlag>1) and (MBPM<2) then
begin
if (MaxBrakePress[2]>0) and (LoadFlag=3) then
LoadFlag:=2
else
LoadFlag:=1;
DecBrakeMult:=true;
if BrakeCylMult[1]>0 then BrakeCylMult[0]:=BrakeCylMult[1];
end
else
DecBrakeMult:=false;
end;
function T_MoverParameters.BrakeReleaser(state: byte): boolean;
var OK:boolean;
begin
Hamulec.Releaser(state);
if CabNo<>0 then //rekurencyjne wysłanie do następnego
OK:=SendCtrlToNext('BrakeReleaser',state,CabNo);
BrakeReleaser:=OK;
end;
function T_MoverParameters.SwitchEPBrake(state: byte):boolean;
var
OK:boolean;
temp: real;
begin
OK:=false;
if (BrakeHandle = St113) and (ActiveCab<>0) then
begin
if(state>0)then
temp:=(Handle as TSt113).GetCP
else
temp:=0;
Hamulec.SetEPS(temp);
SendCtrlToNext('Brake',temp,CabNo);
end;
// OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused));
// SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabNo);
SwitchEPBrake:=OK;
end;
{uklady pneumatyczne}
function T_MoverParameters.IncBrakePress(var brake:real;PressLimit,dp:real):boolean;
begin
// if (DynamicBrakeType<>dbrake_switch) and (DynamicBrakeType<>dbrake_none) and ((BrakePress>2.0) or (PipePress<3.7{(LowPipePress+0.5)})) then
if (DynamicBrakeType<>dbrake_switch) and (DynamicBrakeType<>dbrake_none) and (BrakePress>2.0) and (TrainType<>dt_EZT) then //yB radzi nie sprawdzać ciśnienia w przewodzie
//hunter-301211: dla EN57 silnikow nie odlaczamy
begin
DynamicBrakeFlag:=true; {uruchamianie hamulca ED albo odlaczanie silnikow}
if (DynamicBrakeType=dbrake_automatic) and (abs(Im)>60) then {nie napelniaj wiecej, jak na EP09}
dp:=0.0;
end;
if brake+dp<PressLimit then
begin
brake:=brake+dp;
IncBrakePress:=true;
end
else
begin
IncBrakePress:=false;
brake:=PressLimit;
end;
end;
function T_MoverParameters.DecBrakePress(var brake:real;PressLimit,dp:real):boolean;
begin
if brake-dp>PressLimit then
begin
brake:=brake-dp;
DecBrakePress:=true;
end
else
begin
DecBrakePress:=false;
brake:=PressLimit;
end;
// if (DynamicBrakeType<>dbrake_switch) and ((BrakePress<0.1) and (PipePress>0.45{(LowPipePress+0.06)})) then
if (DynamicBrakeType<>dbrake_switch) and (BrakePress<0.1) then //yB radzi nie sprawdzać ciśnienia w przewodzie
DynamicBrakeFlag:=false; {wylaczanie hamulca ED i/albo zalaczanie silnikow}
end;
procedure T_MoverParameters.UpdateBrakePressure(dt:real);
const LBDelay=5.0; {stala czasowa hamulca}
var Rate,Speed,dp,sm:real;
begin
dpLocalValve:=0;
dpBrake:=0;
BrakePress:=Hamulec.GetBCP;
// BrakePress:=(Hamulec as TEst4).ImplsRes.pa;
Volume:=Hamulec.GetBRP;
end; {updatebrakepressure}
function T_MoverParameters.GetDVc(dt:real):real;
var c:T_MoverParameters;dv1,dv2,dv:real;
begin
dv1:=0;
dv2:=0;
//sprzeg 1
if Couplers[0].Connected<>nil then
if TestFlag(Couplers[0].CouplingFlag,ctrain_pneumatic) then
begin //*0.85
c:=Couplers[0].Connected; //skrot //0.08 //e/D * L/D = e/D^2 * L
dv1:=0.5*dt*PF(PipePress,c.PipePress,(Spg)/(1+0.015/Spg*Dim.L));
if (dv1*dv1>0.00000000000001) then c.Physic_Reactivation;
c.Pipe.Flow(-dv1);
end;
//sprzeg 2
if Couplers[1].Connected<>nil then
if TestFlag(Couplers[1].CouplingFlag,ctrain_pneumatic) then
begin
c:=Couplers[1].Connected; //skrot
dv2:=0.5*dt*PF(PipePress,c.PipePress,(Spg)/(1+0.015/Spg*Dim.L));
if (dv2*dv2>0.00000000000001) then c.Physic_Reactivation;
c.Pipe.Flow(-dv2);
end;
if (Couplers[1].Connected<>nil)and(Couplers[0].Connected<>nil) then
if (TestFlag(Couplers[0].CouplingFlag,ctrain_pneumatic))and(TestFlag(Couplers[1].CouplingFlag,ctrain_pneumatic))then
begin
dv:=0.05*dt*PF(Couplers[0].Connected.PipePress,Couplers[1].Connected.PipePress,(Spg*0.85)/(1+0.03*Dim.L))*0;
Couplers[0].Connected.Pipe.Flow(+dv);
Couplers[1].Connected.Pipe.Flow(-dv);
end;
//suma
GetDVc:=dv2+dv1;
end;
procedure T_MoverParameters.UpdatePipePressure(dt:real);
const LBDelay=100;kL=0.5;
var {b: byte;} dV{,PWSpeed}{,PPP}:real; c: T_MoverParameters;
temp: real;
b: byte;
begin
PipePress:=Pipe.P;
// PPP:=PipePress;
dpMainValve:=0;
if (BrakeCtrlPosNo>1) {and(ActiveCab<>0)}then
with BrakePressureTable[BrakeCtrlPos] do
begin
if(EngineType<>ElectricInductionMotor)then
dpLocalValve:=LocHandle.GetPF(Max0R(LocalBrakePos/LocalBrakePosNo,LocalBrakePosA), Hamulec.GetBCP, ScndPipePress, dt, 0)
else
dpLocalValve:=LocHandle.GetPF(LocalBrakePosA, Hamulec.GetBCP, ScndPipePress, dt, 0);
if(BrakeHandle=FV4a)and((PipePress<2.75)and((Hamulec.GetStatus and b_rls)=0))and(BrakeSubsystem=ss_LSt)and(TrainType<>dt_EZT)then
temp:=PipePress+0.00001
else
temp:=ScndPipePress;
Handle.SetReductor(BrakeCtrlPos2);
if (BrakeOpModeFlag<>bom_PS) then
if (BrakeOpModeFlag<bom_EP) or (Handle.GetPos(bh_EB)-0.5<BrakeCtrlPosR) or (BrakeHandle<>MHZ_EN57) then
dpMainValve:=Handle.GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress)
else
dpMainValve:=Handle.GetPF(0, PipePress, temp, dt, EqvtPipePress);
if (dpMainValve<0){and(PipePressureVal>0.01)} then {50}
if Compressor>ScndPipePress then
begin
CompressedVolume:=CompressedVolume+dpMainValve/1500;
Pipe2.Flow(dpMainValve/3);
end
else
Pipe2.Flow(dpMainValve);
end;
// if(EmergencyBrakeFlag)and(BrakeCtrlPosNo=0)then {ulepszony hamulec bezp.}
if(EmergencyBrakeFlag)or TestFlag(SecuritySystem.Status,s_SHPebrake) or TestFlag(SecuritySystem.Status,s_CAebrake) or (s_CAtestebrake=true) or (TestFlag(EngDmgFlag,32)){ or (not Battery)}then {ulepszony hamulec bezp.}
dpMainValve:=dpMainValve/1+PF(0,PipePress,0.15)*dt;
//0.2*Spg
Pipe.Flow(-dpMainValve);
Pipe.Flow(-(PipePress)*0.001*dt);
// if Heating then
// Pipe.Flow(PF(PipePress,0,d2A(7))*dt);
// if ConverterFlag then
// Pipe.Flow(PF(PipePress,0,d2A(12))*dt);
dpMainValve:=dpMainValve/(Dim.L*Spg*20);
CntrlPipePress:=Hamulec.GetVRP; //ciśnienie komory wstępnej rozdzielacza
case BrakeValve of
W:
begin
if (BrakeLocHandle<>NoHandle) then
begin
LocBrakePress:=LocHandle.GetCP;
(Hamulec as TWest).SetLBP(LocBrakePress);
end;
if MBPM<2 then
(Hamulec as TWest).PLC(MaxBrakePress[LoadFlag])
else
(Hamulec as TWest).PLC(TotalMass);
end;
LSt,EStED:
begin
LocBrakePress:=LocHandle.GetCP;
for b:=0 to 1 do
if((TrainType and (dt_ET41 or dt_ET42))>0)and(Couplers[b].Connected<>nil)then //nie podoba mi się to rozwiązanie, chyba trzeba dodać jakiś wpis do fizyki na to
if((Couplers[b].Connected.TrainType and (dt_ET41 or dt_ET42))>0)and((Couplers[b].CouplingFlag and 36) = 36)then
LocBrakePress:=Max0R(Couplers[b].Connected.LocHandle.GetCP,LocBrakePress);
if(DynamicBrakeFlag)and(EngineType=ElectricInductionMotor)then
begin
(Hamulec as TLSt).SetLBP(LocBrakePress);
// if(Vel>10)then LocBrakePress:=0 else
// if(Vel>5)then LocBrakePress:=(10-Vel)/5*LocBrakePress
end
else
(Hamulec as TLSt).SetLBP(LocBrakePress);
if (BrakeValve = EStED) then
if MBPM<2 then
(Hamulec as TEStED).PLC(MaxBrakePress[LoadFlag])
else
(Hamulec as TEStED).PLC(TotalMass);
end;
CV1_L_TR:
begin
LocBrakePress:=LocHandle.GetCP;
(Hamulec as TCV1L_TR).SetLBP(LocBrakePress);
end;
EP2: (Hamulec as TEStEP2).PLC(TotalMass);
ESt3AL2,NESt3,ESt4,ESt3:
begin
if MBPM<2 then
(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag])
else
(Hamulec as TNESt3).PLC(TotalMass);
LocBrakePress:=LocHandle.GetCP;
(Hamulec as TNESt3).SetLBP(LocBrakePress);
end;
KE:
begin
LocBrakePress:=LocHandle.GetCP;
(Hamulec as TKE).SetLBP(LocBrakePress);
if MBPM<2 then
(Hamulec as TKE).PLC(MaxBrakePress[LoadFlag])
else
(Hamulec as TKE).PLC(TotalMass);
end;
end;
if (BrakeHandle = FVel6) and (ActiveCab<>0) then
begin
if (Battery) and (ActiveDir<>0) and (EpFuse) then //tu powinien byc jeszcze bezpiecznik EP i baterie -
temp:=(Handle as TFVel6).GetCP
else
temp:=0;
Hamulec.SetEPS(temp);
SendCtrlToNext('Brake',temp,CabNo); //Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach
end;
Pipe.Act;
PipePress:=Pipe.P;
if (BrakeStatus and 128)=128 then //jesli hamulec wyłączony
temp:=0 //odetnij
else
temp:=1; //połącz
Pipe.Flow(temp*Hamulec.GetPF(temp*PipePress,dt,Vel)+GetDVc(dt));
if ASBType=128 then
Hamulec.ASB(Byte(SlippingWheels));
dpPipe:=0;
//yB: jednokrokowe liczenie tego wszystkiego
Pipe.Act;
PipePress:=Pipe.P;
dpMainValve:=dpMainValve/(100*dt); //normalizacja po czasie do syczenia;
if PipePress<-1 then
begin
PipePress:=-1;
Pipe.CreatePress(-1);
Pipe.Act;
end;
if CompressedVolume<0 then
CompressedVolume:=0;
end; {updatepipepressure}
procedure T_MoverParameters.CompressorCheck(dt:real);
begin
//if (CompressorSpeed>0.0) then //ten warunek został sprawdzony przy wywołaniu funkcji
if (VeselVolume>0) then
begin
if MaxCompressor-MinCompressor<0.0001 then
begin
{ if Mains and (MainCtrlPos>1) then}
if CompressorAllow and Mains and (MainCtrlPos>0) then
begin
if (Compressor<MaxCompressor) then
if (EngineType=DieselElectric) and (CompressorPower>0) then
CompressedVolume:=CompressedVolume+dt*CompressorSpeed*(2*MaxCompressor-Compressor)/MaxCompressor*(DEList[MainCtrlPos].rpm/DEList[MainCtrlPosNo].rpm)
else
begin
CompressedVolume:=CompressedVolume+dt*CompressorSpeed*(2*MaxCompressor-Compressor)/MaxCompressor;
TotalCurrent:=TotalCurrent+0.0015*Voltage; //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
end
else
begin
CompressedVolume:=CompressedVolume*0.8;
SetFlag(SoundFlag,sound_relay);
SetFlag(SoundFlag,sound_loud);
end;
end;
end
else
begin
if (CompressorFlag) then //jeśli sprężarka załączona
begin //sprawdzić możliwe warunki wyłączenia sprężarki
if (CompressorPower=5) then //jeśli zasilanie z sąsiedniego członu
begin //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[1].Connected<>NIL) then
CompressorFlag:=Couplers[1].Connected.CompressorAllow and Couplers[1].Connected.ConverterFlag and Couplers[1].Connected.Mains
else
CompressorFlag:=false; //bez tamtego członu nie zadziała
end
else if (CompressorPower=4) then //jeśli zasilanie z poprzedniego członu
begin //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[0].Connected<>NIL) then
CompressorFlag:=Couplers[0].Connected.CompressorAllow and Couplers[0].Connected.ConverterFlag and Couplers[0].Connected.Mains
else
CompressorFlag:=false; //bez tamtego członu nie zadziała
end
else
CompressorFlag:=(CompressorAllow) and ((ConverterFlag) or (CompressorPower=0)) and (Mains);
if (Compressor>MaxCompressor) then //wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
CompressorFlag:=false;
end
else //jeśli nie załączona
if (Compressor<MinCompressor) and (LastSwitchingTime>CtrlDelay) then //jeśli nie załączona, a ciśnienie za małe
begin //załączenie przy małym ciśnieniu
if (CompressorPower=5) then //jeśli zasilanie z następnego członu
begin //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[1].Connected<>NIL) then
CompressorFlag:=Couplers[1].Connected.CompressorAllow and Couplers[1].Connected.ConverterFlag and Couplers[1].Connected.Mains
else
CompressorFlag:=false; //bez tamtego członu nie zadziała
end
else if (CompressorPower=4) then //jeśli zasilanie z poprzedniego członu
begin //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[0].Connected<>NIL) then
CompressorFlag:=Couplers[0].Connected.CompressorAllow and Couplers[0].Connected.ConverterFlag and Couplers[0].Connected.Mains
else
CompressorFlag:=false; //bez tamtego członu nie zadziała
end
else
CompressorFlag:=(CompressorAllow) and ((ConverterFlag) or (CompressorPower=0)) and (Mains);
if (CompressorFlag) then //jeśli została załączona
LastSwitchingTime:=0; //to trzeba ograniczyć ponowne włączenie
end;
// for b:=0 to 1 do //z Megapacka
// with Couplers[b] do
// if TestFlag(CouplingFlag,ctrain_scndpneumatic) then
// Connected.CompressorFlag:=CompressorFlag;
if CompressorFlag then
if (EngineType=DieselElectric) and (CompressorPower>0) then
CompressedVolume:=CompressedVolume+dt*CompressorSpeed*(2*MaxCompressor-Compressor)/MaxCompressor*(DEList[MainCtrlPos].rpm/DEList[MainCtrlPosNo].rpm)
else
begin
CompressedVolume:=CompressedVolume+dt*CompressorSpeed*(2*MaxCompressor-Compressor)/MaxCompressor;
if (CompressorPower=5)and(Couplers[1].Connected<>NIL) then
Couplers[1].Connected.TotalCurrent:=Couplers[1].Connected.TotalCurrent+0.0015*Couplers[1].Connected.Voltage //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
else if (CompressorPower=4)and(Couplers[0].Connected<>NIL) then
Couplers[0].Connected.TotalCurrent:=Couplers[0].Connected.TotalCurrent+0.0015*Couplers[0].Connected.Voltage //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
else
TotalCurrent:=TotalCurrent+0.0015*Voltage; //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
end
end;
end;
end;
{Ra 2014-07: do C++
procedure T_MoverParameters.ConverterCheck;
begin //sprawdzanie przetwornicy
if (ConverterAllow=true)and(Mains=true) then
ConverterFlag:=true
else
ConverterFlag:=false;
end;
}
//youBy - przewod zasilajacy
procedure T_MoverParameters.UpdateScndPipePressure(dt: real);
const Spz=0.5067;
var c:T_MoverParameters;dv1,dv2,dv:real;
begin
dv1:=0;
dv2:=0;
//sprzeg 1
if Couplers[0].Connected<>nil then
if TestFlag(Couplers[0].CouplingFlag,ctrain_scndpneumatic) then
begin
c:=Couplers[0].Connected; //skrot
dv1:=0.5*dt*PF(ScndPipePress,c.ScndPipePress,Spz*0.75);
if (dv1*dv1>0.00000000000001) then c.Physic_Reactivation;
c.Pipe2.Flow(-dv1);
end;
//sprzeg 2
if Couplers[1].Connected<>nil then
if TestFlag(Couplers[1].CouplingFlag,ctrain_scndpneumatic) then
begin
c:=Couplers[1].Connected; //skrot
dv2:=0.5*dt*PF(ScndPipePress,c.ScndPipePress,Spz*0.75);
if (dv2*dv2>0.00000000000001) then c.Physic_Reactivation;
c.Pipe2.Flow(-dv2);
end;
if(Couplers[1].Connected<>nil)and(Couplers[0].Connected<>nil)then
if (TestFlag(Couplers[0].CouplingFlag,ctrain_scndpneumatic))and(TestFlag(Couplers[1].CouplingFlag,ctrain_scndpneumatic))then
begin
dv:=0.00025*dt*PF(Couplers[0].Connected.ScndPipePress,Couplers[1].Connected.ScndPipePress,Spz*0.25);
Couplers[0].Connected.Pipe2.Flow(+dv);
Couplers[1].Connected.Pipe2.Flow(-dv);
end;
Pipe2.Flow(Hamulec.GetHPFlow(ScndPipePress, dt));
if ((Compressor>ScndPipePress) and (CompressorSpeed>0.0001)) or (TrainType=dt_EZT) then
begin
dV:=PF(Compressor,ScndPipePress,Spz)*dt;
CompressedVolume:=CompressedVolume+dV/1000;
Pipe2.Flow(-dV);
end;
Pipe2.Flow(dv1+dv2);
Pipe2.Act;
ScndPipePress:=Pipe2.P;
if ScndPipePress<-1 then
begin
ScndPipePress:=-1;
Pipe2.CreatePress(-1);
Pipe2.Act;
end;
end;
{lokomotywy}
function T_MoverParameters.ComputeRotatingWheel(WForce,dt,n:real): real;
var newn,eps:real;
begin
if (n=0) and (WForce*Sign(V)<0) then
newn:=0
else
begin
eps:=WForce*WheelDiameter/(2.0*AxleInertialMoment);
newn:=n+eps*dt;
if (newn*n<=0) and (eps*n<0) then
newn:=0;
end;
ComputeRotatingWheel:=newn;
end;
{----------------------}
{LOKOMOTYWA ELEKTRYCZNA}
function T_MoverParameters.FuseFlagCheck: boolean;
var b:byte;
begin
FuseFlagCheck:=false;
if Power>0.01 then FuseFlagCheck:=FuseFlag
else {pobor pradu jezeli niema mocy}
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected.Power>0.01 then
FuseFlagCheck:=Connected.FuseFlagCheck();
end;
function T_MoverParameters.FuseOn: boolean;
begin
FuseOn:=false;
if (MainCtrlPos=0) and (ScndCtrlPos=0) and (TrainType<>dt_ET40) and ((Mains) or (TrainType<>dt_EZT)) and (not TestFlag(EngDmgFlag,1)) then
begin //w ET40 jest blokada nastawnika, ale czy działa dobrze?
SendCtrlToNext('FuseSwitch',1,CabNo);
if ((EngineType=ElectricSeriesMotor)or((EngineType=DieselElectric))) and FuseFlag then
begin
FuseFlag:=false; {wlaczenie ponowne obwodu}
FuseOn:=true;
SetFlag(SoundFlag,sound_relay); SetFlag(SoundFlag,sound_loud);
end;
end;
end;
procedure T_MoverParameters.FuseOff;
begin
if not FuseFlag then
begin
FuseFlag:=true;
EventFlag:=true;
SetFlag(SoundFlag,sound_relay);
SetFlag(SoundFlag,sound_loud);
end;
end;
function T_MoverParameters.ShowCurrent(AmpN:byte): integer;
var b,Bn:byte;
Grupowy: boolean;
begin
ClearPendingExceptions;
ShowCurrent:=0;
Grupowy:=(DelayCtrlFlag) and (TrainType=dt_et22); //przerzucanie walu grupowego w ET22;
Bn:=RList[MainCtrlActualPos].Bn; //ile równoległych gałęzi silników
if (DynamicBrakeType=dbrake_automatic) and (DynamicBrakeFlag) then
Bn:=2;
if Power>0.01 then
begin
if AmpN>0 then //podać prąd w gałęzi
begin
if (Bn<AmpN)or((Grupowy) and (AmpN=Bn-1)) then
ShowCurrent:=0
else //normalne podawanie pradu
ShowCurrent:=Trunc(Abs(Im));
end
else //podać całkowity
ShowCurrent:=Trunc(Abs(Itot));
end
else {pobor pradu jezeli niema mocy}
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected.Power>0.01 then
ShowCurrent:=Connected.ShowCurrent(AmpN);
end;
{Ra 2014-06: przeniesione do C++
function T_MoverParameters.ShowEngineRotation(VehN:byte): integer;
var b:Byte; //,Bn:byte;
begin
ClearPendingExceptions;
ShowEngineRotation:=0;
case VehN of
1: ShowEngineRotation:=Trunc(Abs(enrot));
2: for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected.Power>0.01 then
ShowEngineRotation:=Trunc(Abs(Connected.enrot));
3: if Couplers[1].Connected<>nil then
if TestFlag(Couplers[1].CouplingFlag,ctrain_controll) then
if Couplers[1].Connected.Couplers[1].Connected<>nil then
if TestFlag(Couplers[1].Connected.Couplers[1].CouplingFlag,ctrain_controll) then
if Couplers[1].Connected.Couplers[1].Connected.Power>0.01 then
ShowEngineRotation:=Trunc(Abs(Couplers[1].Connected.Couplers[1].Connected.enrot));
end;
end;
}
{funkcje uzalezniajace sile pociagowa od predkosci: V2n, n2R, Current, Momentum}
{----------------}
function T_MoverParameters.V2n:real;
{przelicza predkosc liniowa na obrotowa}
const dmgn=0.5;
var n,deltan:real;
begin
n:=V/(Pi*WheelDiameter); //predkosc obrotowa wynikajaca z liniowej [obr/s]
deltan:=n-nrot; //"pochodna" prędkości obrotowej
if SlippingWheels then
if Abs(deltan)<0.01 then
SlippingWheels:=false; {wygaszenie poslizgu}
if SlippingWheels then {nie ma zwiazku z predkoscia liniowa V}
begin {McZapkie-221103: uszkodzenia kol podczas poslizgu}
if deltan>dmgn then
if FuzzyLogic(deltan,dmgn,p_slippdmg) then
if SetFlag(DamageFlag,dtrain_wheelwear) {podkucie}
then EventFlag:=true;
if deltan<-dmgn then
if FuzzyLogic(-deltan,dmgn,p_slippdmg) then
if SetFlag(DamageFlag,dtrain_thinwheel) {wycieranie sie obreczy}
then EventFlag:=true;
n:=nrot; {predkosc obrotowa nie zalezy od predkosci liniowej}
end;
V2n:=n;
end;
function T_MoverParameters.Current(n,U:real): real;
{wazna funkcja - liczy prad plynacy przez silniki polaczone szeregowo lub rownolegle}
{w zaleznosci od polozenia nastawnikow MainCtrl i ScndCtrl oraz predkosci obrotowej n}
{a takze wywala bezpiecznik nadmiarowy gdy za duzy prad lub za male napiecie}
{jest takze mozliwosc uszkodzenia silnika wskutek nietypowych parametrow}
const ep09resED=5.8; {TODO: dobrac tak aby sie zgadzalo ze wbudzeniem}
var //Rw,
R,MotorCurrent:real;
Rz,Delta,Isf:real;
Mn: integer;
Bn: real;
SP: byte;
U1: real; //napiecie z korekta
begin
MotorCurrent:=0;
//i dzialanie hamulca ED w EP09
if (DynamicBrakeType=dbrake_automatic) then
begin
if (((Hamulec as TLSt).GetEDBCP<0.25)and(Vadd<1))or(BrakePress>2.1) then
DynamicBrakeFlag:=false
else if (BrakePress>0.25) and ((Hamulec as TLSt).GetEDBCP>0.25) then
DynamicBrakeFlag:=true;
DynamicBrakeFlag:=DynamicBrakeFlag and ConverterFlag;
end;
//wylacznik cisnieniowy yBARC - to jest chyba niepotrzebne tutaj
// if BrakePress>2 then
// begin
// StLinFlag:=true;
// DelayCtrlFlag:=(TrainType<>dt_EZT); //EN57 nie ma czekania na 1. pozycji
// DynamicBrakeFlag:=false;
// end;
if(BrakeSubSystem=ss_LSt)then
if(DynamicBrakeFlag)then
(Hamulec as TLSt).SetED(Abs(Im/350)) //hamulec ED na EP09 dziala az do zatrzymania lokomotywy
else
(Hamulec as TLSt).SetED(0);
ResistorsFlag:=(RList[MainCtrlActualPos].R>0.01){ and (not DelayCtrlFlag)};
ResistorsFlag:=ResistorsFlag or ((DynamicBrakeFlag=true) and (DynamicBrakeType=dbrake_automatic));
if(TrainType=dt_ET22)and(DelayCtrlFlag)and(MainCtrlActualPos>1)then
Bn:=1-1/RList[MainCtrlActualPos].Bn
else
Bn:=1;
R:=RList[MainCtrlActualPos].R*Bn+CircuitRes;
if (TrainType<>dt_EZT)or(Imin<>IminLo)or(not ScndS) then //yBARC - boczniki na szeregu poprawnie
Mn:=RList[MainCtrlActualPos].Mn
else
Mn:=RList[MainCtrlActualPos].Mn*RList[MainCtrlActualPos].Bn;
//z Megapacka
// if DynamicBrakeFlag and (TrainType=dt_ET42) then { KURS90 azeby mozna bylo hamowac przy opuszczonych pantografach }
// SP:=ScndCtrlActualPos;
// if(ScndInMain)then
// if not (RList[MainCtrlActualPos].ScndAct=255) then
// SP:=RList[MainCtrlActualPos].ScndAct;
// with MotorParam[SP] do
// begin
// Rz:=WindingRes+R;
// MotorCurrent:=-fi*n/Rz;
// end;
if DynamicBrakeFlag and (not FuseFlag) and (DynamicBrakeType=dbrake_automatic) and ConverterFlag and Mains then {hamowanie EP09}
with MotorParam[0] do //TUHEX
begin
MotorCurrent:=-Max0R(fi*(Vadd/(Vadd+Isat)-fi0),0)*n*2/ep09resED; {TODO: zrobic bardziej uniwersalne nie tylko dla EP09}
// if abs(MotorCurrent)>500 then
// MotorCurrent:=sign(MotorCurrent)*500 {TODO: zrobic bardziej finezyjnie}
end
else
if (RList[MainCtrlActualPos].Bn=0) {or FuseFlag} or (not StLinFlag) {or DelayCtrlFlag} then
//if (RList[MainCtrlActualPos].Bn=0) or FuseFlag or StLinFlag or DelayCtrlFlag or ((TrainType=dt_ET42)and(not(ConverterFlag)and not(DynamicBrakeFlag))) then //z Megapacka
MotorCurrent:=0 {wylaczone}
else {wlaczone}
begin
SP:=ScndCtrlActualPos;
if(ScndCtrlActualPos<255)then {tak smiesznie bede wylaczal }
begin
if(ScndInMain)then
if not (RList[MainCtrlActualPos].ScndAct=255) then
SP:=RList[MainCtrlActualPos].ScndAct;
with MotorParam[SP] do
begin
Rz:=Mn*WindingRes+R;
if DynamicBrakeFlag then {hamowanie}
begin
if DynamicBrakeType>1 then
begin
//if DynamicBrakeType<>dbrake_automatic then
// MotorCurrent:=-fi*n/Rz {hamowanie silnikiem na oporach rozruchowych}
(* begin
U:=0;
Isf:=Isat;
Delta:=SQR(Isf*Rz+Mn*fi*n-U)+4*U*Isf*Rz;
MotorCurrent:=(U-Isf*Rz-Mn*fi*n+SQRT(Delta))/(2*Rz)
end*)
if (DynamicBrakeType=dbrake_switch) and (TrainType=dt_ET42) then
begin //z Megapacka
Rz:=WindingRes+R;
MotorCurrent:=-fi*n/Rz; //{hamowanie silnikiem na oporach rozruchowych}
end;
end
else
MotorCurrent:=0; {odciecie pradu od silnika}
end
else
begin
U1:=U+Mn*n*fi0*fi;
Isf:=Sign(U1)*Isat;
Delta:=SQR(Isf*Rz+Mn*fi*n-U1)+4*U1*Isf*Rz;
if Mains then
begin
if U>0 then
MotorCurrent:=(U1-Isf*Rz-Mn*fi*n+SQRT(Delta))/(2.0*Rz)
else
MotorCurrent:=(U1-Isf*Rz-Mn*fi*n-SQRT(Delta))/(2.0*Rz)
end
else
MotorCurrent:=0;
end;{else DBF}
end;{with}
end{255}
else
MotorCurrent:=0;
end;
{ if Abs(CabNo)<2 then Im:=MotorCurrent*ActiveDir*CabNo
else Im:=0;
}
if (DynamicBrakeType=dbrake_switch) and ((BrakePress>2.0) or (PipePress<3.6)) then
begin
Im:=0;
MotorCurrent:=0;
//Im:=0;
Itot:=0;
end
else
Im:=MotorCurrent;
Current:=Im; {prad brany do liczenia sily trakcyjnej}
{ EnginePower:=Im*Im*RList[MainCtrlActualPos].Bn*RList[MainCtrlActualPos].Mn*WindingRes;}
EnginePower:=Abs(Itot)*(1+RList[MainCtrlActualPos].Mn)*Abs(U);
{awarie}
MotorCurrent:=Abs(Im); {zmienna pomocnicza}
if Motorcurrent>0 then
begin
if FuzzyLogic(Abs(n),nmax*1.1,p_elengproblem) then
if MainSwitch(false) then
EventFlag:=true; {zbyt duze obroty - wywalanie wskutek ognia okreznego}
if TestFlag(DamageFlag,dtrain_engine) then
if FuzzyLogic(MotorCurrent,ImaxLo/10.0,p_elengproblem) then
if MainSwitch(false) then
EventFlag:=true; {uszkodzony silnik (uplywy)}
if (FuzzyLogic(Abs(Im),Imax*2,p_elengproblem) or FuzzyLogic(Abs(n),nmax*1.11,p_elengproblem)) then
{ or FuzzyLogic(Abs(U/Mn),2*NominalVoltage,1)) then } {poprawic potem}
if (SetFlag(DamageFlag,dtrain_engine)) then
EventFlag:=true;
{! dorobic grzanie oporow rozruchowych i silnika}
end;
end;
function T_MoverParameters.Momentum(I:real): real;
{liczy moment sily wytwarzany przez silnik elektryczny}
var SP: byte;
begin
SP:=ScndCtrlActualPos;
if (ScndInMain) then
if not (RList[MainCtrlActualPos].ScndAct=255) then
SP:=RList[MainCtrlActualPos].ScndAct;
with MotorParam[SP] do
// Momentum:=mfi*I*(1-1.0/(Abs(I)/mIsat+1));
Momentum:=mfi*I*(Abs(I)/(Abs(I)+mIsat)-mfi0);
end;
function T_MoverParameters.MomentumF(I, Iw :real; SCP: byte): real;
begin
//umozliwia dokladne sterowanie wzbudzeniem
with MotorParam[SCP] do
MomentumF:=mfi*I*Max0R(Abs(Iw)/(Abs(Iw)+mIsat)-mfi0,0);
end;
function T_MoverParameters.dizel_Momentum(dizel_fill,n,dt:real): real;
{liczy moment sily wytwarzany przez silnik spalinowy}
var Moment, enMoment, eps, newn, friction: real;
begin
{ friction:=dizel_engagefriction*(11-2*random)/10; }
friction:=dizel_engagefriction;
if enrot>0 then
begin
Moment:=dizel_Mmax*dizel_fill-(dizel_Mmax-dizel_Mnmax*dizel_fill)*sqr(enrot/(dizel_nmax-dizel_nMmax*dizel_fill))-dizel_Mstand;
{ Moment:=Moment*(1+sin(eAngle*4))-dizel_Mstand*(1+cos(eAngle*4));}
end
else Moment:=-dizel_Mstand;
if enrot<dizel_nmin/10.0 then
if (eAngle<Pi/2.0) then Moment:=Moment-dizel_Mstand; {wstrzymywanie przy malych obrotach}
//!! abs
if abs(abs(n)-enrot)<0.1 then
begin
if (Moment)>(dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction*2) then {zerwanie przyczepnosci sprzegla}
enrot:=enrot+dt*Moment/dizel_AIM
else
begin
dizel_engagedeltaomega:=0;
enrot:=abs(n); {jest przyczepnosc tarcz}
end
(*
end
end
else
begin
if (enrot=0) and (Moment<0) then
newn:=0
else
begin
//!! abs
dizel_engagedeltaomega:=enrot-n; {sliganie tarcz}
enMoment:=Moment-sign(dizel_engagedeltaomega)*dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction;
Moment:=sign(dizel_engagedeltaomega)*dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction;
dizel_engagedeltaomega:=abs(enrot-abs(n));
eps:=enMoment/dizel_AIM;
newn:=enrot+eps*dt;
if (newn*enrot<=0) and (eps*enrot<0) then
newn:=0;
end;
enrot:=newn;
end;
dizel_Momentum:=Moment;
if (enrot=0) and (not dizel_enginestart) then
Mains:=false;
end;
function T_MoverParameters.CutOffEngine: boolean; {wylacza uszkodzony silnik}
begin
CutOffEngine:=false; //Ra: wartość domyślna, sprawdzić to trzeba
if (NPoweredAxles>0) and (CabNo=0) and (EngineType=ElectricSeriesMotor) then
begin
if SetFlag(DamageFlag,-dtrain_engine) then
begin
NPoweredAxles:=NPoweredAxles div 2;
CutOffEngine:=true;
end;
end
end;
{przelacznik pradu wysokiego rozruchu}
function T_MoverParameters.MaxCurrentSwitch(State:boolean):boolean;
begin
MaxCurrentSwitch:=false;
if (EngineType=ElectricSeriesMotor) then
if (ImaxHi>ImaxLo) then
begin
if State and (Imax=ImaxLo) and (RList[MainCtrlPos].Bn<2) and not ((TrainType=dt_ET42)and(MainctrlPos>0)) then
begin
Imax:=ImaxHi;
MaxCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MaxCurrentSwitch',1,CabNo);
end;
if (not State) then
if (Imax=ImaxHi) then
if not ((TrainType=dt_ET42)and(MainctrlPos>0)) then
begin
Imax:=ImaxLo;
MaxCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MaxCurrentSwitch',0,CabNo);
end;
end;
end;
{przelacznik pradu automatycznego rozruchu}
function T_MoverParameters.MinCurrentSwitch(State:boolean):boolean;
begin
MinCurrentSwitch:=false;
if ((EngineType=ElectricSeriesMotor) and (IminHi>IminLo)) or (TrainType=dt_EZT) then
begin
if State and (Imin=IminLo) then
begin
Imin:=IminHi;
MinCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MinCurrentSwitch',1,CabNo);
end;
if (not State) and (Imin=IminHi) then
begin
Imin:=IminLo;
MinCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MinCurrentSwitch',0,CabNo);
end;
end;
end;
{reczne przelaczanie samoczynnego rozruchu}
function T_MoverParameters.AutoRelaySwitch(State:boolean):boolean;
begin
if (AutoRelayType=2) and (AutoRelayFlag<>State) then
begin
AutoRelayFlag:=State;
AutoRelaySwitch:=true;
SendCtrlToNext('AutoRelaySwitch',ord(State),CabNo);
end
else
AutoRelaySwitch:=false;
end;
function T_MoverParameters.AutoRelayCheck: boolean;
var OK:boolean; b:byte;
begin
// if ((TrainType=dt_EZT{) or (TrainType=dt_ET22)}) and (Imin=IminLo)) or ((ActiveDir<0) and (TrainType<>dt_PseudoDiesel')) then
// if RList[MainCtrlActualPos].Bn>1 then
// begin
// dec(MainCtrlActualPos);
// AutoRelayCheck:=false;
// Exit;
// end;
//yB: wychodzenie przy odcietym pradzie
if (ScndCtrlActualPos=255)then
begin
AutoRelayCheck:=false;
MainCtrlActualPos:=0;
end
else
//if (not Mains) or (FuseFlag) or (StLinFlag) then //hunter-111211: wylacznik cisnieniowy
//if ((not Mains) or (FuseFlag)) and not((DynamicBrakeFlag) and (TrainType=dt_ET42)) then
if ((not Mains) or (FuseFlag) or (StLinFlag)) and not((DynamicBrakeFlag) and (TrainType=dt_ET42)) then //hunter-111211: wylacznik cisnieniowy
begin
AutoRelayCheck:=false;
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0;
end
else
begin
OK:=false;
if DelayCtrlFlag and (MainCtrlPos=1) and (MainCtrlActualPos=1) and (LastRelayTime>InitialCtrlDelay) then
begin
DelayCtrlFlag:=false;
SetFlag(SoundFlag,sound_relay); SetFlag(SoundFlag,sound_loud);
end;
//if (TrainType<>dt_EZT) then //Ra: w EZT można dać od razu na S albo R, wał kułakowy sobie dokręci
if (LastRelayTime>CtrlDelay) and not DelayCtrlFlag then
begin
if (MainCtrlPos=0) and (TrainType<>dt_ET40) and (TrainType<>dt_EP05) then
DelayCtrlFlag:=true; //(TrainType<>dt_EZT); //EN57 nie ma czekania na 1. pozycji
if (MainCtrlPos=0) and ((TrainType=dt_ET40)or(TrainType=dt_EP05)) and (MainCtrlActualPos=0) then
DelayCtrlFlag:=true; //(TrainType<>dt_EZT); //EN57 nie ma czekania na 1. pozycji
if (((RList[MainCtrlActualPos].R=0) and ((not CoupledCtrl) or ((Imin=IminLo) and (ScndS=true)))) or (MainCtrlActualPos=RListSize))
and ((ScndCtrlActualPos>0) or (ScndCtrlPos>0)) then
begin {zmieniaj scndctrlactualpos}
if (not AutoRelayFlag) or (not MotorParam[ScndCtrlActualPos].AutoSwitch) then
begin {scnd bez samoczynnego rozruchu}
OK:=true;
if (ScndCtrlActualPos<ScndCtrlPos) then
inc(ScndCtrlActualPos)
else
if (ScndCtrlActualPos>ScndCtrlPos) and (TrainType<>dt_EZT) then
dec(ScndCtrlActualPos)
else
if (ScndCtrlActualPos>ScndCtrlPos) and (TrainType=dt_EZT) then
Exit {utkniecie walu kulakowego}
else OK:=false;
end
else
begin {scnd z samoczynnym rozruchem}
if (ScndCtrlPos<ScndCtrlActualPos) and (TrainType<>dt_EZT) then
begin
dec(ScndCtrlActualPos);
OK:=true;
end
else
if (ScndCtrlPos<ScndCtrlActualPos) and (TrainType=dt_EZT) then
begin
Exit; {utkniecie walu kulakowego}
end
else
if (ScndCtrlPos>ScndCtrlActualPos) then
if Abs(Im)<Imin then
if MotorParam[ScndCtrlActualPos].AutoSwitch then
begin
inc(ScndCtrlActualPos);
OK:=true
end;
end;
end
else
begin {zmieniaj mainctrlactualpos}
if ((TrainType=dt_EZT) and (Scnds=true) and (Imin=IminLo)) then
if RList[MainCtrlActualPos+1].Bn>1 then
begin
AutoRelayCheck:=false;
Exit;
end;
if (not AutoRelayFlag) or (not RList[MainCtrlActualPos].AutoSwitch) then
begin {main bez samoczynnego rozruchu}
OK:=true;
if RList[MainCtrlActualPos].Relay<MainCtrlPos then
if ((RList[MainCtrlActualPos].Mn>RList[MainCtrlPos].Mn)and (RList[MainCtrlActualPos+1].Mn<RList[MainCtrlActualPos].Mn) and (TrainType=dt_ET22) and (LastRelayTime<InitialCtrlDelay))then
begin
Itot:=0;
Im:=0;
OK:=false; {odciecie pradu, przy przelaczaniu silnikow w ET22}
end
else
//if (RList[MainCtrlActualPos].R=0) and (RList[MainCtrlPos].R>0) and (TrainType=dt_ET22) and (LastRelayTime<InitialCtrlDelay) then
begin
inc(MainCtrlActualPos);
//---------
//hunter-111211: poprawki
if MainCtrlActualPos>0 then
//if (RList[MainCtrlActualPos].R=0) and ((RList[MainCtrlActualPos].ScndAct=0) or (RList[MainCtrlActualPos].ScndAct=255)) then {dzwieki przechodzenia na bezoporowa}
if (RList[MainCtrlActualPos].R=0) and (not (MainCtrlActualPos=MainCtrlPosNo)) then //wejscie na bezoporowa
begin
SetFlag(SoundFlag,sound_manyrelay); SetFlag(SoundFlag,sound_loud);
end
else if (RList[MainCtrlActualPos].R>0) and (RList[MainCtrlActualPos-1].R=0) then //wejscie na drugi uklad
begin
SetFlag(SoundFlag,sound_manyrelay);
end;
end
else if (RList[MainCtrlActualPos].Relay>MainCtrlPos) and (TrainType<>dt_EZT) then
begin
if not ((RList[MainCtrlActualPos].Mn<RList[MainCtrlPos].Mn) and (RList[MainCtrlActualPos-1].Mn>RList[MainCtrlActualPos].Mn)and (TrainType=dt_ET22) and (LastRelayTime<InitialCtrlDelay))then
begin
dec(MainCtrlActualPos);
if MainCtrlActualPos>0 then //hunter-111211: poprawki
//if (RList[MainCtrlActualPos+1].R=0) and ((RList[MainCtrlActualPos+1].ScndAct=0) or (RList[MainCtrlActualPos+1].ScndAct=255)) then {dzwieki schodzenia z bezoporowej}
if RList[MainCtrlActualPos].R=0 then {dzwieki schodzenia z bezoporowej}
begin
SetFlag(SoundFlag,sound_manyrelay);
end;
end
else
begin
Itot:=0;
Im:=0;
OK:=false; {odciecie pradu, przy przelaczaniu silnikow w ET22}
end;
end
else if (RList[MainCtrlActualPos].Relay>MainCtrlPos) and (TrainType=dt_EZT) and (MainCtrlPos>0) then //K90
begin
Exit; {utkniecie walu kulakowego}
end
else if (TrainType=dt_EZT) and (MainCtrlPos=0) then
MainCtrlActualPos:=0
else
if (RList[MainCtrlActualPos].R>0) and (ScndCtrlActualPos>0) and (TrainType<>dt_EZT) then
Dec(ScndCtrlActualPos) {boczniki nie dzialaja na poz. oporowych}
else
if (ScndCtrlPos<ScndCtrlActualPos) and (TrainType=dt_EZT) then
Exit {boczniki nie dzialaja na poz. oporowych}
else
OK:=false;
end
else {main z samoczynnym rozruchem}
begin
OK:=false;
if (MainCtrlPos<RList[MainCtrlActualPos].Relay) and (TrainType<>dt_EZT) then
begin
if not ((RList[MainCtrlActualPos].Mn<RList[MainCtrlPos].Mn)and (RList[MainCtrlActualPos-1].Mn>RList[MainCtrlActualPos].Mn) and (TrainType=dt_ET22) and (LastRelayTime<InitialCtrlDelay))then
begin
dec(MainCtrlActualPos);
OK:=true;
if MainCtrlActualPos>0 then
if (RList[MainCtrlActualPos+1].R=0) and ((RList[MainCtrlActualPos+1].ScndAct=0) or (RList[MainCtrlActualPos+1].ScndAct=255)) then {dzwieki schodzenia z bezoporowej}
begin
SetFlag(SoundFlag,sound_manyrelay);
end;
end
else
begin
Itot:=0;
Im:=0;
OK:=false; {odciecie pradu, przy przelaczaniu silnikow w ET22}
end;
end
else
if (MainCtrlPos<RList[MainCtrlActualPos].Relay) and (MainCtrlPos>0) and (TrainType=dt_EZT) then
begin
AutoRelayCheck:=false;
Exit; {utkniecie walu}
end
else
if (TrainType=dt_EZT) and (MainCtrlPos=0) then
begin
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0;
end
else
if ((ScndCtrlPos<ScndCtrlActualPos) and (TrainType=dt_EZT)) then
begin
Exit; {utkniecie walu}
end
else
if (MainCtrlPos>RList[MainCtrlActualPos].Relay) or ((MainCtrlActualPos<RListSize) and (MainCtrlPos=RList[MainCtrlActualPos+1].Relay)) then
begin
if ((RList[MainCtrlActualPos].Mn>RList[MainCtrlPos].Mn) and(RList[MainCtrlActualPos+1].Mn<RList[MainCtrlActualPos].Mn) and (TrainType=dt_ET22) and (LastRelayTime<InitialCtrlDelay))then
begin
Itot:=0;
Im:=0;
OK:=false; {odciecie pradu, przy przelaczaniu silnikow w ET22}
end
else
if Abs(Im)<Imin then
begin
inc(MainCtrlActualPos);
OK:=true;
if MainCtrlActualPos>0 then
if (RList[MainCtrlActualPos].R=0) and ((RList[MainCtrlActualPos].ScndAct=0) or (RList[MainCtrlActualPos].ScndAct=255)) then {dzwieki przechodzenia na bezoporowa}
begin
SetFlag(SoundFlag,sound_manyrelay); SetFlag(SoundFlag,sound_loud);
end;
end;
end;
end;
end;
end
else {DelayCtrlFlag}
if ((MainCtrlPos>1) and (MainCtrlActualPos>0) and DelayCtrlFlag) then
begin
//if (TrainType<>dt_EZT) then //Ra: w EZT można dać od razu na S albo R, wał kułakowy sobie dokręci
MainCtrlActualPos:=0; //Ra: tu jest chyba wyłączanie przy zbyt szybkim wejściu na drugą pozycję
OK:=true;
end
else
if ((MainCtrlPos=0) and (TrainType=dt_EZT)) then
begin
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0; {zejscie walu kulakowego do 0 po ustawieniu nastawnika na 0}
OK:=true;
end
else
if (MainCtrlPos=1) and (MainCtrlActualPos=0) then
MainCtrlActualPos:=1
else
if (MainCtrlPos=0) and (MainCtrlActualPos>0) and (TrainType<>dt_EZT) and (TrainType<>dt_ET40) and (TrainType<>dt_EP05) then
begin
dec(MainCtrlActualPos);
OK:=true;
end;
if (MainCtrlPos=0) and (MainCtrlActualPos>0) and ((TrainType=dt_ET40)or(TrainType=dt_EP05)) and (LastRelayTime>(InitialCtrlDelay*2)) then
begin
dec(MainCtrlActualPos);
OK:=true; {wal kulakowy w ET40}
end;
if OK then LastRelayTime:=0;
AutoRelayCheck:=OK;
end;
end;
*)
end
else
begin
if (enrot=0) and (Moment<0) then
newn:=0
else
begin
//!! abs
dizel_engagedeltaomega:=enrot-n; {sliganie tarcz}
enMoment:=Moment-sign(dizel_engagedeltaomega)*dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction;
Moment:=sign(dizel_engagedeltaomega)*dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction;
dizel_engagedeltaomega:=abs(enrot-abs(n));
eps:=enMoment/dizel_AIM;
newn:=enrot+eps*dt;
if (newn*enrot<=0) and (eps*enrot<0) then
newn:=0;
end;
enrot:=newn;
end;
dizel_Momentum:=Moment;
if (enrot=0) and (not dizel_enginestart) then
Mains:=false;
end;
function T_MoverParameters.CutOffEngine: boolean; {wylacza uszkodzony silnik}
begin
CutOffEngine:=false; //Ra: wartość domyślna, sprawdzić to trzeba
if (NPoweredAxles>0) and (CabNo=0) and (EngineType=ElectricSeriesMotor) then
begin
if SetFlag(DamageFlag,-dtrain_engine) then
begin
NPoweredAxles:=NPoweredAxles div 2;
CutOffEngine:=true;
end;
end
end;
{przelacznik pradu wysokiego rozruchu}
function T_MoverParameters.MaxCurrentSwitch(State:boolean):boolean;
begin
MaxCurrentSwitch:=false;
if (EngineType=ElectricSeriesMotor) then
if (ImaxHi>ImaxLo) then
begin
if State and (Imax=ImaxLo) and (RList[MainCtrlPos].Bn<2) and not ((TrainType=dt_ET42)and(MainctrlPos>0)) then
begin
Imax:=ImaxHi;
MaxCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MaxCurrentSwitch',1,CabNo);
end;
if (not State) then
if (Imax=ImaxHi) then
if not ((TrainType=dt_ET42)and(MainctrlPos>0)) then
begin
Imax:=ImaxLo;
MaxCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MaxCurrentSwitch',0,CabNo);
end;
end;
end;
{przelacznik pradu automatycznego rozruchu}
function T_MoverParameters.MinCurrentSwitch(State:boolean):boolean;
begin
MinCurrentSwitch:=false;
if ((EngineType=ElectricSeriesMotor) and (IminHi>IminLo)) or (TrainType=dt_EZT) then
begin
if State and (Imin=IminLo) then
begin
Imin:=IminHi;
MinCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MinCurrentSwitch',1,CabNo);
end;
if (not State) and (Imin=IminHi) then
begin
Imin:=IminLo;
MinCurrentSwitch:=true;
if CabNo<>0 then
SendCtrlToNext('MinCurrentSwitch',0,CabNo);
end;
end;
end;
{reczne przelaczanie samoczynnego rozruchu}
function T_MoverParameters.AutoRelaySwitch(State:boolean):boolean;
begin
if (AutoRelayType=2) and (AutoRelayFlag<>State) then
begin
AutoRelayFlag:=State;
AutoRelaySwitch:=true;
SendCtrlToNext('AutoRelaySwitch',ord(State),CabNo);
end
else
AutoRelaySwitch:=false;
end;
function T_MoverParameters.AutoRelayCheck: boolean;
var OK:boolean; //b:byte;
ARFASI, ARFASI2 :boolean; //sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im<Imin)
begin
//Ra 2014-06: dla SN61 nie działa prawidłowo
//rozlaczanie stycznikow liniowych
if (not Mains) or (FuseFlag) or (MainCtrlPos=0) or ((BrakePress>2.1)and(TrainType<>dt_EZT)) or (ActiveDir=0) then //hunter-111211: wylacznik cisnieniowy
begin
StLinFlag:=false; //yBARC - rozlaczenie stycznikow liniowych
AutoRelayCheck:=false;
if not DynamicBrakeFlag then
begin
Im:=0;
Itot:=0;
ResistorsFlag:=false;
end;
end;
ARFASI2:=(not AutoRelayFlag) or ((MotorParam[ScndCtrlActualPos].AutoSwitch) and (Abs(Im)<Imin)); //wszystkie warunki w jednym
ARFASI :=(not AutoRelayFlag) or ((RList[MainCtrlActualPos].AutoSwitch) and (Abs(Im)<Imin)) or ((not RList[MainCtrlActualPos].AutoSwitch) and (RList[MainCtrlActualPos].Relay<MainCtrlPos)); //wszystkie warunki w jednym
//brak PSR na tej pozycji działa PSR i prąd poniżej progu na tej pozycji nie działa PSR i pozycja walu ponizej
// chodzi w tym wszystkim o to, żeby można było zatrzymać rozruch na jakiejś pozycji wpisując Autoswitch=0 i wymuszać
// przejście dalej przez danie nastawnika na dalszą pozycję - tak to do tej pory działało i na tym się opiera fizyka ET22-2k
////// LocalBrakePos:=byte(ARFASI)+2*byte(ARFASI2);
begin
if (StLinFlag) then
begin
if (RList[MainCtrlActualPos].R=0)and ((ScndCtrlActualPos>0) or (ScndCtrlPos>0)) and (not(CoupledCtrl)or(RList[MainCtrlActualPos].Relay=MainCtrlPos))then
begin //zmieniaj scndctrlactualpos
begin {scnd bez samoczynnego rozruchu}
if (ScndCtrlActualPos<ScndCtrlPos) then
begin
if (LastRelayTime>CtrlDelay)and(ARFASI2) then
begin
inc(ScndCtrlActualPos);
OK:=true;
end
end
else
if ScndCtrlActualPos>ScndCtrlPos then
begin
if (LastRelayTime>CtrlDownDelay)and(TrainType<>dt_EZT) then
begin
dec(ScndCtrlActualPos);
OK:=true;
end
end
else OK:=false;
end;
end
else
begin //zmieniaj mainctrlactualpos
if ((ActiveDir<0) and (TrainType<>dt_PseudoDiesel)) then
if RList[MainCtrlActualPos+1].Bn>1 then
begin
AutoRelayCheck:=false;
Exit; //Ra: to powoduje, że EN57 nie wyłącza się przy IminLo
end;
begin //main bez samoczynnego rozruchu
if (RList[MainCtrlActualPos].Relay<MainCtrlPos)or(RList[MainCtrlActualPos+1].Relay=MainCtrlPos)or((TrainType=dt_ET22)and(DelayCtrlFlag)) then
begin
if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (not (MainCtrlPos=MainCtrlPosNo)) and (FastSerialCircuit=1) then
begin
inc(MainCtrlActualPos);
// MainCtrlActualPos:=MainCtrlPos; //hunter-111012: szybkie wchodzenie na bezoporowa (303E)
OK:=true;
SetFlag(SoundFlag,sound_manyrelay); SetFlag(SoundFlag,sound_loud);
end
else if (LastRelayTime>CtrlDelay)and(ARFASI) then
begin
if (TrainType=dt_ET22)and(MainCtrlPos>1)and((RList[MainCtrlActualPos].Bn<RList[MainCtrlActualPos+1].Bn)or(DelayCtrlFlag))then //et22 z walem grupowym
if (not DelayCtrlFlag) then //najpierw przejscie
begin
inc(MainCtrlActualPos);
DelayCtrlFlag:=true; //tryb przejscia
OK:=true;
end
else if(LastRelayTime>4*CtrlDelay) then //przejscie
begin
DelayCtrlFlag:=false;
OK:=true;
end
else
else //nie ET22 z wałem grupowym
begin
inc(MainCtrlActualPos);
OK:=true;
end;
//---------
//hunter-111211: poprawki
if MainCtrlActualPos>0 then
if (RList[MainCtrlActualPos].R=0) and (not (MainCtrlActualPos=MainCtrlPosNo)) then //wejscie na bezoporowa
begin
SetFlag(SoundFlag,sound_manyrelay); SetFlag(SoundFlag,sound_loud);
end
else if (RList[MainCtrlActualPos].R>0) and (RList[MainCtrlActualPos-1].R=0) then //wejscie na drugi uklad
begin
SetFlag(SoundFlag,sound_manyrelay);
end;
end
end
else if RList[MainCtrlActualPos].Relay>MainCtrlPos then
begin
if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (not (MainCtrlPos=MainCtrlPosNo)) and (FastSerialCircuit=1) then
begin
dec(MainCtrlActualPos);
// MainCtrlActualPos:=MainCtrlPos; //hunter-111012: szybkie wchodzenie na bezoporowa (303E)
OK:=true;
SetFlag(SoundFlag,sound_manyrelay);
end
else if (LastRelayTime>CtrlDownDelay) then
begin
if (TrainType<>dt_EZT) then //tutaj powinien być tryb sterowania wałem
begin
dec(MainCtrlActualPos);
OK:=true;
end;
if MainCtrlActualPos>0 then //hunter-111211: poprawki
if RList[MainCtrlActualPos].R=0 then {dzwieki schodzenia z bezoporowej}
begin
SetFlag(SoundFlag,sound_manyrelay);
end;
end
end
else
if (RList[MainCtrlActualPos].R>0) and (ScndCtrlActualPos>0) then
begin
if (LastRelayTime>CtrlDownDelay) then
begin
Dec(ScndCtrlActualPos); {boczniki nie dzialaja na poz. oporowych}
OK:=true;
end
end
else
OK:=false;
end;
end;
end
else {not StLinFlag}
begin
OK:=false;
//ybARC - tutaj sa wszystkie warunki, jakie musza byc spelnione, zeby mozna byla zalaczyc styczniki liniowe
if ((MainCtrlPos=1)or((TrainType=dt_EZT)and(MainCtrlPos>0)))and(not FuseFlag)and(Mains)and((BrakePress<1.0)or(TrainType=dt_EZT))and(MainCtrlActualPos=0)and(ActiveDir<>0) then
begin
DelayCtrlFlag:=true;
if (LastRelayTime>=InitialCtrlDelay) then
begin
StLinFlag:=true; //ybARC - zalaczenie stycznikow liniowych
MainCtrlActualPos:=1;
DelayCtrlFlag:=false;
SetFlag(SoundFlag,sound_relay); SetFlag(SoundFlag,sound_loud);
OK:=true;
end;
end
else
DelayCtrlFlag:=false;
if (not StLinFlag)and((MainCtrlActualPos>0)or(ScndCtrlActualPos>0)) then
if (TrainType=dt_EZT)and(CoupledCtrl)then //EN57 wal jednokierunkowy calosciowy
begin
if(MainCtrlActualPos=1)then
begin
MainCtrlActualPos:=0;
OK:=true;
end
else
if(LastRelayTime>CtrlDownDelay)then
begin
if(MainCtrlActualPos<RListSize)then
inc(MainCtrlActualPos) //dojdz do konca
else if(ScndCtrlActualPos<ScndCtrlPosNo)then
inc(ScndCtrlActualPos) //potem boki
else
begin //i sie przewroc na koniec
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0;
end;
OK:=true;
end
end
else if(CoupledCtrl)then //wal kulakowy dwukierunkowy
begin
if (LastRelayTime>CtrlDownDelay) then
begin
if (ScndCtrlActualPos>0) then
dec(ScndCtrlActualPos)
else dec(MainCtrlActualPos);
OK:=true;
end
end
else
begin
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0;
OK:=true;
end;
end;
if OK then LastRelayTime:=0;
AutoRelayCheck:=OK;
end;
end;
function T_MoverParameters.ResistorsFlagCheck:boolean; {sprawdzanie wskaznika oporow}
var b:byte;
begin
ResistorsFlagCheck:=false;
if Power>0.01 then ResistorsFlagCheck:=ResistorsFlag
else {pobor pradu jezeli niema mocy}
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected.Power>0.01 then
ResistorsFlagCheck:=Connected.ResistorsFlagCheck();
end;
function T_MoverParameters.dizel_EngageSwitch(state: real): boolean;
{zmienia parametr do ktorego dazy sprzeglo}
begin
if (EngineType=DieselEngine) and (state<=1) and (state>=0) and (state<>dizel_engagestate) then
begin
dizel_engagestate:=state;
dizel_EngageSwitch:=true
end
else
dizel_EngageSwitch:=false;
end;
function T_MoverParameters.dizel_EngageChange(dt: real): boolean;
{zmienia parametr do ktorego dazy sprzeglo}
const engagedownspeed=0.9; engageupspeed=0.5;
var engagespeed:real; //OK:boolean;
begin
dizel_EngageChange:=false;
if dizel_engage-dizel_engagestate>0 then
engagespeed:=engagedownspeed
else
engagespeed:=engageupspeed;
if dt>0.2 then
dt:=0.1;
if abs(dizel_engage-dizel_engagestate)<0.11 then
begin
if (dizel_engage<>dizel_engagestate) then
begin
dizel_EngageChange:=true;
dizel_engage:=dizel_engagestate;
end
//else OK:=false; //już jest false
end
else
begin
dizel_engage:=dizel_engage+engagespeed*dt*(dizel_engagestate-dizel_engage);
//OK:=false;
end;
//dizel_EngageChange:=OK;
end;
(*
function T_MoverParameters.dizel_rotateengine(Momentum,dt,n,engage:real): real;
{oblicza obroty silnika}
var newn,eps:real;
begin
if (Momentum<0) and (n=0) and (enrot=0) then
newn:=0
else
begin
if (enrot<dizel_nmin/16) and (Momentum>0) then
Momentum:=0 {nie dziala przy b. malych obrotach}
else
if enrot<dizel_nmin/4 then
begin
if (eAngle>Pi/2) then Momentum:=Momentum-2*dizel_Mstand
end
else
if enrot<dizel_nmin then
if (eAngle>Pi) then Momentum:=Momentum-dizel_Mstand; {wstrzymywanie przy malych obrotach}
eps:=Momentum/dizel_AIM;
if engage<0.9 then {niepelny docisk - poslizg}
begin
newn:=(1-engage)*(enrot+eps*dt)+engage*(n+eps*dt);
if (newn*enrot<=0) and (eps*enrot<0) then
newn:=0;
end
else
newn:=n; {bez poslizgu sprzegla}
end;
dizel_rotateengine:=newn;
{todo: uwzglednianie AIM przy ruszaniu}
end;
*)
function T_MoverParameters.dizel_fillcheck(mcp:byte): real;
{oblicza napelnienie, uzwglednia regulator obrotow}
var realfill,nreg: real;
begin
realfill:=0;
nreg:=0;
if Mains and (MainCtrlPosNo>0) then
begin
if dizel_enginestart and (LastSwitchingTime>=0.9*InitialCtrlDelay) then {wzbogacenie przy rozruchu}
realfill:=1
else
realfill:=RList[mcp].R; {napelnienie zalezne od MainCtrlPos}
if dizel_nmax_cutoff>0 then
begin
case RList[MainCtrlPos].Mn of
0,1: nreg:=dizel_nmin;
2: if(dizel_automaticgearstatus=0)then
nreg:=dizel_nmax
else
nreg:=dizel_nmin;
else realfill:=0; {sluczaj}
end;
if enrot>nreg then
realfill:=realfill*(3.9-3.0*abs(enrot)/nreg);
if enrot>dizel_nmax_cutoff then
realfill:=realfill*(9.8-9.0*abs(enrot)/dizel_nmax_cutoff);
if enrot<dizel_nmin then
realfill:=realfill*(1+(dizel_nmin-abs(enrot))/dizel_nmin);
end;
end;
if realfill<0 then
realfill:=0;
if realfill>1 then
realfill:=1;
dizel_fillcheck:=realfill;
end;
function T_MoverParameters.dizel_AutoGearCheck: boolean;
{automatycznie zmienia biegi gdy predkosc przekroczy widelki}
var OK: boolean;
begin
OK:=false;
if MotorParam[ScndCtrlActualPos].AutoSwitch and Mains then
begin
if (RList[MainCtrlPos].Mn=0) then
begin
if (dizel_engagestate>0) then
dizel_EngageSwitch(0);
if (MainCtrlPos=0) and (ScndCtrlActualPos>0) then
dizel_automaticgearstatus:=-1
end
else
begin
if MotorParam[ScndCtrlActualPos].AutoSwitch and (dizel_automaticgearstatus=0) then {sprawdz czy zmienic biegi}
begin
if (Vel>MotorParam[ScndCtrlActualPos].mfi) and (ScndCtrlActualPos<ScndCtrlPosNo) then
begin
dizel_automaticgearstatus:=1;
OK:=true
end
else
if (Vel<MotorParam[ScndCtrlActualPos].fi) and (ScndCtrlActualPos>0) then
begin
dizel_automaticgearstatus:=-1;
OK:=true
end;
end;
end;
if (dizel_engage<0.1) and (dizel_automaticgearstatus<>0) then
begin
if dizel_automaticgearstatus=1 then
inc(ScndCtrlActualPos)
else
dec(ScndCtrlActualPos);
dizel_automaticgearstatus:=0;
{} dizel_EngageSwitch(1.0); {}
OK:=true;
end
end;
if Mains then
begin
if (dizel_automaticgearstatus=0) then {ustaw cisnienie w silowniku sprzegla}
case RList[MainCtrlPos].Mn of
1: dizel_EngageSwitch(0.5);
2: dizel_EngageSwitch(1.0);
else dizel_EngageSwitch(0.0)
end
else
dizel_EngageSwitch(0.0);
if not (MotorParam[ScndCtrlActualPos].mIsat>0) then
dizel_EngageSwitch(0.0); //wylacz sprzeglo na pozycjach neutralnych
if not AutoRelayFlag then
ScndCtrlActualPos:=ScndCtrlPos;
end;
dizel_AutoGearCheck:=OK;
end;
function T_MoverParameters.dizel_Update(dt:real): boolean;
{odświeża informacje o silniku}
//var OK:boolean;
const fillspeed=2;
begin
//dizel_Update:=false;
if dizel_enginestart and (LastSwitchingTime>=InitialCtrlDelay) then
begin
dizel_enginestart:=false;
LastSwitchingTime:=0;
enrot:=dizel_nmin/2.0; {TODO: dac zaleznie od temperatury i baterii}
end;
{OK:=}dizel_EngageChange(dt);
// if AutoRelayFlag then Poprawka na SM03
dizel_Update:=dizel_AutoGearCheck;
{ dizel_fill:=(dizel_fill+dizel_fillcheck(MainCtrlPos))/2; }
dizel_fill:=dizel_fill+fillspeed*dt*(dizel_fillcheck(MainCtrlPos)-dizel_fill);
//dizel_Update:=OK;
end;
{przyczepnosc}
function T_MoverParameters.Adhesive(staticfriction:real): real;
//var Adhesion: real;
begin
{Adhesion:=0;
case SlippingWheels of
true:
if SandDose then
Adhesion:=0.48
else
Adhesion:=staticfriction*0.2;
false:
if SandDose then
Adhesion:=Max0R(staticfriction*(100+Vel)/(50+Vel)*1.1,0.48)
else
Adhesion:=staticfriction*(100+Vel)/(50+Vel)
end;
Adhesion:=Adhesion*(11-2*random)/10;
Adhesive:=Adhesion;}
//ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS?
// w kazdym razie zaciemni kod na pewno :)
if SlippingWheels=false then
begin
if SandDose then
Adhesive:=(Max0R(staticfriction*(100.0+Vel)/((50.0+Vel)*11.0),0.048))*(11.0-2.0*random)
else
Adhesive:=(staticfriction*(100.0+Vel)/((50.0+Vel)*10))*(11.0-2.0*random);
end
else
begin
if SandDose then
Adhesive:=(0.048)*(11-2*random)
else
Adhesive:=(staticfriction*0.02)*(11-2*random);
end;
end;
{SILY}
function T_MoverParameters.TractionForce(dt:real):real;
const kv=0.2; ksum=0.05;
var PosRatio,dmoment,dtrans,tmp,tmpV: real;
i: byte;
{oblicza sile trakcyjna lokomotywy (dla elektrowozu tez calkowity prad)}
begin
Ft:=0;
dtrans:=0;
dmoment:=0;
// tmpV:=Abs(nrot*WheelDiameter/2);
//youBy
if (EngineType=DieselElectric) then
begin
tmp:=DEList[MainCtrlPos].rpm/60.0;
if (Heating) and (HeatingPower>0) and (MainCtrlPosNo>MainCtrlPos) then
begin
i:=MainCtrlPosNo;
while (DEList[i-2].rpm/60.0>tmp) do
i:=i-1;
tmp:=DEList[i].rpm/60.0
end;
if enrot<>tmp*Byte(ConverterFlag) then
if ABS(tmp*Byte(ConverterFlag) - enrot) < 0.001 then
enrot:=tmp*Byte(ConverterFlag)
else
if (enrot<DEList[0].rpm*0.01) and (ConverterFlag) then
enrot:=enrot + (tmp*Byte(ConverterFlag) - enrot)*dt/5.0
else
enrot:=enrot + (tmp*Byte(ConverterFlag) - enrot)*1.5*dt;
end
else
if EngineType<>DieselEngine then
enrot:=Transmision.Ratio*nrot
else //dla DieselEngine
begin
if (ShuntMode) then //dodatkowa przekładnia np. dla 2Ls150
dtrans:=AnPos*Transmision.Ratio*MotorParam[ScndCtrlActualPos].mIsat
else
dtrans:=Transmision.Ratio*MotorParam[ScndCtrlActualPos].mIsat;
dmoment:=dizel_Momentum(dizel_fill,ActiveDir*1*dtrans*nrot,dt); {oblicza tez enrot}
end;
eAngle:=eAngle+enrot*dt;
if eAngle>Pirazy2 then
//eAngle:=Pirazy2-eAngle; <- ABu: a nie czasem tak, jak nizej?
eAngle:=eAngle-Pirazy2;
//hunter-091012: przeniesione z if ActiveDir<>0 (zeby po zejsciu z kierunku dalej spadala predkosc wentylatorow)
if (EngineType=ElectricSeriesMotor) then
begin
case RVentType of {wentylatory rozruchowe}
1: if ActiveDir<>0 and (RList[MainCtrlActualPos].R>RVentCutOff) then
RventRot:=RventRot+(RVentnmax-RventRot)*RVentSpeed*dt
else
RventRot:=RventRot*(1-RVentSpeed*dt);
2: if (Abs(Itot)>RVentMinI) and (RList[MainCtrlActualPos].R>RVentCutOff) then
RventRot:=RventRot+(RVentnmax*Abs(Itot)/(ImaxLo*RList[MainCtrlActualPos].Bn)-RventRot)*RVentSpeed*dt
else
if (DynamicBrakeType=dbrake_automatic) and (DynamicBrakeFlag) then
RventRot:=RventRot+(RVentnmax*Im/ImaxLo-RventRot)*RVentSpeed*dt
else
begin
RventRot:=RventRot*(1-RVentSpeed*dt);
if RventRot<0.1 then RventRot:=0;
end;
end; {case}
end; {if}
if ActiveDir<>0 then
case EngineType of
Dumb:
begin
PosRatio:=(MainCtrlPos+ScndCtrlPos)/(MainCtrlPosNo+ScndCtrlPosNo+0.01);
if Mains and (ActiveDir<>0) and (CabNo<>0) then
begin
if Vel>0.1 then
begin
Ft:=Min0R(1000.0*Power/Abs(V),Ftmax)*PosRatio;
end
else Ft:=Ftmax*PosRatio;
Ft:=Ft*DirAbsolute; //ActiveDir*CabNo;
end
else Ft:=0;
EnginePower:=1000*Power*PosRatio;
end;
WheelsDriven:
begin
if EnginePowerSource.SourceType=InternalSource then
if EnginePowerSource.PowerType=BioPower then
Ft:=sign(sin(eAngle))*PulseForce*Transmision.Ratio;
PulseForceTimer:=PulseForceTimer+dt;
if PulseForceTimer>CtrlDelay then
begin
PulseForce:=0;
if PulseForceCount>0 then
dec(PulseForceCount);
end;
EnginePower:=Ft*(1+Vel);
end;
ElectricSeriesMotor:
begin
{ enrot:=Transmision.Ratio*nrot; }
//yB: szereg dwoch sekcji w ET42
if(TrainType=dt_ET42)and(Imax=ImaxHi)then
Voltage:=Voltage/2.0;
Mm:=Momentum(Current(enrot,Voltage)); {oblicza tez prad p/slinik}
if(TrainType=dt_ET42)then
begin
if(Imax=ImaxHi)then
Voltage:=Voltage*2;
if(DynamicBrakeFlag)and(Abs(Im)>300)then
FuseOff;
end;
if (DynamicBrakeType=dbrake_automatic)and(DynamicBrakeFlag) then
begin
if ((Vadd+Abs(Im))>760)or((Hamulec as TLSt).GetEDBCP<0.25) then
begin
Vadd:=Vadd-500*dt;
if(Vadd<1)then
Vadd:=0;
end
else if (DynamicBrakeFlag)and((Vadd+Abs(Im))<740) then
begin
Vadd:=Vadd+70*dt;
Vadd:=Min0R(Max0R(Vadd,60),400);
end;
if(Vadd>0)then Mm:=MomentumF(Im,Vadd,0);
end;
if(TrainType=dt_ET22)and(DelayCtrlFlag)then //szarpanie przy zmianie układu w byku
Mm:=Mm*RList[MainCtrlActualPos].Bn/(RList[MainCtrlActualPos].Bn+1); //zrobione w momencie, żeby nie dawac elektryki w przeliczaniu sił
if (Abs(Im)>Imax) then
Vhyp:=Vhyp+dt//*(Abs(Im)/Imax-0.9)*10 //zwieksz czas oddzialywania na PN
else
Vhyp:=0;
if (Vhyp>CtrlDelay/2) then //jesli czas oddzialywania przekroczony
// dec(MainCtrlActualPos);
FuseOff; {wywalanie bezpiecznika z powodu przetezenia silnikow}
if (Mains) then //nie wchodzić w funkcję bez potrzeby
if (Abs(Voltage)<EnginePowerSource.CollectorParameters.MinV) or (Abs(Voltage)*EnginePowerSource.CollectorParameters.OVP>EnginePowerSource.CollectorParameters.MaxV) then
if MainSwitch(false) then
EventFlag:=true; //wywalanie szybkiego z powodu niewłaściwego napięcia
if (((DynamicBrakeType=dbrake_automatic)or(DynamicBrakeType=dbrake_switch)) and (DynamicBrakeFlag)) then
Itot:=Im*2 {2x2 silniki w EP09}
else if (TrainType=dt_EZT)and(Imin=IminLo)and(ScndS) then //yBARC - boczniki na szeregu poprawnie
Itot:=Im
else
Itot:=Im*RList[MainCtrlActualPos].Bn; {prad silnika * ilosc galezi}
Mw:=Mm*Transmision.Ratio;
Fw:=Mw*2.0/WheelDiameter;
Ft:=Fw*NPoweredAxles; {sila trakcyjna}
end;
DieselEngine: begin
EnginePower:=dmoment*enrot;
if MainCtrlPos>1 then
dmoment:=dmoment-dizel_Mstand*(0.2*enrot/nmax); {dodatkowe opory z powodu sprezarki}
Mm:=dizel_engage*dmoment;
Mw:=Mm*dtrans; {dmoment i dtrans policzone przy okazji enginerotation}
Fw:=Mw*2.0/WheelDiameter;
Ft:=Fw*NPoweredAxles; {sila trakcyjna}
Ft:=Ft*DirAbsolute; //ActiveDir*CabNo;
end;
DieselElectric: //youBy
begin
// tmpV:=V*CabNo*ActiveDir;
tmpV:=nrot*Pirazy2*0.5*WheelDiameter*DirAbsolute; //*CabNo*ActiveDir;
//jazda manewrowa
if (ShuntMode) then
begin
Voltage:=(SST[MainCtrlPos].Umax * AnPos) + (SST[MainCtrlPos].Umin * (1 - AnPos));
tmp:=(SST[MainCtrlPos].Pmax * AnPos) + (SST[MainCtrlPos].Pmin * (1 - AnPos));
Ft:=tmp * 1000.0 / (abs(tmpV)+1.6);
PosRatio:=1;
end
else //jazda ciapongowa
begin
tmp:=Min0R(DEList[MainCtrlPos].genpower,Power-HeatingPower*byte(Heating));
PosRatio:=DEList[MainCtrlPos].genpower / DEList[MainCtrlPosNo].genpower; {stosunek mocy teraz do mocy max}
if (MainCtrlPos>0) and (ConverterFlag) then
if tmpV < (Vhyp*(Power-HeatingPower*byte(Heating))/DEList[MainCtrlPosNo].genpower) then //czy na czesci prostej, czy na hiperboli
Ft:=(Ftmax - ((Ftmax - 1000.0 * DEList[MainCtrlPosNo].genpower / (Vhyp+Vadd)) * (tmpV/Vhyp) / PowerCorRatio)) * PosRatio //posratio - bo sila jakos tam sie rozklada
//Ft:=(Ftmax - (Ftmax - (1000.0 * DEList[MainCtrlPosNo].genpower / (Vhyp+Vadd) / PowerCorRatio)) * (tmpV/Vhyp)) * PosRatio //wersja z Megapacka
else //na hiperboli //1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka
Ft:=1000.0 * tmp / (tmpV+Vadd) / PowerCorRatio //tu jest zawarty stosunek mocy
else Ft:=0; //jak nastawnik na zero, to sila tez zero
PosRatio:=tmp/DEList[MainCtrlPosNo].genpower;
end;
if (FuseFlag) then Ft:=0 else
Ft:=Ft*DirAbsolute; //ActiveDir * CabNo; //zwrot sily i jej wartosc
Fw:=Ft/NPoweredAxles; //sila na obwodzie kola
Mw:=Fw*WheelDiameter / 2.0; // moment na osi kola
Mm:=Mw/Transmision.Ratio; // moment silnika trakcyjnego
with MotorParam[ScndCtrlPos] do
if ABS(Mm) > fi then
Im:=NPoweredAxles * ABS(ABS(Mm) / mfi + mIsat)
else
Im:=NPoweredAxles * sqrt(ABS(Mm * Isat));
if (ShuntMode) then
begin
EnginePower:=Voltage * Im/1000.0;
if (EnginePower > tmp) then
begin
EnginePower:=tmp*1000.0;
Voltage:=EnginePower/Im;
end;
if (EnginePower < tmp) then
Ft:=Ft * EnginePower / tmp;
end
else
begin
if (ABS(Im) > DEList[MainCtrlPos].Imax) then
begin //nie ma nadmiarowego, tylko Imax i zwarcie na pradnicy
Ft:=Ft/Im*DEList[MainCtrlPos].Imax;Im:=DEList[MainCtrlPos].Imax;
end;
if (Im > 0) then //jak pod obciazeniem
if (Flat) then //ograniczenie napiecia w pradnicy - plaszczak u gory
Voltage:=1000.0 * tmp / ABS(Im)
else //charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa
begin
Voltage:=sqrt(ABS(sqr(DEList[MainCtrlPos].Umax)-sqr(DEList[MainCtrlPos].Umax*Im/DEList[MainCtrlPos].Imax)))*(MainCtrlPos-1)+
(1-Im/DEList[MainCtrlPos].Imax)*DEList[MainCtrlPos].Umax*(MainCtrlPosNo-MainCtrlPos);
Voltage:=Voltage/(MainCtrlPosNo-1);
Voltage:=Min0R(Voltage,(1000.0 * tmp / ABS(Im)));
if Voltage<(Im*0.05) then Voltage:=Im*0.05;
end;
if (Voltage > DEList[MainCtrlPos].Umax) or (Im = 0) then //gdy wychodzi za duze napiecie
Voltage:=DEList[MainCtrlPos].Umax * byte(ConverterFlag); //albo przy biegu jalowym (jest cos takiego?)
EnginePower:=Voltage * Im / 1000.0;
if (tmpV>2) and (EnginePower<tmp) then
Ft:=Ft*EnginePower/tmp;
end;
if (Imax>1) and (Im>Imax) then FuseOff;
if FuseFlag then Voltage:=0;
//przekazniki bocznikowania, kazdy inny dla kazdej pozycji
if (MainCtrlPos = 0) or (ShuntMode) then
ScndCtrlPos:=0
else if AutoRelayFlag then
case RelayType of
0: begin
if (Im <= (MPTRelay[ScndCtrlPos].Iup*PosRatio)) and (ScndCtrlPos<ScndCtrlPosNo) then
inc(ScndCtrlPos);
if (Im >= (MPTRelay[ScndCtrlPos].Idown*PosRatio)) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
end;
1: begin
if (MPTRelay[ScndCtrlPos].Iup<Vel) and (ScndCtrlPos<ScndCtrlPosNo) then
inc(ScndCtrlPos);
if (MPTRelay[ScndCtrlPos].Idown>Vel) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
end;
2: begin
if (MPTRelay[ScndCtrlPos].Iup<Vel) and (ScndCtrlPos<ScndCtrlPosNo) and (EnginePower<(tmp*0.99)) then
inc(ScndCtrlPos);
if (MPTRelay[ScndCtrlPos].Idown<Im) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
end;
41:
begin
if (MainCtrlPos=MainCtrlPosNo) and (tmpV*3.6>MPTRelay[ScndCtrlPos].Iup) and (ScndCtrlPos<ScndCtrlPosNo)then
begin inc(ScndCtrlPos); enrot:=enrot*0.73; end;
if (Im>MPTRelay[ScndCtrlPos].Idown)and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
end;
45:
begin
//wzrastanie
if (MainCtrlPos>11) and (ScndCtrlPos<ScndCtrlPosNo) then
if (ScndCtrlPos=0) then
if (MPTRelay[ScndCtrlPos].Iup>Im) then
inc(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos].Iup<Vel) then
inc(ScndCtrlPos);
//malenie
if(ScndCtrlPos>0)and(MainCtrlPos<12)then
if (ScndCtrlPos=ScndCtrlPosNo)then
if (MPTRelay[ScndCtrlPos].Idown<Im)then
dec(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos].Idown>Vel)then
dec(ScndCtrlPos);
if (MainCtrlPos<11)and(ScndCtrlPos>2) then ScndCtrlPos:=2;
if (MainCtrlPos<9)and(ScndCtrlPos>0) then ScndCtrlPos:=0;
end;
46:
begin
//wzrastanie
if (MainCtrlPos>9) and (ScndCtrlPos<ScndCtrlPosNo) then
if (ScndCtrlPos) mod 2 = 0 then
if (MPTRelay[ScndCtrlPos].Iup>Im) then
inc(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos-1].Iup>Im) and (MPTRelay[ScndCtrlPos].Iup<Vel) then
inc(ScndCtrlPos);
//malenie
if (MainCtrlPos<10) and (ScndCtrlPos>0)then
if (ScndCtrlPos) mod 2 = 0 then
if (MPTRelay[ScndCtrlPos].Idown<Im)then
dec(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos+1].Idown<Im) and (MPTRelay[ScndCtrlPos].Idown>Vel)then
dec(ScndCtrlPos);
if (MainCtrlPos<9)and(ScndCtrlPos>2) then ScndCtrlPos:=2;
if (MainCtrlPos<6)and(ScndCtrlPos>0) then ScndCtrlPos:=0;
end;
end;
end;
ElectricInductionMotor:
begin
if (Mains) then //nie wchodzić w funkcję bez potrzeby
if (Abs(Voltage)<EnginePowerSource.CollectorParameters.MinV) or (Abs(Voltage)>EnginePowerSource.CollectorParameters.MaxV+200) then
begin
MainSwitch(false);
end;
tmpV:=abs(nrot)*(Pi*WheelDiameter)*3.6;//*DirAbsolute*eimc[eimc_s_p]; - do przemyslenia dzialanie pp
if (MainS) then
begin
dtrans:=(Hamulec as TLSt).GetEDBCP;
if ((DoorLeftOpened)or(DoorRightOpened)) then
DynamicBrakeFlag:=true
else if ((dtrans<0.25) and (LocHandle.GetCP<0.25) and (AnPos<0.01)) or ((dtrans<0.25) and (ShuntModeAllow) and (LocalBrakePos=0)) then
DynamicBrakeFlag:=false
else if (((BrakePress>0.25) and (dtrans>0.25) or (LocHandle.GetCP>0.25))) or (AnPos>0.02) then
DynamicBrakeFlag:=true;
dtrans:=(Hamulec as TLSt).GetEDBCP*eimc[eimc_p_abed]; //stala napedu
if(DynamicBrakeFlag)then
begin
if eimv[eimv_Fmax]*sign(V)*DirAbsolute<-1 then
begin
PosRatio:=-sign(V)*DirAbsolute*eimv[eimv_Fr]/(eimc[eimc_p_Fh]*Max0R(dtrans/MaxBrakePress[0],AnPos){dizel_fill});
end
else
PosRatio:=0;
PosRatio:=round(20*Posratio)/20;
if PosRatio<19.5/20 then PosRatio:=PosRatio*0.9;
// if PosRatio<0 then
// PosRatio:=2+PosRatio-2;
(Hamulec as TLSt).SetED(Max0R(0.0,Min0R(PosRatio,1)));
// (Hamulec as TLSt).SetLBP(LocBrakePress*(1-PosRatio));
PosRatio:=-Max0R(Min0R(dtrans/MaxBrakePress[0],1),AnPos)*Max0R(0,Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0])));
eimv[eimv_Fzad]:=-Max0R(LocalBrakeRatio,dtrans/MaxBrakePress[0]);
tmp:=5;
end
else
begin
PosRatio:=(MainCtrlPos/MainCtrlPosNo);
eimv[eimv_Fzad]:=PosRatio;
if(Flat)and(eimc[eimc_p_F0]*eimv[eimv_Fful]>0)then
PosRatio:=Min0R(PosRatio*eimc[eimc_p_F0]/eimv[eimv_Fful],1);
if ScndCtrlActualPos>0 then
if (Vmax<250) then
PosRatio:=Min0R(PosRatio,Max0R(-1,0.5*(ScndCtrlActualPos-Vel)))
else
PosRatio:=Min0R(PosRatio,Max0R(-1,0.5*(ScndCtrlActualPos*2-Vel)));
PosRatio:=1.0*(PosRatio*0+1)*PosRatio;
(Hamulec as TLSt).SetED(0);
// (Hamulec as TLSt).SetLBP(LocBrakePress);
if (PosRatio>dizel_fill) then tmp:=1 else tmp:=4; //szybkie malenie, powolne wzrastanie
end;
// if SlippingWheels then begin PosRatio:=0; tmp:=10; SandDoseOn; end;//przeciwposlizg
// if(Flat)then //PRZECIWPOŚLIZG
dmoment:=eimv[eimv_Fful];
// else
// dmoment:=eimc[eimc_p_F0]*0.99;
if (abs((PosRatio+9.66*dizel_fill)*dmoment*100)>0.95*Adhesive(RunningTrack.friction)*TotalMassxg) then begin PosRatio:=0; tmp:=4; SandDoseOn; end;//przeciwposlizg
if (abs((PosRatio+9.80*dizel_fill)*dmoment*100)>0.95*Adhesive(RunningTrack.friction)*TotalMassxg) then begin PosRatio:=0; tmp:=9; SandDoseOn; end;//przeciwposlizg
if (SlippingWheels) then begin PosRatio:=-PosRatio*0; tmp:=9; SandDoseOn; end;//przeciwposlizg
dizel_fill:=dizel_fill+Max0R(Min0R(PosRatio-dizel_fill,0.1),-0.1)*2*(tmp{2{+4*byte(PosRatio<dizel_fill)})*dt; //wartość zadana/procent czegoś
if(DynamicBrakeFlag)then tmp:=eimc[eimc_f_Uzh] else tmp:=eimc[eimc_f_Uzmax];
eimv[eimv_Uzsmax]:=Min0R(Voltage-eimc[eimc_f_DU],tmp);
eimv[eimv_fkr]:=eimv[eimv_Uzsmax]/eimc[eimc_f_cfu];
if(dizel_fill<0)then
eimv[eimv_Pmax]:=eimc[eimc_p_Ph]
else
eimv[eimv_Pmax]:=Min0R(eimc[eimc_p_Pmax],0.001*Voltage*(eimc[eimc_p_Imax]-eimc[eimc_f_I0])*Pirazy2*eimc[eimc_s_cim]/eimc[eimc_s_p]/eimc[eimc_s_cfu]);
eimv[eimv_FMAXMAX]:=0.001*SQR(Min0R(eimv[eimv_fkr]/Max0R(abs(enrot)*eimc[eimc_s_p]+eimc[eimc_s_dfmax]*eimv[eimv_ks],eimc[eimc_s_dfmax]),1)*eimc[eimc_f_cfu]/eimc[eimc_s_cfu])*(eimc[eimc_s_dfmax]*eimc[eimc_s_dfic]*eimc[eimc_s_cim])*Transmision.Ratio*NPoweredAxles*2/WheelDiameter;
if(dizel_fill<0)then
begin
eimv[eimv_Fful]:=Min0R(eimc[eimc_p_Ph]*3.6/Vel,Min0R(eimc[eimc_p_Fh],eimv[eimv_FMAXMAX]));
eimv[eimv_Fmax]:=-sign(V)*(DirAbsolute)*Min0R(eimc[eimc_p_Ph]*3.6/Vel,Min0R(-eimc[eimc_p_Fh]*dizel_fill,eimv[eimv_FMAXMAX]));//*Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0]))
end
else
begin
eimv[eimv_Fful]:=Min0R(Min0R(3.6*eimv[eimv_Pmax]/Max0R(Vel,1),eimc[eimc_p_F0]-Vel*eimc[eimc_p_a1]),eimv[eimv_FMAXMAX]);
// if(not Flat)then
eimv[eimv_Fmax]:=eimv[eimv_Fful]*dizel_fill
// else
// eimv[eimv_Fmax]:=Min0R(eimc[eimc_p_F0]*dizel_fill,eimv[eimv_Fful]);
end;
eimv[eimv_ks]:=eimv[eimv_Fmax]/eimv[eimv_FMAXMAX];
eimv[eimv_df]:=eimv[eimv_ks]*eimc[eimc_s_dfmax];
eimv[eimv_fp]:=DirAbsolute*enrot*eimc[eimc_s_p]+eimv[eimv_df]; //do przemyslenia dzialanie pp z tmpV
// eimv[eimv_U]:=Max0R(eimv[eimv_Uzsmax],Min0R(eimc[eimc_f_cfu]*eimv[eimv_fp],eimv[eimv_Uzsmax]));
// eimv[eimv_pole]:=eimv[eimv_U]/(eimv[eimv_fp]*eimc[eimc_s_cfu]);
if(abs(eimv[eimv_fp])<=eimv[eimv_fkr])then
eimv[eimv_pole]:=eimc[eimc_f_cfu]/eimc[eimc_s_cfu]
else
eimv[eimv_pole]:=eimv[eimv_Uzsmax]/eimc[eimc_s_cfu]/abs(eimv[eimv_fp]);
eimv[eimv_U]:=eimv[eimv_pole]*eimv[eimv_fp]*eimc[eimc_s_cfu];
eimv[eimv_Ic]:=(eimv[eimv_fp]-DirAbsolute*enrot*eimc[eimc_s_p])*eimc[eimc_s_dfic]*eimv[eimv_pole];
eimv[eimv_If]:=eimv[eimv_Ic]*eimc[eimc_s_icif];
eimv[eimv_M]:=eimv[eimv_pole]*eimv[eimv_Ic]*eimc[eimc_s_cim];
eimv[eimv_Ipoj]:=(eimv[eimv_Ic]*NPoweredAxles*eimv[eimv_U])/(Voltage-eimc[eimc_f_DU])+eimc[eimc_f_I0];
eimv[eimv_Pm]:=ActiveDir*eimv[eimv_M]*NPoweredAxles*enrot*Pirazy2/1000;
eimv[eimv_Pe]:=eimv[eimv_Ipoj]*Voltage/1000;
eimv[eimv_eta]:=eimv[eimv_Pm]/eimv[eimv_Pe];
Im:=eimv[eimv_If];
if (eimv[eimv_Ipoj]>=0) then
Vadd:=Vadd*(1-2*dt)
else if (Voltage<EnginePowerSource.CollectorParameters.MaxV) then
Vadd:=Vadd*(1-dt)
else
Vadd:=Max0R(Vadd*(1-0.2*dt),0.007*(Voltage-(EnginePowerSource.CollectorParameters.MaxV-100)));
Itot:=eimv[eimv_Ipoj]*(0.01+Min0R(0.99,0.99-Vadd));
EnginePower:=Abs(eimv[eimv_Ic]*eimv[eimv_U]*NPoweredAxles)/1000;
tmpV:=eimv[eimv_fp];
if ((abs(eimv[eimv_If])>1) or (abs(tmpV)>0.1))and(RlistSize>0) then
begin
i:=0;
while (i<RlistSize-1)and(DEList[i+1].RPM<abs(tmpV))do inc(i);
RventRot:=(abs(tmpV)-DEList[i].RPM)/(DEList[i+1].RPM-DEList[i].RPM)*(DEList[i+1].GenPower-DEList[i].GenPower)+DEList[i].GenPower;
end
else RVentRot:=0;
Mm:=eimv[eimv_M]*DirAbsolute;
Mw:=Mm*Transmision.Ratio;
Fw:=Mw*2.0/WheelDiameter;
Ft:=Fw*NPoweredAxles;
eimv[eimv_Fr]:=DirAbsolute*Ft/1000;
// RventRot;
end
else
begin
Im:=0;Mm:=0;Mw:=0;Fw:=0;Ft:=0;Itot:=0;dizel_fill:=0;EnginePower:=0;
for i:=1 to 20 do
eimv[i]:=0;
(Hamulec as TLSt).SetED(0);RventRot:=0.0;//(Hamulec as TLSt).SetLBP(LocBrakePress);
end;
end;
None: begin end;
end {case EngineType}
else if EngineType=ElectricInductionMotor then
begin
Im:=0;Mm:=0;Mw:=0;Fw:=0;Ft:=0;Itot:=0;dizel_fill:=0;EnginePower:=0;
for i:=1 to 20 do
eimv[i]:=0;
(Hamulec as TLSt).SetED(0);RventRot:=0.0;//(Hamulec as TLSt).SetLBP(LocBrakePress);
end;
TractionForce:=Ft
end;
function T_MoverParameters.BrakeForce(Track:TTrackParam):real;
var K,Fb,NBrakeAxles,sm:real;
//const OerlikonForceFactor=1.5;
begin
K:=0;
if NPoweredAxles>0 then
NBrakeAxles:=NPoweredAxles
else
NBrakeAxles:=NAxles;
case LocalBrake of
NoBrake : K:=0;
ManualBrake : K:=MaxBrakeForce*ManualBrakeRatio;
HydraulicBrake : K:=MaxBrakeForce*LocalBrakeRatio;
PneumaticBrake:if Compressor<MaxBrakePress[3] then
K:=MaxBrakeForce*LocalBrakeRatio/2.0
else
K:=0;
end;
if MBrake=true then
begin
K:=MaxBrakeForce*ManualBrakeRatio;
end;
//0.03
u:=((BrakePress*P2FTrans)-BrakeCylSpring)*BrakeCylMult[0]-BrakeSlckAdj;
if (u*BrakeRigEff>Ntotal)then //histereza na nacisku klockow
Ntotal:=u*BrakeRigEff
else
begin
u:=(BrakePress*P2FTrans)*BrakeCylMult[0]-BrakeSlckAdj;
if (u*(2-1*BrakeRigEff)<Ntotal)then //histereza na nacisku klockow
Ntotal:=u*(2-1*BrakeRigEff);
end;
if (NBrakeAxles*NBpA>0) then
begin
if Ntotal>0 then {nie luz}
K:=K+Ntotal; {w kN}
K:=K*BrakeCylNo/(NBrakeAxles*NBpA); {w kN na os}
end;
if (BrakeSystem=Pneumatic)or(BrakeSystem=ElectroPneumatic) then
begin
u:=Hamulec.GetFC(Vel, K);
UnitBrakeForce:=u*K*1000; {sila na jeden klocek w N}
end
else
UnitBrakeForce:=K*1000;
if (NBpA*UnitBrakeForce>TotalMassxg*Adhesive(RunningTrack.friction)/NAxles) and (Abs(V)>0.001) then
{poslizg}
begin
{ Fb:=Adhesive(Track.friction)*Mass*g; }
SlippingWheels:=true;
end;
{ else
begin
{ SlippingWheels:=false;}
// if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then
// Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os}
// else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder hamulcowy/wózek, dlatego potrzebne są oddzielnie liczone osie
Fb:=UnitBrakeForce*NBrakeAxles*Max0R(1,NBpA);
// u:=((BrakePress*P2FTrans)-BrakeCylSpring*BrakeCylMult[BCMFlag]/BrakeCylNo-0.83*BrakeSlckAdj/(BrakeCylNo))*BrakeCylNo;
{ end; }
BrakeForce:=Fb;
end;
function T_MoverParameters.CouplerForce(CouplerN:byte;dt:real):real;
//wyliczenie siły na sprzęgu
var tempdist,newdist,distDelta,CF,dV,absdv,Fmax,BetaAvg:real; CNext:byte;
const MaxDist=405.0; {ustawione + 5 m, bo skanujemy do 400 m }
MinDist=0.5; {ustawione +.5 m, zeby nie rozlaczac przy malych odleglosciach}
MaxCount=1500;
begin
CF:=0;
//distDelta:=0; //Ra: value never used
CNext:=Couplers[CouplerN].ConnectedNr;
{ if Couplers[CouplerN].CForce=0 then {nie bylo uzgadniane wiec policz}
with Couplers[CouplerN] do
begin
CheckCollision:=false;
newdist:=CoupleDist; //odległość od sprzęgu sąsiada
//newdist:=Distance(Loc,Connected^.Loc,Dim,Connected^.Dim);
if (CouplerN=0) then
begin
//ABu: bylo newdist+10*((...
tempdist:=((Connected.dMoveLen*DirPatch(0,ConnectedNr))-dMoveLen);
newdist:=newdist+10.0*tempdist;
//tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
end
else
begin
//ABu: bylo newdist+10*((...
tempdist:=((dMoveLen-(Connected.dMoveLen*DirPatch(1,ConnectedNr))));
newdist:=newdist+10.0*tempdist;
//tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
end;
//blablabla
//ABu: proby znalezienia problemu ze zle odbijajacymi sie skladami
//***if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then
if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (CoupleDist>0) then
begin
CF:=0; {kontrola zderzania sie - OK}
inc(ScanCounter);
if (newdist>MaxDist) or ((ScanCounter>MaxCount)and(newdist>MinDist)) then
//***if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then
begin {zerwij kontrolnie wirtualny sprzeg}
//Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest wirtualny
Connected:=nil;
ScanCounter:=Random(500);
end;
end
else
begin
if CouplingFlag=ctrain_virtual then
begin
BetaAvg:=beta;
Fmax:=(FmaxC+FmaxB)*CouplerTune;
end
else {usrednij bo wspolny sprzeg}
begin
BetaAvg:=(beta+Connected.Couplers[CNext].beta)/2.0;
Fmax:=(FmaxC+FmaxB+Connected.Couplers[CNext].FmaxC+Connected.Couplers[CNext].FmaxB)*CouplerTune/2.0;
end;
dV:=V-DirPatch(CouplerN,CNext)*Connected.V;
absdv:=abs(dV);
if (newdist<-0.001) and (Dist>=-0.001) and (absdv>0.010) then {090503: dzwieki pracy zderzakow}
begin
if SetFlag(SoundFlag,sound_bufferclamp) then
if absdV>0.5 then
SetFlag(SoundFlag,sound_loud);
end
else
if (newdist>0.002) and (Dist<=0.002) and (absdv>0.005) then {090503: dzwieki pracy sprzegu}
begin
if CouplingFlag>0 then
if SetFlag(SoundFlag,sound_couplerstretch) then
if absdV>0.1 then
SetFlag(SoundFlag,sound_loud);
end;
distDelta:=abs(newdist)-abs(Dist); //McZapkie-191103: poprawka na histereze
Dist:=newdist;
if Dist>0 then
begin
if distDelta>0 then
CF:=(-(SpringKC+Connected.Couplers[CNext].SpringKC)*Dist/2.0)*DirF(CouplerN)-Fmax*dV*betaAvg
else
CF:=(-(SpringKC+Connected.Couplers[CNext].SpringKC)*Dist/2.0)*DirF(CouplerN)*betaAvg-Fmax*dV*betaAvg;
{liczenie sily ze sprezystosci sprzegu}
if Dist>(DmaxC+Connected.Couplers[CNext].DmaxC) then {zderzenie}
//***if tempdist>(DmaxC+Connected^.Couplers[CNext].DmaxC) then {zderzenie}
CheckCollision:=true;
end;
if Dist<0 then
begin
if distDelta>0 then
CF:=(-(SpringKB+Connected.Couplers[CNext].SpringKB)*Dist/2.0)*DirF(CouplerN)-Fmax*dV*betaAvg
else
CF:=(-(SpringKB+Connected.Couplers[CNext].SpringKB)*Dist/2.0)*DirF(CouplerN)*betaAvg-Fmax*dV*betaAvg;
{liczenie sily ze sprezystosci zderzaka}
if -Dist>(DmaxB+Connected.Couplers[CNext].DmaxB) then {zderzenie}
//***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie}
begin
CheckCollision:=true;
if (CouplerType=Automatic) and (CouplingFlag=0) then {sprzeganie wagonow z samoczynnymi sprzegami}
//CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic;
CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll; //EN57
end;
end;
end;
if (CouplingFlag<>ctrain_virtual)
then {uzgadnianie prawa Newtona}
Connected.Couplers[1-CouplerN].CForce:=-CF;
end;
CouplerForce:=CF;
end;
procedure T_MoverParameters.CollisionDetect(CouplerN:byte; dt:real);
var CCF,Vprev,VprevC:real; VirtualCoupling:boolean;
begin
CCF:=0;
with Couplers[CouplerN] do
if (Connected<>nil) then
begin
VirtualCoupling:=(CouplingFlag=ctrain_virtual);
Vprev:=V;
VprevC:=Connected.V;
case CouplerN of
0 : CCF:=ComputeCollision(V,Connected.V,TotalMass,Connected.TotalMass,(beta+Connected.Couplers[ConnectedNr].beta)/2.0,VirtualCoupling)/(dt{+0.01}); //yB: ej ej ej, a po
1 : CCF:=ComputeCollision(Connected.V,V,Connected.TotalMass,TotalMass,(beta+Connected.Couplers[ConnectedNr].beta)/2.0,VirtualCoupling)/(dt{+0.01}); //czemu tu jest +0.01??
end;
AccS:=AccS+(V-Vprev)/dt; //korekta przyspieszenia o siły wynikające ze zderzeń?
Connected.AccS:=Connected.AccS+(Connected.V-VprevC)/dt;
if (Dist>0) and (not VirtualCoupling) then
if FuzzyLogic(Abs(CCF),5*(FmaxC+1),p_coupldmg) then
begin {! zerwanie sprzegu}
if SetFlag(DamageFlag,dtrain_coupling) then
EventFlag:=true;
if (Couplers[CouplerN].CouplingFlag and ctrain_pneumatic>0) then
EmergencyBrakeFlag:=true; {hamowanie nagle - zerwanie przewodow hamulcowych}
CouplingFlag:=0;
case CouplerN of {wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone}
0 : Connected.Couplers[1].CouplingFlag:=0;
1 : Connected.Couplers[0].CouplingFlag:=0;
end
end ;
end;
end;
procedure T_MoverParameters.ComputeConstans;
var BearingF,RollF,HideModifier: real;
Curvature: real; //Ra 2014-07: odwrotność promienia
begin
TotalCurrent:=0; //Ra 2014-04: tu zerowanie, aby EZT mogło pobierać prąd innemu członowi
TotalMass:=ComputeMass;
TotalMassxg:=TotalMass*g; {TotalMass*g}
BearingF:=2*(DamageFlag and dtrain_bearing);
HideModifier:=0;//Byte(Couplers[0].CouplingFlag>0)+Byte(Couplers[1].CouplingFlag>0);
with Dim do
begin
if BearingType=0 then
RollF:=0.05 {slizgowe}
else
RollF:=0.015; {toczne}
RollF:=RollF+BearingF/200.0;
(* if NPoweredAxles>0 then
RollF:=RollF*1.5; {dodatkowe lozyska silnikow}*)
if (NPoweredAxles>0) then //drobna optymalka
begin
RollF:=RollF+0.025;
{ if(Ft*Ft<1)then
HideModifier:=HideModifier-3; }
end;
Ff:=TotalMassxg*(BearingF+RollF*V*V/10.0)/1000.0;
{dorobic liczenie temperatury lozyska!}
FrictConst1:=((TotalMassxg*RollF)/10000.0)+(Cx*W*H);
Curvature:=abs(RunningShape.R); //zero oznacza nieskończony promień
if (Curvature>0.0) then Curvature:=1.0/Curvature;
//opór składu na łuku (youBy): +(500*TrackW/R)*TotalMassxg*0.001 do FrictConst2s/d
FrictConst2s:= (TotalMassxg*((500.0*TrackW*Curvature)+ 2.5 - HideModifier + 2*BearingF/dtrain_bearing))*0.001;
FrictConst2d:= (TotalMassxg*((500.0*TrackW*Curvature)+ 2.0 - HideModifier + BearingF/dtrain_bearing))*0.001;
end;
end;
(* poprawione opory ruchu czekajace na lepsze cx w chk
procedure T_MoverParameters.ComputeConstans2(R:real);
var BearingF,RollF,HideModifier: real;
begin
TotalMass:=ComputeMass;
TotalMassxg:=TotalMass*g; {TotalMass*g}
BearingF:=2*(DamageFlag and dtrain_bearing);
HideModifier:=Byte(Couplers[0].CouplingFlag>0)+Byte(Couplers[1].CouplingFlag>0);
with Dim do
begin
if BearingType=0 then
RollF:=10 {slizgowe}
else
RollF:=8; {toczne}
if NPoweredAxles>0 then
RollF:=RollF+2; {dodatkowe lozyska silnikow}
RollF:=RollF+BearingF/100.0; //stala do ustalenia
{dorobic liczenie temperatury lozyska!}
//stale do wzoru CNTK
FrictConst1:=(Cx*W*H)*(6.0-2.5*HideModifier)/100; //dwa czola, kazde ma +2.5 (lokomotywa i wagon) //V2
FrictConst2s:=Totalmass*0.001*0.15; //V1
if(R<TrackW)then //jakakolwiek wartosc dodatnia, np. szerokosc albo rozstaw
FrictConst2d:=RollF*TotalMassxg*0.001+NAxles*150; //V0 na prostej
else
FrictConst2d:=(RollF+500*TrackW/R)*TotalMassxg*0.001+NAxles*150; //V0 na luku
end;
end; *)
function T_MoverParameters.FrictionForce(R:real;TDamage:byte):real;
begin
//ABu 240205: chyba juz ekstremalnie zoptymalizowana funkcja liczaca sily tarcia
if (abs(V)>0.01) then
FrictionForce:=(FrictConst1*V*V)+FrictConst2d
else
FrictionForce:=(FrictConst1*V*V)+FrictConst2s;
end;
(* poprawione opory ruchu czekajace na lepsze cx w chk
function T_MoverParameters.FrictionForce2(R:real;TDamage:byte):real;
begin
//ABu 240205: chyba juz ekstremalnie zoptymalizowana funkcja liczaca sily tarcia
FrictionForce2:=(FrictConst1*Vel*Vel)+(FrictConst2s*Vel)+FrictConst2d;
end; *)
function T_MoverParameters.AddPulseForce(Multipler:integer): boolean; {dla drezyny}
begin
if (EngineType=WheelsDriven) and (EnginePowerSource.SourceType=InternalSource) and (EnginePowerSource.PowerType=BioPower) then
begin
ActiveDir:=CabNo;
DirAbsolute:=ActiveDir*CabNo;
if Vel>0 then
PulseForce:=Min0R(1000.0*Power/(Abs(V)+0.1),Ftmax)
else PulseForce:=Ftmax;
if PulseForceCount>1000.0 then
PulseForce:=0
else
PulseForce:=PulseForce*Multipler;
PulseForceCount:=PulseForceCount+Abs(Multipler);
AddPulseForce:=(PulseForce>0);
end
else AddPulseForce:=false;
end;
function T_MoverParameters.LoadingDone(LSpeed:real; LoadInit:string): boolean;
//test zakończenia załadunku/rozładunku
var LoadChange:longint;
begin
ClearPendingExceptions; //zabezpieczenie dla Trunc()
//LoadingDone:=false; //nie zakończone
if (LoadInit<>'') then //nazwa ładunku niepusta
begin
if Load>MaxLoad then
LoadChange:=Abs(Trunc(LSpeed*LastLoadChangeTime/2.0)) //przeładowanie?
else
LoadChange:=Abs(Trunc(LSpeed*LastLoadChangeTime));
if LSpeed<0 then //gdy rozładunek
begin
LoadStatus:=2; //trwa rozładunek (włączenie naliczania czasu)
if LoadChange<>0 then //jeśli coś przeładowano
begin
LastLoadChangeTime:=0; //naliczony czas został zużyty
Load:=Load-LoadChange; //zmniejszenie ilości ładunku
CommandIn.Value1:=CommandIn.Value1-LoadChange; //zmniejszenie ilości do rozładowania
if Load<0 then
Load:=0; //ładunek nie może być ujemny
if (Load=0) or (CommandIn.Value1<0) then //pusto lub rozładowano żądaną ilość
LoadStatus:=4; //skończony rozładunek
if Load=0 then LoadType:=''; //jak nic nie ma, to nie ma też nazwy
end
end
else if LSpeed>0 then //gdy załadunek
begin
LoadStatus:=1; //trwa załadunek (włączenie naliczania czasu)
if LoadChange<>0 then //jeśli coś przeładowano
begin
LastLoadChangeTime:=0; //naliczony czas został zużyty
LoadType:=LoadInit; //nazwa
Load:=Load+LoadChange; //zwiększenie ładunku
CommandIn.Value1:=CommandIn.Value1-LoadChange;
if (Load>=MaxLoad*(1+OverLoadFactor)) or (CommandIn.Value1<0) then
LoadStatus:=4; //skończony załadunek
end
end
else LoadStatus:=4; //zerowa prędkość zmiany, to koniec
end;
LoadingDone:=(LoadStatus>=4);
end;
{-------------------------------------------------------------------}
{WAZNA FUNKCJA - oblicza siłę wypadkową}
procedure T_MoverParameters.ComputeTotalForce(dt: real; dt1: real; FullVer: boolean);
var b: byte;
begin
if PhysicActivation then
begin
{ EventFlag:=false; {jesli cos sie zlego wydarzy to ustawiane na true}
{ SoundFlag:=0; {jesli ma byc jakis dzwiek to zapalany jet odpowiedni bit}
{to powinno byc zerowane na zewnatrz}
//juz zoptymalizowane:
FStand:=FrictionForce(RunningShape.R,RunningTrack.DamageFlag); //siła oporów ruchu
Vel:=Abs(V)*3.6; //prędkość w km/h
nrot:=V2n(); //przeliczenie prędkości liniowej na obrotową
if TestFlag(BrakeMethod,bp_MHS) and (PipePress<3.0) and (Vel>45) and TestFlag(BrakeDelayFlag,bdelay_M) then //ustawione na sztywno na 3 bar
FStand:=Fstand+{(RunningTrack.friction)*}TrackBrakeForce; //doliczenie hamowania hamulcem szynowym
//w charakterystykach jest wartość siły hamowania zamiast nacisku
// if(FullVer=true) then
// begin //ABu: to dla optymalizacji, bo chyba te rzeczy wystarczy sprawdzac 1 raz na klatke?
LastSwitchingTime:=LastSwitchingTime+dt1;
if EngineType=ElectricSeriesMotor then
LastRelayTime:=LastRelayTime+dt1;
// end;
if Mains and {(Abs(CabNo)<2) and} (EngineType=ElectricSeriesMotor) then //potem ulepszyc! pantogtrafy!
begin //Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik
if CabNo=0 then
Voltage:=RunningTraction.TractionVoltage*ActiveDir
else
Voltage:=RunningTraction.TractionVoltage*DirAbsolute; //ActiveDir*CabNo;
end {bo nie dzialalo}
else if (EngineType=ElectricInductionMotor) or (((Couplers[0].CouplingFlag and ctrain_power)=ctrain_power) or ((Couplers[1].CouplingFlag and ctrain_power)=ctrain_power)) then //potem ulepszyc! pantogtrafy!
Voltage:=Max0R(Max0R(RunningTraction.TractionVoltage,HVCouplers[0][1]),HVCouplers[1][1])
else
Voltage:=0;
//end;
if Power>0 then
FTrain:=TractionForce(dt)
else
FTrain:=0;
Fb:=BrakeForce(RunningTrack);
if Max0R(Abs(FTrain),Fb)>TotalMassxg*Adhesive(RunningTrack.friction) then {poslizg}
SlippingWheels:=true;
if SlippingWheels then
begin
{ TrainForce:=TrainForce-Fb; }
nrot:=ComputeRotatingWheel((FTrain-Fb*Sign(V)-Fstand)/NAxles-Sign(nrot*Pi*WheelDiameter-V)*Adhesive(RunningTrack.friction)*TotalMass,dt,nrot);
FTrain:=sign(FTrain)*TotalMassxg*Adhesive(RunningTrack.friction);
Fb:=Min0R(Fb,TotalMassxg*Adhesive(RunningTrack.friction));
end;
{ else SlippingWheels:=false; }
{ FStand:=0; }
for b:=0 to 1 do
if (Couplers[b].Connected<>nil) {and (Couplers[b].CouplerType<>Bare) and (Couplers[b].CouplerType<>Articulated)} then
begin //doliczenie sił z innych pojazdów
Couplers[b].CForce:=CouplerForce(b,dt);
FTrain:=FTrain+Couplers[b].CForce
end
else Couplers[b].CForce:=0;
//FStand:=Fb+FrictionForce(RunningShape.R,RunningTrack.DamageFlag);
FStand:=Fb+FStand;
FTrain:=FTrain+TotalMassxg*RunningShape.dHtrack; //doliczenie składowej stycznej grawitacji
{!niejawne przypisanie zmiennej!}
FTotal:=FTrain-Sign(V)*FStand;
end;
{McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty}
{ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam
zakomentowalem PhysicActivationFlag bo cos nie dzialalo i fizyka byla
liczona zawsze.}
//if PhysicActivationFlag then
// begin
if (CabNo=0) and (Vel<0.0001) and (abs(AccS)<0.0001) and (TrainType<>dt_EZT) then
begin
if not PhysicActivation then
begin
if Couplers[0].Connected<>nil then
if (Couplers[0].Connected.Vel>0.0001) or (Abs(Couplers[0].Connected.AccS)>0.0001) then
Physic_ReActivation;
if Couplers[1].Connected<>nil then
if (Couplers[1].Connected.Vel>0.0001) or (Abs(Couplers[1].Connected.AccS)>0.0001) then
Physic_ReActivation;
end;
if LastSwitchingTime>5 then //10+Random(100) then
PhysicActivation:=false; {zeby nie brac pod uwage braku V po uruchomieniu programu}
end
else
PhysicActivation:=true;
// end;
end;
{------------------------------------------------------------}
{OBLICZENIE PRZEMIESZCZENIA}
function T_MoverParameters.ComputeMovement(dt:real; dt1:real; Shape:TTrackShape; var Track:TTrackParam; var ElectricTraction:TTractionParam; NewLoc:TLocation; var NewRot:TRotation):real;
var b:byte;
Vprev,AccSprev:real;
// Iheat:real; prad ogrzewania
hvc: real;
const Vepsilon=1e-5; Aepsilon=1e-3; //ASBSpeed=0.8;
begin
TotalCurrent:=0;
hvc:=Max0R(Max0R(PantFrontVolt,PantRearVolt),ElectricTraction.TractionVoltage*0.9);
for b:=0 to 1 do //przekazywanie napiec
if ((Couplers[b].CouplingFlag and ctrain_power) = ctrain_power)or(((Couplers[b].CouplingFlag and ctrain_heating) = ctrain_heating)and(Heating)) then
begin
HVCouplers[1-b][1]:=Max0R(Abs(hvc),Couplers[b].Connected.HVCouplers[Couplers[b].ConnectedNr][1]-HVCouplers[b][0]*0.02);
end
else
HVCouplers[1-b][1]:=Abs(hvc)-HVCouplers[b][0]*0.02;//Max0R(Abs(Voltage),0);
// end;
hvc:=HVCouplers[0][1]+HVCouplers[1][1];
if (Abs(PantFrontVolt)+Abs(PantRearVolt)<1) and (hvc>1)then //bez napiecia, ale jest cos na sprzegach:
begin
for b:=0 to 1 do //przekazywanie pradow
if ((Couplers[b].CouplingFlag and ctrain_power) = ctrain_power)or(((Couplers[b].CouplingFlag and ctrain_heating) = ctrain_heating)and(Heating)) then //jesli spiety
begin
HVCouplers[b][0]:=Couplers[b].Connected.HVCouplers[1-Couplers[b].ConnectedNr][0]+Itot*HVCouplers[b][1]/hvc; //obciążenie rozkladane stosownie do napiec
end
else //pierwszy pojazd
begin
HVCouplers[b][0]:=Itot*HVCouplers[b][1]/hvc;
end;
end
else
begin
if ((Couplers[0].CouplingFlag and ctrain_power) = ctrain_power)or(((Couplers[0].CouplingFlag and ctrain_heating) = ctrain_heating)and(Heating)) then
TotalCurrent:=TotalCurrent+Couplers[0].Connected.HVCouplers[1-Couplers[0].ConnectedNr][0];
if ((Couplers[1].CouplingFlag and ctrain_power) = ctrain_power)or(((Couplers[1].CouplingFlag and ctrain_heating) = ctrain_heating)and(Heating)) then
TotalCurrent:=TotalCurrent+Couplers[1].Connected.HVCouplers[1-Couplers[1].ConnectedNr][0];
HVCouplers[0][0]:=0;
HVCouplers[1][0]:=0;
end;
ClearPendingExceptions;
if not TestFlag(DamageFlag,dtrain_out) then
begin //Ra: to przepisywanie tu jest bez sensu
RunningShape:=Shape;
RunningTrack:=Track;
RunningTraction:=ElectricTraction;
with ElectricTraction do
if not DynamicBrakeFlag then
RunningTraction.TractionVoltage:=TractionVoltage{-Abs(TractionResistivity*(Itot+HVCouplers[0][0]+HVCouplers[1][0]))}
else
RunningTraction.TractionVoltage:=TractionVoltage-Abs(TractionResistivity*Itot*0); //zasadniczo ED oporowe nie zmienia napięcia w sieci
end;
if CategoryFlag=4 then
OffsetTrackV:=TotalMass/(Dim.L*Dim.W*1000.0)
else
if TestFlag(CategoryFlag,1) and TestFlag(RunningTrack.CategoryFlag,1) then
if TestFlag(DamageFlag,dtrain_out) then
begin
OffsetTrackV:=-0.2; OffsetTrackH:=sign(RunningShape.R)*0.2;
end;
Loc:=NewLoc;
Rot:=NewRot;
with NewRot do begin Rx:=0; Ry:=0; Rz:=0; end;
if dL=0 then {oblicz przesuniecie}
begin
Vprev:=V;
AccSprev:=AccS;
{dt:=ActualTime-LastUpdatedTime;} {przyrost czasu}
{przyspieszenie styczne}
AccS:=(FTotal/TotalMass+AccSprev)/2.0; //prawo Newtona ale z wygladzaniem (średnia z poprzednim)
if TestFlag(DamageFlag,dtrain_out) then
AccS:=-Sign(V)*g*Random;
{przyspieszenie normalne}
if Abs(Shape.R)>0.01 then
AccN:=SQR(V)/Shape.R+g*Shape.dHrail/TrackW
else AccN:=g*Shape.dHrail/TrackW;
{szarpanie}
if FuzzyLogic((10+Track.DamageFlag)*Mass*Vel/Vmax,500000,p_accn) then {Ra: czemu tu masa bez ładunku?}
AccV:=sqrt((1+Track.DamageFlag)*random(Trunc(50*Mass/1000000.0))*Vel/(Vmax*(10+(Track.QualityFlag and 31))))
else
AccV:=AccV/2.0;
if AccV>1.0 then
AccN:=AccN+(7-random(5))*(100.0+Track.DamageFlag/2.0)*AccV/2000.0;
{wykolejanie na luku oraz z braku szyn}
if TestFlag(CategoryFlag,1) then
begin
if FuzzyLogic((AccN/g)*(1+0.1*(Track.DamageFlag and dtrack_freerail)),TrackW/Dim.H,1)
or TestFlag(Track.DamageFlag,dtrack_norail) then
if SetFlag(DamageFlag,dtrain_out) then
begin
EventFlag:=true;
MainS:=false;
RunningShape.R:=0;
if (TestFlag(Track.DamageFlag,dtrack_norail)) then
DerailReason:=1 //Ra: powód wykolejenia: brak szyn
else
DerailReason:=2; //Ra: powód wykolejenia: przewrócony na łuku
end;
{wykolejanie na poszerzeniu toru}
if FuzzyLogic(Abs(Track.Width-TrackW),TrackW/10.0,1) then
if SetFlag(DamageFlag,dtrain_out) then
begin
EventFlag:=true;
MainS:=false;
RunningShape.R:=0;
DerailReason:=3; //Ra: powód wykolejenia: za szeroki tor
end;
end;
{wykolejanie wkutek niezgodnosci kategorii toru i pojazdu}
if not TestFlag(RunningTrack.CategoryFlag,CategoryFlag) then
if SetFlag(DamageFlag,dtrain_out) then
begin
EventFlag:=true;
MainS:=false;
DerailReason:=4; //Ra: powód wykolejenia: nieodpowiednia trajektoria
end;
V:=V+(3*AccS-AccSprev)*dt/2.0; {przyrost predkosci}
if TestFlag(DamageFlag,dtrain_out) then
if Vel<1 then
begin
V:=0;
AccS:=0;
end;
if (V*Vprev<=0) and (Abs(FStand)>Abs(FTrain)) then {tlumienie predkosci przy hamowaniu}
begin {zahamowany}
V:=0;
//AccS:=0; //Ra 2014-03: ale siła grawitacji działa, więc nie może być zerowe
end;
(*
else
if (Abs(V)<Vepsilon) and (Abs(AccS)<Aepsilon) then
begin
V:=0;
AccS:=0;
end;
*)
{ dL:=(V+AccS*dt/2)*dt; {przyrost dlugosci czyli przesuniecie}
dL:=(3*V-Vprev)*dt/2.0; {metoda Adamsa-Bashfortha}
{ale jesli jest kolizja (zas. zach. pedu) to...}
for b:=0 to 1 do
if Couplers[b].CheckCollision then
CollisionDetect(b,dt); {zmienia niejawnie AccS, V !!!}
(*
for b:=0 to 1 do
begin
Couplers[b].CForce:=0; {!}
SendAVL(AccS,AccN,V,dL,0);
end;
*)
end; {liczone dL, predkosc i przyspieszenie}
{Ra: reszta przeniesiona do Mover.cpp}
end; {ComputeMovement}
{blablabla}
{OBLICZENIE PRZEMIESZCZENIA}
function T_MoverParameters.FastComputeMovement(dt:real; Shape:TTrackShape; var Track:TTrackParam;NewLoc:TLocation; var NewRot:TRotation):real; //;var ElectricTraction:TTractionParam; NewLoc:TLocation; var NewRot:TRotation):real;
var b:byte;
Vprev,AccSprev:real;
const Vepsilon=1e-5; Aepsilon=1e-3; //ASBSpeed=0.8;
begin
ClearPendingExceptions;
Loc:=NewLoc;
Rot:=NewRot;
with NewRot do begin Rx:=0; Ry:=0; Rz:=0; end;
if dL=0 then {oblicz przesuniecie}
begin
Vprev:=V;
AccSprev:=AccS;
{dt:=ActualTime-LastUpdatedTime;} {przyrost czasu}
{przyspieszenie styczne}
AccS:=(FTotal/TotalMass+AccSprev)/2.0; //prawo Newtona ale z wygladzaniem (średnia z poprzednim)
if TestFlag(DamageFlag,dtrain_out) then
AccS:=-Sign(V)*g*Random;
{przyspieszenie normalne}
// if Abs(Shape.R)>0.01 then
// AccN:=SQR(V)/Shape.R+g*Shape.dHrail/TrackW
// else AccN:=g*Shape.dHrail/TrackW;
{szarpanie}
if FuzzyLogic((10+Track.DamageFlag)*Mass*Vel/Vmax,500000,p_accn) then
AccV:=sqrt((1+Track.DamageFlag)*random(Trunc(50*Mass/1000000.0))*Vel/(Vmax*(10+(Track.QualityFlag and 31))))
else
AccV:=AccV/2.0;
if AccV>1.0 then
AccN:=AccN+(7-random(5))*(100.0+Track.DamageFlag/2.0)*AccV/2000.0;
// {wykolejanie na luku oraz z braku szyn}
// if TestFlag(CategoryFlag,1) then
// begin
// if FuzzyLogic((AccN/g)*(1+0.1*(Track.DamageFlag and dtrack_freerail)),TrackW/Dim.H,1)
// or TestFlag(Track.DamageFlag,dtrack_norail) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// RunningShape.R:=0;
// end;
// {wykolejanie na poszerzeniu toru}
// if FuzzyLogic(Abs(Track.Width-TrackW),TrackW/10,1) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// RunningShape.R:=0;
// end;
// end;
// {wykolejanie wkutek niezgodnosci kategorii toru i pojazdu}
// if not TestFlag(RunningTrack.CategoryFlag,CategoryFlag) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// end;
V:=V+(3.0*AccS-AccSprev)*dt/2.0; {przyrost predkosci}
if TestFlag(DamageFlag,dtrain_out) then
if Vel<1 then
begin
V:=0;
AccS:=0; //Ra 2014-03: ale siła grawitacji działa, więc nie może być zerowe
end;
if (V*Vprev<=0) and (Abs(FStand)>Abs(FTrain)) then {tlumienie predkosci przy hamowaniu}
begin {zahamowany}
V:=0;
AccS:=0;
end;
dL:=(3*V-Vprev)*dt/2.0; {metoda Adamsa-Bashfortha}
{ale jesli jest kolizja (zas. zach. pedu) to...}
for b:=0 to 1 do
if Couplers[b].CheckCollision then
CollisionDetect(b,dt); {zmienia niejawnie AccS, V !!!}
end; {liczone dL, predkosc i przyspieszenie}
{Ra: reszta przeniesiona do Mover.cpp}
end; {FastComputeMovement}
function T_MoverParameters.ComputeMass: real;
var M:real;
begin
if Load>0 then
begin //zakładamy, że ładunek jest pisany małymi literami
if LoadQuantity='tonns' then
M:=Load*1000
else if (LoadType='passengers') then
M:=Load*80
else if LoadType='luggage' then
M:=Load*100
else if LoadType='cars' then
M:=Load*800
else if LoadType='containers' then
M:=Load*8000
else if LoadType='transformers' then
M:=Load*50000
else
M:=Load*1000;
end
else
M:=0;
{Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają}
ComputeMass:=Mass+M+Mred;
end;
{-----------------------------------------------------------------}
{funkcje wejscia/wyjscia}
{przekazywanie komend i parametrow}
function T_MoverParameters.SetInternalCommand(NewCommand:string; NewValue1,NewValue2:real):boolean;
begin
if (CommandIn.Command=Newcommand) and (commandIn.Value1=NewValue1) and (commandIn.Value2=NewValue2) then
SetInternalCommand:=false
else
with CommandIn do
begin
Command:=NewCommand;
Value1:=NewValue1;
Value2:=NewValue2;
SetInternalCommand:=true;
LastLoadChangeTime:=0; //zerowanie czasu (roz)ładowania
end;
end;
function T_MoverParameters.GetExternalCommand(var Command:string):real;
begin
Command:=CommandOut;
GetExternalCommand:=ValueOut;
end;
function T_MoverParameters.DoorBlockedFlag:Boolean;
begin
//if (DoorBlocked=true) and (Vel<5.0) then
DoorBlockedFlag:=false;
if (DoorBlocked=true) and (Vel>=5.0) then
DoorBlockedFlag:=true
end;
function T_MoverParameters.RunCommand(command:string; CValue1,CValue2:real):boolean;
//wysłanie komendy otrzymanej z kierunku CValue2 (względem sprzęgów: 1=przod,-1=tył)
// Ra: Jest tu problem z rekurencją. Trzeba by oddzielić wykonywanie komend od mechanizmu
// ich propagacji w składzie. Osobnym problemem może być propagacja tylko w jedną stronę.
// Jeśli jakiś człon jest wstawiony odwrotnie, to również odwrotnie musi wykonywać
// komendy związane z kierunkami (PantFront, PantRear, DoorLeft, DoorRight).
// Komenda musi być zdefiniowana tutaj, a jeśli się wywołuje funkcję, to ona nie może
// sama przesyłać do kolejnych pojazdów. Należy też się zastanowić, czy dla uzyskania
// jakiejś zmiany (np. IncMainCtrl) lepiej wywołać funkcję, czy od razu wysłać komendę.
var OK:boolean; testload:string;
Begin
{$B+} {cholernie mi sie nie podoba ta dyrektywa!!!}
OK:=false;
ClearPendingExceptions();
{test komend sterowania ukrotnionego}
if command='MainCtrl' then
begin
if MainCtrlPosNo>=Trunc(CValue1) then
MainCtrlPos:=Trunc(CValue1);
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='ScndCtrl' then
begin
if (EngineType=ElectricInductionMotor) then
if (ScndCtrlPos=0) and (Trunc(CValue1)>0) then
if (Vmax<250) then
ScndCtrlActualPos:=Round(Vel+0.5)
else
ScndCtrlActualPos:=Round(Vel/2+0.5)
else if (Trunc(CValue1)=0) then
ScndCtrlActualPos:=0;
if ScndCtrlPosNo>=Trunc(CValue1) then
ScndCtrlPos:=Trunc(CValue1);
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
(* else if command='BrakeCtrl' then
begin
if BrakeCtrlPosNo>=Trunc(CValue1) then
begin
BrakeCtrlPos:=Trunc(CValue1);
OK:=SendCtrlToNext(command,CValue1,CValue2);
end;
end *)
else if command='Brake' then //youBy - jak sie EP hamuje, to trza sygnal wyslac...
begin
Hamulec.SetEPS(CValue1);
//fBrakeCtrlPos:=BrakeCtrlPos; //to powinnno być w jednym miejscu, aktualnie w C++!!!
BrakePressureActual:=BrakePressureTable[BrakeCtrlPos];
OK:=SendCtrlToNext(command,CValue1,CValue2);
end //youby - odluzniacz hamulcow, przyda sie
else if command='BrakeReleaser' then
begin
OK:=BrakeReleaser(Round(CValue1)); //samo się przesyła dalej
//OK:=SendCtrlToNext(command,CValue1,CValue2); //to robiło kaskadę 2^n
end
else if command='MainSwitch' then
begin
if CValue1=1 then
begin
Mains:=true;
if (EngineType=DieselEngine) and Mains then
dizel_enginestart:=true;
end
else Mains:=false;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='Direction' then
begin
ActiveDir:=Trunc(CValue1);
DirAbsolute:=ActiveDir*CabNo;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='CabActivisation' then
begin
// OK:=Power>0.01;
case Trunc(CValue1*CValue2) of //CValue2 ma zmieniany znak przy niezgodności sprzęgów
1 : CabNo:= 1;
-1 : CabNo:=-1;
else CabNo:=0; //gdy CValue1==0
end;
DirAbsolute:=ActiveDir*CabNo;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='AutoRelaySwitch' then
begin
if (CValue1=1) and (AutoRelayType=2) then AutoRelayFlag:=true
else AutoRelayFlag:=false;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='FuseSwitch' then
begin
if ((EngineType=ElectricSeriesMotor)or(EngineType=DieselElectric)) and FuseFlag and (CValue1=1) and
(MainCtrlActualPos=0) and (ScndCtrlActualPos=0) and Mains then
{ if (EngineType=ElectricSeriesMotor) and (CValue1=1) and
(MainCtrlActualPos=0) and (ScndCtrlActualPos=0) and Mains then}
FuseFlag:=false; {wlaczenie ponowne obwodu}
// if ((EngineType=ElectricSeriesMotor)or(EngineType=DieselElectric)) and not FuseFlag and (CValue1=0) and Mains then
// FuseFlag:=true;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='ConverterSwitch' then {NBMX}
begin
if (CValue1=1) then ConverterAllow:=true
else if (CValue1=0) then ConverterAllow:=false;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='BatterySwitch' then {NBMX}
begin
if (CValue1=1) then Battery:=true
else if (CValue1=0) then Battery:=false;
if (Battery) and (ActiveCab<>0) {or (TrainType=dt_EZT)} then
SecuritySystem.Status:=SecuritySystem.Status or s_waiting //aktywacja czuwaka
else
SecuritySystem.Status:=0; //wyłączenie czuwaka
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
// else if command='EpFuseSwitch' then {NBMX}
// begin
// if (CValue1=1) then EpFuse:=true
// else if (CValue1=0) then EpFuse:=false;
// OK:=SendCtrlToNext(command,CValue1,CValue2);
// end
else if command='CompressorSwitch' then {NBMX}
begin
if (CValue1=1) then CompressorAllow:=true
else if (CValue1=0) then CompressorAllow:=false;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='DoorOpen' then {NBMX}
begin //Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if (CValue2>0) then
begin //normalne ustawienie pojazdu
if (CValue1=1) OR (CValue1=3) then
DoorLeftOpened:=true;
if (CValue1=2) OR (CValue1=3) then
DoorRightOpened:=true;
end
else
begin //odwrotne ustawienie pojazdu
if (CValue1=2) OR (CValue1=3) then
DoorLeftOpened:=true;
if (CValue1=1) OR (CValue1=3) then
DoorRightOpened:=true;
end;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='DoorClose' then {NBMX}
begin //Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if (CValue2>0) then
begin //normalne ustawienie pojazdu
if (CValue1=1) OR (CValue1=3) then
DoorLeftOpened:=false;
if (CValue1=2) OR (CValue1=3) then
DoorRightOpened:=false;
end
else
begin //odwrotne ustawienie pojazdu
if (CValue1=2) OR (CValue1=3) then
DoorLeftOpened:=false;
if (CValue1=1) OR (CValue1=3) then
DoorRightOpened:=false;
end;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='PantFront' then {Winger 160204}
begin //Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
//Czemu EZT ma być traktowane inaczej? Ukrotnienie ma, a człon może być odwrócony
if (TrainType=dt_EZT) then
begin //'ezt'
if (CValue1=1) then
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else if (CValue1=0) then
begin
PantFrontUp:=false;
PantFrontStart:=1;
end;
end
else
begin //nie 'ezt' - odwrotne ustawienie pantografów: ^-.-^ zamiast ^-.^-
if (CValue1=1) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else
begin
PantRearUp:=true;
PantRearStart:=0;
end
else if (CValue1=0) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantFrontUp:=false;
PantFrontStart:=1;
end
else
begin
PantRearUp:=false;
PantRearStart:=1;
end;
end;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='PantRear' then {Winger 160204, ABu 310105 i 030305}
begin //Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if (TrainType=dt_EZT) then
begin {'ezt'}
if (CValue1=1) then
begin
PantRearUp:=true;
PantRearStart:=0;
end
else if (CValue1=0) then
begin
PantRearUp:=false;
PantRearStart:=1;
end;
end
else
begin {nie 'ezt'}
if (CValue1=1) then
{if ostatni polaczony sprz. sterowania}
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantRearUp:=true;
PantRearStart:=0;
end
else
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else if (CValue1=0) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantRearUp:=false;
PantRearStart:=1;
end
else
begin
PantFrontUp:=false;
PantFrontStart:=1;
end;
end;
OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='MaxCurrentSwitch' then
begin
OK:=MaxCurrentSwitch(CValue1=1);
end
else if command='MinCurrentSwitch' then
begin
OK:=MinCurrentSwitch(CValue1=1);
end
{test komend oddzialywujacych na tabor}
else if command='SetDamage' then
begin
if CValue2=1 then OK:=SetFlag(DamageFlag,Trunc(CValue1));
if CValue2=-1 then OK:=SetFlag(DamageFlag,-Trunc(CValue1));
end
else if command='Emergency_brake' then
begin
if EmergencyBrakeSwitch(Trunc(CValue1)=1) then //YB: czy to jest potrzebne?
OK:=true
else OK:=false;
end
else if command='BrakeDelay' then
begin
BrakeDelayFlag:=Trunc(CValue1);
OK:=true;
end
else if command='SandDoseOn' then
begin
if SandDoseOn then
OK:=true
else OK:=false;
end
else if command='CabSignal' then {SHP,Indusi}
begin //Ra: to powinno działać tylko w członie obsadzonym
if {(TrainType=dt_EZT)or} (ActiveCab<>0) and (Battery) and TestFlag(SecuritySystem.SystemType,2) then //jeśli kabina jest obsadzona (silnikowy w EZT?)
with SecuritySystem do
begin
VelocityAllowed:=Trunc(CValue1);
NextVelocityAllowed:=Trunc(CValue2);
SystemSoundSHPTimer:=0; //hunter-091012
SetFlag(Status,s_active);
end;
//else OK:=false;
OK:=true; //true, gdy można usunąć komendę
end
{naladunek/rozladunek}
else if Pos('Load=',command)=1 then
begin
OK:=false; //będzie powtarzane aż się załaduje
if (Vel=0) and (MaxLoad>0) and (Load<MaxLoad*(1+OverLoadFactor)) then //czy można ładowac?
if Distance(Loc,CommandIn.Location,Dim,Dim)<10 then //ten peron/rampa
begin
testload:=LowerCase(DUE(command));
if Pos(testload,LoadAccepted)>0 then //nazwa jest obecna w CHK
OK:=LoadingDone(Min0R(CValue2,LoadSpeed),testload); //zmienia LoadStatus
end;
//if OK then LoadStatus:=0; //nie udalo sie w ogole albo juz skonczone
end
else if Pos('UnLoad=',command)=1 then
begin
OK:=false; //będzie powtarzane aż się rozładuje
if (Vel=0) and (Load>0) then //czy jest co rozladowac?
if Distance(Loc,CommandIn.Location,Dim,Dim)<10 then //ten peron
begin
testload:=DUE(command); //zgodność nazwy ładunku z CHK
if LoadType=testload then {mozna to rozladowac}
OK:=LoadingDone(-Min0R(CValue2,LoadSpeed),testload);
end;
//if OK then LoadStatus:=0;
end;
RunCommand:=OK; //dla true komenda będzie usunięta, dla false wykonana ponownie
{$B-}
End;
function T_MoverParameters.RunInternalCommand:boolean;
var OK:boolean;
begin
if CommandIn.Command<>'' then
begin
OK:=RunCommand(CommandIn.Command,CommandIn.Value1,CommandIn.Value2);
if OK then
with CommandIn do
begin
Command:=''; {kasowanie bo rozkaz wykonany}
Value1:=0;
Value2:=0;
Location.x:=0; Location.y:=0; Location.z:=0;
if not PhysicActivation then
Physic_ReActivation;
end;
end
else
OK:=false;
RunInternalCommand:=OK;
end;
procedure T_MoverParameters.PutCommand(NewCommand:string; NewValue1,NewValue2:real; NewLocation:TLocation);
begin
CommandLast:=NewCommand; //zapamiętanie komendy
with CommandIn do
begin
Command:=NewCommand;
Value1:=NewValue1;
Value2:=NewValue2;
Location:=NewLocation;
end; {czy uruchomic tu RunInternalCommand? nie wiem}
end;
{dla samochodow - kolej nie wężykuje}
function T_MoverParameters.ChangeOffsetH(DeltaOffset:real):boolean;
begin
if TestFlag(CategoryFlag,2) and TestFlag(RunningTrack.CategoryFlag,2) then
begin
OffsetTrackH:=OffsetTrackH+DeltaOffset;
// if abs(OffsetTrackH)>(RunningTrack.Width/1.95-TrackW/2.0) then
if abs(OffsetTrackH)>(0.5*(RunningTrack.Width-Dim.W)-0.05) then //Ra: może pół pojazdu od brzegu?
ChangeOffsetH:=false {kola na granicy drogi}
else
ChangeOffsetH:=true;
end
else ChangeOffsetH:=false;
end;
{inicjalizacja}
constructor T_MoverParameters.Init(//LocInitial:TLocation; RotInitial:TRotation;
VelInitial:real; TypeNameInit, NameInit: string; LoadInitial:longint; LoadTypeInitial: string; Cab:integer);
{predkosc pocz. w km/h, ilosc ladunku, typ ladunku, numer kabiny}
var b,k:integer;
begin
{inicjalizacja stalych}
dMoveLen:=0;
CategoryFlag:=1;
EngineType:=None;
for b:=0 to ResArraySize do
begin
RList[b].Relay:=0;
RList[b].R:=0;
RList[b].Bn:=0;
RList[b].Mn:=0;
RList[b].AutoSwitch:=false;
end;
WheelDiameter:=1.0;
BrakeCtrlPosNo:=0;
LightsPosNo:=0;
LightsDefPos:=1;
for k:=-1 to MainBrakeMaxPos do
with BrakePressureTable[k] do
begin
PipePressureVal:=0;
BrakePressureVal:=0;
FlowSpeedVal:=0;
end;
with BrakePressureTable[-2] do {pozycja odciecia}
begin
PipePressureVal:=-1;
BrakePressureVal:=-1;
FlowSpeedVal:=0;
end;
Transmision.Ratio:=1;
NBpA:=0;
DynamicBrakeType:=0;
ASBType:=0;
AutoRelayType:=0;
for b:=0 to 1 do //Ra: kto tu zrobił "for b:=1 to 2 do" ???
with Couplers[b] do
begin
CouplerType:=NoCoupler;
SpringkB:=1; SpringkC:=1;
DmaxB:=0.1; FmaxB:=1000;
DmaxC:=0.1; FmaxC:=1000;
end;
Power:=0;
MaxLoad:=0; LoadAccepted:='';
LoadSpeed:=0; UnLoadSpeed:=0;
HeatingPower:=0; LightPower:=0;
with HeatingPowerSource do
begin
MaxVoltage:=0; MaxCurrent:=0; IntR:=0.001;
SourceType:=NotDefined; PowerType:=NoPower; RPowerCable.PowerTrans:=NoPower;
end;
with AlterHeatPowerSource do
begin
MaxVoltage:=0; MaxCurrent:=0; IntR:=0.001;
SourceType:=NotDefined; PowerType:=NoPower; RPowerCable.PowerTrans:=NoPower;
end;
with LightPowerSource do
begin
MaxVoltage:=0; MaxCurrent:=0; IntR:=0.001;
SourceType:=NotDefined; PowerType:=NoPower; RPowerCable.PowerTrans:=NoPower;
end;
with AlterLightPowerSource do
begin
MaxVoltage:=0; MaxCurrent:=0; IntR:=0.001;
SourceType:=NotDefined; PowerType:=NoPower; RPowerCable.PowerTrans:=NoPower;
end;
TypeName:=TypeNameInit;
HighPipePress:=0;
LowPipePress:=0;
DeltaPipePress:=0;
BrakeCylNo:=0;
BrakeCylRadius:=0;
BrakeCylDist:=0;
for b:=0 to 3 do
BrakeCylMult[b]:=0;
VeselVolume:=0;
BrakeVolume:=0;
RapidMult:=1;
dizel_Mmax:=1; dizel_nMmax:=1; dizel_Mnmax:=2; dizel_nmax:=2; dizel_nominalfill:=0;
dizel_Mstand:=0;
dizel_nmax_cutoff:=0;
dizel_nmin:=0;
dizel_minVelfullengage:=0;
dizel_AIM:=1;
dizel_engageDia:=0.5; dizel_engageMaxForce:=6000; dizel_engagefriction:=0.5;
DoorOpenCtrl:=0; DoorCloseCtrl:=0;
DoorStayOpen:=0;
DoorClosureWarning:=false;
DoorOpenSpeed:=1; DoorCloseSpeed:=1;
DoorMaxShiftL:=0.5; DoorMaxShiftR:=0.5;
DoorOpenMethod:=2;
DepartureSignal:=false;
InsideConsist:=false;
CompressorPower:=1;
SmallCompressorPower:=0;
for b:=0 to 25 do
eimc[b]:=0;
eimc[eimc_p_eped]:=1.5;
StopBrakeDecc:=0;
ScndInMain:=false;
Vhyp:=1;
Vadd:=1;
PowerCorRatio:=1;
{inicjalizacja zmiennych}
//Loc:=LocInitial; //Ra: to i tak trzeba potem przesunąć, po ustaleniu pozycji na torze (potrzebna długość)
//Rot:=RotInitial;
for b:=0 to 1 do
with Couplers[b] do
begin
AllowedFlag:=3; //domyślnie hak i hamulec, inne trzeba włączyć jawnie w FIZ
CouplingFlag:=0;
Connected:=nil;
ConnectedNr:=0; //Ra: to nie ma znaczenia jak nie podłączony
Render:=false;
CForce:=0;
Dist:=0;
CheckCollision:=false;
end;
ScanCounter:=0;
BrakeCtrlPos:=-2; //to nie ma znaczenia, konstruktor w Mover.cpp zmienia na -2
BrakeDelayFlag:=0;
BrakeStatus:=b_off;
EmergencyBrakeFlag:=false;
MainCtrlPos:=0;
ScndCtrlPos:=0;
MainCtrlActualPos:=0;
ScndCtrlActualPos:=0;
LightsPos:=0;
Heating:=false;
Mains:=false;
ActiveDir:=0; //kierunek nie ustawiony
CabNo:=0; //sterowania nie ma, ustawiana przez CabActivization()
ActiveCab:=Cab; //obsada w podanej kabinie
DirAbsolute:=0;
SlippingWheels:=false;
SandDose:=false;
FuseFlag:=false;
ConvOvldFlag:=false; //hunter-251211
StLinFlag:=false;
ResistorsFlag:=false;
Rventrot:=0;
enrot:=0;
nrot:=0;
Itot:=0;
EnginePower:=0;
BrakePress:=0;
Compressor:=0;
ConverterFlag:=false;
CompressorAllow:=false;
DoorLeftOpened:=false;
DoorRightOpened:=false;
battery:=false;
EpFuse:=true;
Signalling:=false;
Radio:=true;
DoorSignalling:=false;
UnBrake:=false;
//Winger 160204
PantVolume:=0.48; //aby podniesione pantografy opadły w krótkim czasie przy wyłączonej sprężarce
PantFrontUp:=false;
PantRearUp:=false;
PantFrontStart:=0;
PantRearStart:=0;
PantFrontSP:=true;
PantRearSP:=true;
DoubleTr:=1;
BrakeSlippingTimer:=0;
dpBrake:=0; dpPipe:=0; dpMainValve:=0; dpLocalValve:=0;
MBPM:=1;
DynamicBrakeFlag:=false;
BrakeSystem:=Individual;
BrakeSubsystem:=ss_None;
Ft:=0; Ff:=0; Fb:=0;
Ftotal:=0; FStand:=0; FTrain:=0;
AccS:=0; AccN:=0; AccV:=0;
EventFlag:=false; SoundFlag:=0;
Vel:=Abs(VelInitial); V:=VelInitial/3.6;
LastSwitchingTime:=0;
LastRelayTime:=0;
DistCounter:=0;
PulseForce:=0;
PulseForceTimer:=0;
PulseForceCount:=0;
eAngle:=1.5;
dizel_fill:=0;
dizel_engagestate:=0;
dizel_engage:=0;
dizel_automaticgearstatus:=0;
dizel_enginestart:=false;
dizel_engagedeltaomega:=0;
PhysicActivation:=true;
for b:=1 to 20 do
eimv[b]:=0;
with RunningShape do
begin
R:=0; Len:=1; dHtrack:=0; dHrail:=0;
end;
RunningTrack.CategoryFlag:=CategoryFlag;
with RunningTrack do
begin
Width:=TrackW; friction:=Steel2Steel_friction;
QualityFlag:=20;
DamageFlag:=0;
Velmax:=100; {dla uzytku maszynisty w ai_driver}
end;
with RunningTraction do
begin
TractionVoltage:=0;
TractionFreq:=0;
TractionMaxCurrent:=0;
TractionResistivity:=1;
end;
OffsetTrackH:=0; OffsetTrackV:=0;
with CommandIn do
begin
Command:='';
Value1:=0; Value2:=0;
Location.x:=0; Location.y:=0; Location.z:=0;
end;
{czesciowo stale, czesciowo zmienne}
with SecuritySystem do
begin
SystemType:=0;
AwareDelay:=-1; SoundSignalDelay:=-1; EmergencyBrakeDelay:=-1;
Status:=0;
SystemTimer:=0; SystemBrakeCATimer:=0; SystemBrakeSHPTimer:=0; //hunter-091012
VelocityAllowed:=-1; NextVelocityAllowed:=-1;
RadioStop:=false; //domyślnie nie ma
AwareMinSpeed:=0.1*Vmax;
end;
//ABu 240105:
//CouplerNr[0]:=1;
//CouplerNr[1]:=0;
{TO POTEM TU UAKTYWNIC A WYWALIC Z CHECKPARAM}
{
if Pos(LoadTypeInitial,LoadAccepted)>0 then
begin
}
LoadType:=LoadTypeInitial;
Load:=LoadInitial;
LoadStatus:=0;
LastLoadChangeTime:=0;
{
end
else Load:=0;
}
Name:=NameInit;
DerailReason:=0; //Ra: powód wykolejenia
TotalCurrent:=0;
ShuntModeAllow:=false;
ShuntMode:=false;
end;
function T_MoverParameters.EngineDescription(what:integer): string; {opis stanu lokomotywy}
var outstr: string;
begin
outstr:='';
case what of
0: begin
if DamageFlag=255 then
outstr:='Totally destroyed!'
else
begin
if TestFlag(DamageFlag,dtrain_thinwheel) then
if Power>0.1 then
outstr:='Thin wheel,'
else
outstr:='Load shifted,';
if TestFlag(DamageFlag,dtrain_wheelwear) then
outstr:='Wheel wear,';
if TestFlag(DamageFlag,dtrain_bearing) then
outstr:='Bearing damaged,';
if TestFlag(DamageFlag,dtrain_coupling) then
outstr:='Coupler broken,';
if TestFlag(DamageFlag,dtrain_loaddamage) then
if Power>0.1 then
outstr:='Ventilator damaged,'
else
outstr:='Load damaged,';
if TestFlag(DamageFlag,dtrain_loaddestroyed) then
if Power>0.1 then
outstr:='Engine damaged,'
else
outstr:='Load destroyed!,';
if TestFlag(DamageFlag,dtrain_axle) then
outstr:='Axle broken,';
if TestFlag(DamageFlag,dtrain_out) then
outstr:='DERAILED!';
if outstr='' then
outstr:='OK!';
end;
end;
else outstr:='Invalid qualifier';
end;
EngineDescription:=outstr;
end;
function T_MoverParameters.CheckLocomotiveParameters(ReadyFlag:boolean;Dir:longint): boolean;
var //k:integer;
OK:boolean;
b:byte;
bcmsno: byte;
bcmss: byte;
const
DefBrakeTable:array[1..8]of Byte=(15,4,25,25,13,3,12,2);
begin
OK:=true;
AutoRelayFlag:=(AutoRelayType=1);
Sand:=SandCapacity;
if (Pos('o',AxleArangement)>0) and (EngineType=ElectricSeriesMotor) then
OK:=(RList[1].Bn*RList[1].Mn=NPoweredAxles); {test poprawnosci ilosci osi indywidualnie napedzanych}
if (Pos(LoadType,LoadAccepted)=0) and (LoadType<>'') then
begin
Load:=0;
OK:=false;
end;
if BrakeSystem=Individual then
if BrakeSubSystem<>ss_None then
OK:=false; {!}
if(BrakeVVolume=0)and(MaxBrakePress[3]>0)and(BrakeSystem<>Individual)then
BrakeVVolume:=MaxBrakePress[3]/(5-MaxBrakePress[3])*(BrakeCylRadius*BrakeCylRadius*BrakeCylDist*BrakeCylNo*pi)*1000;
if BrakeVVolume=0 then BrakeVVolume:=0.01;
// Hamulec.Free;
//(i_mbp, i_bcr, i_bcd, i_brc: real; i_bcn, i_BD, i_mat, i_ba, i_nbpa: byte)
case BrakeValve of
W, K : begin
Hamulec := TWest.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
if(MBPM<2)then //jesli przystawka wazaca
(Hamulec as TWest).SetLP(0,MaxBrakePress[3],0)
else
(Hamulec as TWest).SetLP(Mass, MBPM, MaxBrakePress[1]);
end;
KE : begin
Hamulec := TKE.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(Hamulec as TKE).SetRM(RapidMult);
if(MBPM<2)then //jesli przystawka wazaca
(Hamulec as TKE).SetLP(0,MaxBrakePress[3],0)
else
(Hamulec as TKE).SetLP(Mass, MBPM, MaxBrakePress[1])
end;
NEst3, ESt3, ESt3AL2, ESt4:
begin
Hamulec := TNESt3.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(Hamulec as TNEst3).SetSize(BrakeValveSize,BrakeValveParams);
if(MBPM<2)then //jesli przystawka wazaca
(Hamulec as TNESt3).SetLP(0,MaxBrakePress[3],0)
else
(Hamulec as TNESt3).SetLP(Mass, MBPM, MaxBrakePress[1])
end;
{ ESt3, ESt3AL2: if (MaxBrakePress[1])>0 then
begin
Hamulec := TESt3AL2.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
if(MBPM<2)then
(Hamulec as TESt3AL2).SetLP(0,MaxBrakePress[3],0)
else
(Hamulec as TESt3AL2).SetLP(Mass, MBPM, MaxBrakePress[1])
end
else
Hamulec := TESt3.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);}
LSt :begin
Hamulec := TLSt.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(Hamulec as TLSt).SetRM(RapidMult);
end;
EStED :begin
Hamulec := TEStED.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(Hamulec as TEStED).SetRM(RapidMult);
if(MBPM<2)then //jesli przystawka wazaca
(Hamulec as TEStED).SetLP(0,MaxBrakePress[3],0)
else
(Hamulec as TEStED).SetLP(Mass, MBPM, MaxBrakePress[1]);
end;
EP2:begin
Hamulec :=TEStEP2.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(Hamulec as TEStEP2).SetLP(Mass, MBPM, MaxBrakePress[1]);
end;
{ ESt4 :if (BrakeDelays and bdelay_R)=bdelay_R then
Hamulec:=TESt4R.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA)
else
Hamulec:= TESt.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);}
CV1 : Hamulec:= TCV1.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
CV1_L_TR:Hamulec:= TCV1L_TR.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA)
else
Hamulec := TBrake.Create(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
end;
Hamulec.SetASBP(MaxBrakePress[4]);
case BrakeHandle of
FV4a: Handle := TFV4aM.Create;
MHZ_EN57: Handle := TMHZ_EN57.Create;
FVel6: Handle := TFVel6.Create;
testH: Handle := Ttest.Create;
M394: Handle := TM394.Create;
Knorr: Handle := TH14K1.Create;
St113: Handle := TSt113.Create;
else
Handle := THandle.Create;
end;
case BrakeLocHandle of
FD1:
begin
LocHandle := TFD1.Create;
LocHandle.Init(MaxBrakePress[0]);
if(TrainType=dt_EZT)then
(LocHandle as TFD1).SetSpeed(3.5);
end;
Knorr:
begin
LocHandle := TH1405.Create;
LocHandle.Init(MaxBrakePress[0]);
end;
else
LocHandle := THandle.Create;
end;
//ustalanie srednicy przewodu glownego (lokomotywa lub napędowy
if (TestFlag(BrakeDelays,bdelay_G))and((not TestFlag(BrakeDelays,bdelay_R)) or (Power>1))then
Spg:=0.792
else
Spg:=0.507;
Pipe:= TReservoir.Create;
Pipe2:= TReservoir.Create; //zabezpieczenie, bo sie PG wywala... :(
Pipe.CreateCap((Max0R(Dim.L,14)+0.5)*Spg*1); //dlugosc x przekroj x odejscia i takie tam
Pipe2.CreateCap((Max0R(Dim.L,14)+0.5)*Spg*1);
if LightsPosNo>0 then LightsPos:=LightsDefPos;
{to dac potem do init}
if ReadyFlag then {gotowy do drogi}
begin
CompressedVolume:=VeselVolume*MinCompressor*(9.8+Random)/10;
ScndPipePress:=CompressedVolume/VeselVolume;
PipePress:=CntrlPipePress;
BrakePress:=0;
LocalBrakePos:=0;
// if (BrakeSystem=Pneumatic) and (BrakeCtrlPosNo>0) then
if CabNo=0 then
// BrakeCtrlPos:=-2; //odcięcie na zespolonym; Ra: hamulec jest poprawiany w DynObj.cpp
BrakeCtrlPos:=Trunc(Handle.GetPos(bh_NP))
else
BrakeCtrlPos:=Trunc(Handle.GetPos(bh_RP));
MainSwitch(false);
PantFront(true);
PantRear(true);
MainSwitch(true);
ActiveDir:=0; //Dir; //nastawnik kierunkowy - musi być ustawiane osobno!
DirAbsolute:=ActiveDir*CabNo; //kierunek jazdy względem sprzęgów
LimPipePress:=CntrlPipePress;
end
else
begin {zahamowany}
Volume:=BrakeVVolume*MaxBrakePress[3];
CompressedVolume:=VeselVolume*MinCompressor*0.55;
ScndPipePress:=5.1;
PipePress:=LowPipePress;
PipeBrakePress:=MaxBrakePress[3]*0.5;
BrakePress:=MaxBrakePress[3]*0.5;
LocalBrakePos:=0;
// if (BrakeSystem=Pneumatic) and (BrakeCtrlPosNo>0) then
// BrakeCtrlPos:=-2; //Ra: hamulec jest poprawiany w DynObj.cpp
BrakeCtrlPos:=Trunc(Handle.GetPos(bh_NP));
LimPipePress:=LowPipePress;
end;
ActFlowSpeed:=0;
BrakeCtrlPosR:=BrakeCtrlPos;
if(BrakeLocHandle=Knorr)then
LocalBrakePos:=5;
Pipe.CreatePress(PipePress);
Pipe2.CreatePress(ScndPipePress);
Pipe.Act;Pipe2.Act;
EqvtPipePress:=PipePress;
//// fv4ac:=Pipe.P;
//// fv4ar:=Pipe.P;
Handle.Init(PipePress);
ComputeConstans();
if(LoadFlag>0)then
begin
if(Load<MaxLoad*0.45)then
begin
IncBrakeMult();IncBrakeMult();DecBrakeMult();
if(Load<MaxLoad*0.35)then
DecBrakeMult();
end;
if(Load>=MaxLoad*0.45)then
begin
IncBrakeMult();
if(Load>=MaxLoad*0.55)then
IncBrakeMult();
end;
end;
//taki mini automat - powinno byc ladnie dobrze :)
BrakeDelayFlag:=bdelay_P;
if(TestFlag(BrakeDelays,bdelay_G))and not(TestFlag(BrakeDelays,bdelay_R))then
BrakeDelayFlag:=bdelay_G;
if(TestFlag(BrakeDelays,bdelay_R))and not(TestFlag(BrakeDelays,bdelay_G))then
BrakeDelayFlag:=bdelay_R;
//ustawianie PS/PN/EP/MED
BrakeOpModeFlag:=bom_PN;
if (BrakeOpModes and bom_PS)>0 then BrakeOpModeFlag:=bom_PS;
// if (BrakeOpModes and bom_EP)>0 then BrakeOpModeFlag:=bom_EP;
// if (BrakeOpModes and bom_MED)>0 then BrakeOpModeFlag:=bom_MED;
//
//yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)%
for b:=1 to 4 do
begin
if BrakeDelay[b]=0 then
BrakeDelay[b]:=DefBrakeTable[b];
BrakeDelay[b]:=BrakeDelay[b]*(2.5+Random)/3.0;
end;
if(TrainType=dt_ET22)then
CompressorPower:=0;
// Hamulec.Init(10*PipePress, 10*HighPipePress-0.15, 10*LowPipePress-0.15, 10*BrakePress, BrakeDelayFlag);
Hamulec.Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag);
// Hamulec.Init(0, 0, -1.5, 0, BrakeDelayFlag);
// PipePress:=PipePress;
ScndPipePress:=Compressor;
CheckLocomotiveParameters:=OK;
end;
function T_MoverParameters.DoorLeft(State: Boolean):Boolean;
begin
if (DoorLeftOpened<>State) and (DoorBlockedFlag=false) and (Battery=true) then
begin
DoorLeft:=true;
DoorLeftOpened:=State;
if (State=true) then
begin
if (CabNo>0) then
SendCtrlToNext('DoorOpen',1,CabNo) //1=lewe, 2=prawe
else
SendCtrlToNext('DoorOpen',2,CabNo); //zamiana
CompressedVolume:=CompressedVolume-0.003;
end
else
begin
if (CabNo>0) then
SendCtrlToNext('DoorClose',1,CabNo)
else
SendCtrlToNext('DoorClose',2,CabNo);
end;
end
else
DoorLeft:=false;
end;
function T_MoverParameters.DoorRight(State: Boolean):Boolean;
begin
if (DoorRightOpened<>State) and (DoorBlockedFlag=false) and (Battery=true) then
begin
DoorRight:=true;
DoorRightOpened:=State;
if (State=true) then
begin
if (CabNo>0) then
SendCtrlToNext('DoorOpen',2,CabNo) //1=lewe, 2=prawe
else
SendCtrlToNext('DoorOpen',1,CabNo); //zamiana
CompressedVolume:=CompressedVolume-0.003;
end
else
begin
if (CabNo>0) then
SendCtrlToNext('DoorClose',2,CabNo)
else
SendCtrlToNext('DoorClose',1,CabNo);
end;
end
else
DoorRight:=false;
end;
//Winger 160204 - pantografy
function T_MoverParameters.PantFront(State: Boolean):Boolean;
var pf1: Real;
begin
if (battery=true){ and ((TrainType<>dt_ET40)or ((TrainType=dt_ET40) and (EnginePowerSource.CollectorsNo>1)))}then
begin
PantFront:=true;
if (State=true) then pf1:=1
else pf1:=0;
if (PantFrontUp<>State) then
begin
PantFrontUp:=State;
if (State=true) then
begin
PantFrontStart:=0;
SendCtrlToNext('PantFront',1,CabNo);
end
else
begin
PantFront:=false;
PantFrontStart:=1;
SendCtrlToNext('PantFront',0,CabNo);
{Ra: nie ma potrzeby opuszczać obydwu na raz, jak mozemy każdy osobno
if (TrainType=dt_EZT) and (ActiveCab=1) then
begin
PantRearUp:=false;
PantRearStart:=1;
SendCtrlToNext('PantRear',0,CabNo);
end;
}
end;
end
else
SendCtrlToNext('PantFront',pf1,CabNo);
end
end;
function T_MoverParameters.PantRear(State: Boolean):Boolean;
var pf1: Real;
begin
if battery=true then
begin
PantRear:=true;
if (State=true) then pf1:=1
else pf1:=0;
if (PantRearUp<>State) then
begin
PantRearUp:=State;
if (State=true) then
begin
PantRearStart:=0;
SendCtrlToNext('PantRear',1,CabNo);
end
else
begin
PantRear:=false;
PantRearStart:=1;
SendCtrlToNext('PantRear',0,CabNo);
end;
end
else
SendCtrlToNext('PantRear',pf1,CabNo);
end
end;
{function T_MoverParameters.Heating(State: Boolean):Boolean;
begin
if (Heating<>State) then
begin
Heating:=State;
{ if (State=true) then
begin
// SendCtrlToNext('PantRear',1,CabNo);
end
else
begin
// SendCtrlToNext('PantRear',0,CabNo);
end; }
{ end
{ else
SendCtrlToNext('PantRear',0,CabNo); }
{end;}
function T_MoverParameters.LoadChkFile(chkpath:string):Boolean;
const param_ok=1; wheels_ok=2; dimensions_ok=4;
var
lines,s: string;
bl,i,k:integer;
b,OKflag:byte;
fin: text;
OK: boolean;
procedure BrakeValveDecode(s:string);
begin
if s='W' then
BrakeValve:=W
else if s='W_Lu_L' then
BrakeValve:=W_Lu_L
else if s='W_Lu_XR' then
BrakeValve:=W_Lu_XR
else if s='W_Lu_VI' then
BrakeValve:=W_Lu_VI
else if s='K' then
BrakeValve:=W
else if s='Kkg' then
BrakeValve:=Kkg
else if s='Kkp' then
BrakeValve:=Kkp
else if s='Kks' then
BrakeValve:=Kks
else if s='Hikp1' then
BrakeValve:=Hikp1
else if s='Hikss' then
BrakeValve:=Hikss
else if s='Hikg1' then
BrakeValve:=Hikg1
else if s='KE' then
BrakeValve:=KE
else if s='EStED' then
BrakeValve:=EStED
else if Pos('ESt',s)>0 then
BrakeValve:=ESt3
else if s='LSt' then
BrakeValve:=LSt
else if s='EP2' then
BrakeValve:=EP2
else if s='EP1' then
BrakeValve:=EP1
else if s='CV1' then
BrakeValve:=CV1
else if s='CV1_L_TR' then
BrakeValve:=CV1_L_TR
else
BrakeValve:=Other;
end;
procedure BrakeSubsystemDecode;
begin
case BrakeValve of
W,W_Lu_L,W_Lu_VI,W_Lu_XR: BrakeSubsystem:=ss_W;
ESt3,ESt3AL2,ESt4,EP2,EP1: BrakeSubsystem:=ss_ESt;
KE: BrakeSubsystem:=ss_KE;
CV1, CV1_L_TR: BrakeSubsystem:=ss_Dako;
LSt, EStED: BrakeSubsystem:=ss_LSt;
else
BrakeSubsystem:=ss_None;
end;
end;
function EngineDecode(s:string):TEngineTypes;
begin
if s='ElectricSeriesMotor' then
EngineDecode:=ElectricSeriesMotor
else if s='DieselEngine' then
EngineDecode:=DieselEngine
else if s='SteamEngine' then
EngineDecode:=SteamEngine
else if s='WheelsDriven' then
EngineDecode:=WheelsDriven
else if s='Dumb' then
EngineDecode:=Dumb
else if s='DieselElectric' then
EngineDecode:=DieselElectric //youBy: spal-ele
else if s='DumbDE' then
EngineDecode:=DieselElectric //youBy: spal-ele
else if s='ElectricInductionMotor' then
EngineDecode:=ElectricInductionMotor
{ else if s='EZT' then {dla kibla}
{ EngineDecode:=EZT }
else EngineDecode:=None;
end;
function PowerSourceDecode(s:string):TPowerSource;
begin
if s='Transducer' then PowerSourceDecode:=Transducer
else if s='Generator' then PowerSourceDecode:=Generator
else if s='Accu' then PowerSourceDecode:=Accumulator
else if s='CurrentCollector' then PowerSourceDecode:=CurrentCollector
else if s='PowerCable' then PowerSourceDecode:=PowerCable
else if s='Heater' then PowerSourceDecode:=Heater
else if s='Internal' then PowerSourceDecode:=InternalSource
else PowerSourceDecode:=NotDefined;
end;
function PowerDecode(s:string): TPowerType;
begin
if s='BioPower' then PowerDecode:=BioPower
else if s='BioPower' then PowerDecode:=BioPower
else if s='MechPower' then PowerDecode:=MechPower
else if s='ElectricPower' then PowerDecode:=ElectricPower
else if s='SteamPower' then PowerDecode:=SteamPower
else PowerDecode:=NoPower;
end;
procedure PowerParamDecode(lines,prefix:string; var PowerParamDecode:TPowerParameters);
begin
with PowerParamDecode do
begin
case SourceType of
NotDefined : PowerType:=PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType=')));
InternalSource : PowerType:=PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType=')));
Transducer : InputVoltage:=s2rE(DUE(ExtractKeyWord(lines,prefix+'TransducerInputV=')));
Generator : GeneratorEngine:=EngineDecode(DUE(ExtractKeyWord(lines,prefix+'GeneratorEngine=')));
Accumulator: begin
RAccumulator.MaxCapacity:=s2r(DUE(ExtractKeyWord(lines,prefix+'Cap=')));
s:=DUE(ExtractKeyWord(lines,prefix+'RS='));
RAccumulator.RechargeSource:=PowerSourceDecode(s);
end;
CurrentCollector: begin
with CollectorParameters do
begin
CollectorsNo:=s2lE(DUE(ExtractKeyWord(lines,'CollectorsNo=')));
MinH:=s2rE(DUE(ExtractKeyWord(lines,'MinH=')));
MaxH:=s2rE(DUE(ExtractKeyWord(lines,'MaxH=')));
CSW:=s2rE(DUE(ExtractKeyWord(lines,'CSW='))); //szerokość części roboczej
MaxV:=s2rE(DUE(ExtractKeyWord(lines,'MaxVoltage=')));
s:=ExtractKeyWord(lines,'OverVoltProt='); //przekaźnik nadnapięciowy
if s='Yes' then
OVP:=1
else
OVP:=0;
s:=ExtractKeyWord(lines,'MinV='); //napięcie rozłączające WS
if s='' then
MinV:=0.5*MaxV //gdyby parametr nie podany
else
MinV:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'InsetV='); //napięcie wymagane do załączenia WS
if s='' then
InsetV:=0.6*MaxV //gdyby parametr nie podany
else
InsetV:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'MinPress='); //ciśnienie rozłączające WS
if s='' then
MinPress:=2.0 //domyślnie 2 bary do załączenia WS
else
MinPress:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'MaxPress='); //maksymalne ciśnienie za reduktorem
if s='' then
MaxPress:=5.0+0.001*(random(50)-random(50))
else
MaxPress:=s2rE(DUE(s));
end;
end;
PowerCable : begin
RPowerCable.PowerTrans:=PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerTrans=')));
if RPowerCable.PowerTrans=SteamPower then
RPowerCable.SteamPressure:=s2r(DUE(ExtractKeyWord(lines,prefix+'SteamPress=')));
end;
Heater : begin
{jeszcze nie skonczone!}
end;
end;
if (SourceType<>Heater) and (SourceType<>InternalSource) then
if not ((SourceType=PowerCable) and (RPowerCable.PowerTrans=SteamPower)) then
begin
{ PowerTrans:=ElectricPower; }
MaxVoltage:=s2rE(DUE(ExtractKeyWord(lines,prefix+'MaxVoltage=')));
MaxCurrent:=s2r(DUE(ExtractKeyWord(lines,prefix+'MaxCurrent=')));
IntR:=s2r(DUE(ExtractKeyWord(lines,prefix+'IntR=')));
end;
end;
end;
begin
//OK:=true;
OKflag:=0;
LineCount:=0;
ConversionError:=666;
Mass:=0;
filename:=chkpath+TypeName+'.fiz';//'.chk';
assignfile(fin,filename);
{$I-}
reset(fin);
{$I+}
if IOresult<>0 then
begin
OK:=false;
ConversionError:=-8;
end
else
begin
ConversionError:=0;
while not (eof(fin) or (ConversionError<>0)) do
begin
readln(fin,lines);
inc(LineCount);
if Pos('/',lines)=0 then {nie komentarz}
begin
if Pos('Param.',lines)>0 then {stale parametry}
begin
SetFlag(OKFlag,param_ok);
s:=DUE(ExtractKeyWord(lines,'Category='));
if s='train' then
CategoryFlag:=1
else if s='road' then
CategoryFlag:=2
else if s='ship' then
CategoryFlag:=4
else if s='airplane' then
CategoryFlag:=8
else if s='unimog' then
CategoryFlag:=3
else
ConversionError:=-7;
s:=ExtractKeyWord(lines,'M=');
Mass:=s2rE(DUE(s)); {w kg}
s:=ExtractKeyWord(lines,'Mred='); {zredukowane masy wirujące}
if s='' then
Mred:=0
else
Mred:=s2rE(DUE(s)); {w kg}
s:=ExtractKeyWord(lines,'Vmax=');
Vmax:=s2rE(DUE(s)); {w km/h}
s:=ExtractKeyWord(lines,'PWR=');
Power:=s2r(DUE(s)); {w kW}
s:=ExtractKeyWord(lines,'HeatingP=');
HeatingPower:=s2r(DUE(s)); {w kW}
s:=ExtractKeyWord(lines,'LightP=');
LightPower:=s2r(DUE(s)); {w kW}
s:=ExtractKeyWord(lines,'SandCap=');
SandCapacity:=s2i(DUE(s)); {w kg}
TrainType:=dt_Default;
s:=Ups(DUE(ExtractKeyWord(lines,'Type='))); //wielkimi
if s='EZT' then
begin
TrainType:=dt_EZT;
IminLo:=1;IminHi:=2;Imin:=1; //wirtualne wartości dla rozrządczego
end
else if s='ET41' then TrainType:=dt_ET41
else if s='ET42' then TrainType:=dt_ET42
else if s='ET22' then TrainType:=dt_ET22
else if s='ET40' then TrainType:=dt_ET40
else if s='EP05' then TrainType:=dt_EP05
else if s='SN61' then TrainType:=dt_SN61
else if s='PSEUDODIESEL' then TrainType:=dt_PseudoDiesel
else if s='181' then TrainType:=dt_181
else if s='182' then TrainType:=dt_181; {na razie tak}
end
else if Pos('Load:',lines)>0 then {stale parametry}
begin
LoadAccepted:=LowerCase(DUE(ExtractKeyWord(lines,'LoadAccepted=')));
if LoadAccepted<>'' then
begin
s:=ExtractKeyWord(lines,'MaxLoad=');
MaxLoad:=s2lE(DUE(s));
LoadQuantity:=DUE(ExtractKeyWord(lines,'LoadQ='));
s:=ExtractKeyWord(lines,'OverLoadFactor=');
OverLoadFactor:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'LoadSpeed=');
LoadSpeed:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'UnLoadSpeed=');
UnLoadSpeed:=s2rE(DUE(s));
end;
end
else if Pos('Dimensions:',lines)>0 then {wymiary}
begin
with Dim do
begin
SetFlag(OKFlag,dimensions_ok);
s:=ExtractKeyWord(lines,'L=');
L:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'H=');
H:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'W=');
W:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Cx=');
Cx:=s2r(DUE(s));
if Cx=0 then Cx:=0.3;
s:=ExtractKeyWord(lines,'Floor=');
if s='' then
begin
if (H<=2.0) then
Floor:=H //gdyby nie było parametru, lepsze to niż zero
else
Floor:=0.0; //zgodność wsteczna
end
else
Floor:=s2rE(DUE(s));
end;
end
else if Pos('Wheels:',lines)>0 then {kola}
begin
{ SetFlag(OKFlag,wheels_ok);}
s:=ExtractKeyWord(lines,'D='); //średnica osi napędzających
WheelDiameter:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Dl='); //średnica przednich osi tocznych
if s='' then
WheelDiameterL:=WheelDiameter //gdyby nie było parametru, lepsze to niż zero
else
WheelDiameterL:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Dt='); //średnica tylnych osi tocznych
if s='' then
WheelDiameterT:=WheelDiameter //gdyby nie było parametru, lepsze to niż zero
else
WheelDiameterT:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Tw=');
TrackW:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'AIM=');
AxleInertialMoment:=s2r(DUE(s));
if AxleInertialMoment<=0 then AxleInertialMoment:=1;
AxleArangement:=DUE(ExtractKeyWord(lines,'Axle='));
NPoweredAxles:=s2NPW(AxleArangement);
NAxles:=NPoweredAxles+s2NNW(AxleArangement);
if NAxles=0 then ConversionError:=-1;
s:=DUE(ExtractKeyWord(lines,'BearingType='));
if s='Roll' then BearingType:=1
else BearingType:=0;
s:=ExtractKeyWord(lines,'Ad=');
ADist:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Bd=');
BDist:=s2r(DUE(s));
end
else if Pos('Brake:',lines)>0 then {hamulce}
begin
BrakeValveParams:=DUE(ExtractKeyWord(lines,'BrakeValve='));
BrakeValveDecode(BrakeValveParams);
BrakeSubSystemDecode;
s:=ExtractKeyWord(lines,'NBpA=');
NBpA:=s2b(DUE(s));
s:=ExtractKeyWord(lines,'MBF=');
MaxBrakeForce:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Size=');
BrakeValveSize:=s2i(DUE(s));
s:=ExtractKeyWord(lines,'TBF=');
TrackBrakeForce:=s2r(DUE(s))*1000;
s:=ExtractKeyWord(lines,'MaxBP=');
MaxBrakePress[3]:=s2r(DUE(s));
if MaxBrakePress[3]>0 then
begin
s:=ExtractKeyWord(lines,'BCN=');
BrakeCylNo:=s2iE(DUE(s));
if BrakeCylNo>0 then
begin
s:=ExtractKeyWord(lines,'MaxLBP=');
MaxBrakePress[0]:=s2r(DUE(s));
if MaxBrakePress[0]<0.01 then
MaxBrakePress[0]:=MaxBrakePress[3];
s:=DUE(ExtractKeyWord(lines,'TareMaxBP='));
MaxBrakePress[1]:=s2r(s);
s:=DUE(ExtractKeyWord(lines,'MedMaxBP='));
MaxBrakePress[2]:=s2r(s);
s:=ExtractKeyWord(lines,'MaxASBP=');
MaxBrakePress[4]:=s2r(DUE(s));
if MaxBrakePress[4]<0.01 then
MaxBrakePress[4]:=0;
s:=ExtractKeyWord(lines,'BCR=');
BrakeCylRadius:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'BCD=');
BrakeCylDist:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'BCS=');
BrakeCylSpring:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'BSA=');
BrakeSlckAdj:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'BRE=');
if s<>'' then
BrakeRigEff:=s2r(DUE(s))
else
BrakeRigEff:=1;
s:=ExtractKeyWord(lines,'BCM=');
BrakeCylMult[0]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'BCMlo=');
BrakeCylMult[1]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'BCMHi=');
BrakeCylMult[2]:=s2r(DUE(s));
P2FTrans:=100*Pi*SQR(BrakeCylRadius); {w kN/bar}
if (BrakeCylMult[1]>0) or (MaxBrakePress[1]>0) then LoadFlag:=1 else LoadFlag:=0;
BrakeVolume:=Pi*SQR(BrakeCylRadius)*BrakeCylDist*BrakeCylNo;
s:=ExtractKeyWord(lines,'BVV=');
BrakeVVolume:=s2R(DUE(s));
s:=DUE(ExtractKeyWord(lines,'BM='));
if s='P10-Bg' then BrakeMethod:=bp_P10Bg else
if s='P10-Bgu' then BrakeMethod:=bp_P10Bgu else
if s='FR513' then BrakeMethod:=bp_FR513 else
if s='FR510' then BrakeMethod:=bp_FR510 else
if s='Cosid' then BrakeMethod:=bp_Cosid else
if s='P10yBg' then BrakeMethod:=bp_P10yBg else
if s='P10yBgu' then BrakeMethod:=bp_P10yBgu else
if s='Disk1' then BrakeMethod:=bp_D1 else
if s='Disk1+Mg' then BrakeMethod:=bp_D1+bp_MHS else
if s='Disk2' then BrakeMethod:=bp_D2 else
BrakeMethod:=0;
s:=ExtractKeyWord(lines,'RM=');
if s<>'' then
RapidMult:=s2r(DUE(s))
else
RapidMult:=1;
end
else ConversionError:=-5;
end
else
P2FTrans:=0;
s:=ExtractKeyWord(lines,'HiPP=');
if s<>'' then CntrlPipePress:=s2r(DUE(s))
else CntrlPipePress:=5+0.001*(random(10)-random(10)); //Ra 2014-07: trochę niedokładności
HighPipePress:=CntrlPipePress;
s:=ExtractKeyWord(lines,'LoPP=');
if s<>'' then LowPipePress:=s2r(DUE(s))
else LowPipePress:=Min0R(HighPipePress,3.5);
DeltaPipePress:=HighPipePress-LowPipePress;
s:=ExtractKeyWord(lines,'Vv=');
VeselVolume:=s2r(DUE(s));
if VeselVolume=0 then
VeselVolume:=0.01;
s:=ExtractKeyWord(lines,'MinCP=');
MinCompressor:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'MaxCP=');
MaxCompressor:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'CompressorSpeed=');
CompressorSpeed:=s2r(DUE(s));
s:=DUE(ExtractKeyWord(lines,'CompressorPower='));
if s='Converter' then
CompressorPower:=2
else if s='Engine' then
CompressorPower:=3
else if s='Coupler1' then
CompressorPower:=4 //włączana w silnikowym EZT z przodu
else if s='Coupler2' then
CompressorPower:=5 //włączana w silnikowym EZT z tyłu
else if s='Main' then
CompressorPower:=0;
end
else if Pos('Doors:',lines)>0 then {drzwi}
begin
s:=DUE(ExtractKeyWord(lines,'OpenCtrl='));
if s='DriverCtrl' then DoorOpenCtrl:=1
else
DoorOpenCtrl:=0;
s:=DUE(ExtractKeyWord(lines,'CloseCtrl='));
if s='DriverCtrl' then DoorCloseCtrl:=1
else
if s='AutomaticCtrl' then DoorCloseCtrl:=2
else
DoorCloseCtrl:=0;
if DoorCloseCtrl=2 then
begin
s:=ExtractKeyWord(lines,'DoorStayOpen=');
DoorStayOpen:=s2rE(DUE(s));
end;
s:=ExtractKeyWord(lines,'OpenSpeed=');
DoorOpenSpeed:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'CloseSpeed=');
DoorCloseSpeed:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'DoorMaxShiftL=');
DoorMaxShiftL:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'DoorMaxShiftR=');
DoorMaxShiftR:=s2r(DUE(s));
s:=DUE(ExtractKeyWord(lines,'DoorOpenMethod='));
if s='Shift' then DoorOpenMethod:=1 //przesuw
else if s='Fold' then DoorOpenMethod:=3 //3 submodele się obracają
else if s='Plug' then DoorOpenMethod:=4 //odskokowo-przesuwne
else
DoorOpenMethod:=2; //obrót
s:=DUE(ExtractKeyWord(lines,'DoorClosureWarning='));
if s='Yes' then
DoorClosureWarning:=true
else
DoorClosureWarning:=false;
s:=DUE(ExtractKeyWord(lines,'DoorBlocked='));
if s='Yes' then DoorBlocked:=true
else
DoorBlocked:=false;
s:=ExtractKeyWord(lines,'DoorMaxShiftPlug=');
DoorMaxPlugShift:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'PlatformSpeed=');
PlatformSpeed:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'PlatformMaxSpeed=');
PlatformMaxShift:=s2r(DUE(s));
s:=DUE(ExtractKeyWord(lines,'PlatformOpenMethod='));
if s='Shift' then PlatformOpenMethod:=1 //przesuw
else
PlatformOpenMethod:=2; //obrót
end
else if (Pos('BuffCoupl.',lines)>0) or (Pos('BuffCoupl1.',lines)>0) then {zderzaki i sprzegi}
begin
with Couplers[0] do
begin
s:=DUE(ExtractKeyWord(lines,'CType='));
if s='Automatic' then
CouplerType:=Automatic
else
if s='Screw' then
CouplerType:=Screw
else
if s='Chain' then
CouplerType:=Chain
else
if s='Bare' then
CouplerType:=Bare
else
if s='Articulated' then
CouplerType:=Articulated
else
CouplerType:=NoCoupler;
s:=ExtractKeyWord(lines,'AllowedFlag=');
if s<>'' then AllowedFlag:=s2i(DUE(s));
if (AllowedFlag<0) then AllowedFlag:=(-AllowedFlag) OR ctrain_depot;
if (CouplerType<>NoCoupler) and (CouplerType<>Bare) and (CouplerType<>Articulated) then
begin
s:=ExtractKeyWord(lines,'kC=');
SpringKC:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'DmaxC=');
DmaxC:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'FmaxC=');
FmaxC:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'kB=');
SpringKB:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'DmaxB=');
DmaxB:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'FmaxB=');
FmaxB:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'beta=');
beta:=s2r(DUE(s));
end
else
if (CouplerType=Bare) then {Ra: czemu masy bez ładunków?}
begin
SpringKC:=50*Mass+Ftmax/0.05;
DmaxC:=0.05;
FmaxC:=100*Mass+2*Ftmax;
SpringKB:=60*Mass+Ftmax/0.05;
DmaxB:=0.05;
FmaxB:=50*Mass+2*Ftmax;
beta:=0.3;
end
else
if (CouplerType=Articulated) then
begin
SpringKC:=60*Mass+1000;
DmaxC:=0.05;
FmaxC:=20000000+2*Ftmax;
SpringKB:=70*Mass+1000;
DmaxB:=0.05;
FmaxB:=4000000+2*Ftmax;
beta:=0.55;
end;
end;
if (Pos('BuffCoupl.',lines)>0) then
begin
Couplers[1].SpringKC:=Couplers[0].SpringKC;
Couplers[1].DmaxC:=Couplers[0].DmaxC;
Couplers[1].FmaxC:=Couplers[0].FmaxC;
Couplers[1].SpringKB:=Couplers[0].SpringKB;
Couplers[1].DmaxB:=Couplers[0].DmaxB;
Couplers[1].FmaxB:=Couplers[0].FmaxB;
Couplers[1].beta:=Couplers[0].beta;
Couplers[1].CouplerType:=Couplers[0].CouplerType;
Couplers[1].AllowedFlag:=Couplers[0].AllowedFlag;
end;
{ CouplerTune:=(1+Mass)/100000; }
end
else if (Pos('BuffCoupl2.',lines)>0) then {zderzaki i sprzegi jesli sa rozne}
with Couplers[1] do
begin
s:=DUE(ExtractKeyWord(lines,'CType='));
if s='Automatic' then
CouplerType:=Automatic
else
if s='Screw' then
CouplerType:=Screw
else
if s='Chain' then
CouplerType:=Chain
else
if s='Bare' then
CouplerType:=Bare
else
if s='Articulated' then
CouplerType:=Articulated
else
CouplerType:=NoCoupler;
s:=ExtractKeyWord(lines,'AllowedFlag=');
if s<>'' then AllowedFlag:=s2i(DUE(s));
if (AllowedFlag<0) then AllowedFlag:=(-AllowedFlag) OR ctrain_depot;
if (CouplerType<>NoCoupler) and (CouplerType<>Bare) and (CouplerType<>Articulated) then
begin
s:=ExtractKeyWord(lines,'kC=');
SpringKC:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'DmaxC=');
DmaxC:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'FmaxC=');
FmaxC:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'kB=');
SpringKB:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'DmaxB=');
DmaxB:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'FmaxB=');
FmaxB:=s2rE(DUE(s))*1000;
s:=ExtractKeyWord(lines,'beta=');
beta:=s2r(DUE(s));
end
else
if (CouplerType=Bare) then
begin
SpringKC:=50*Mass+1000;
DmaxC:=0.05;
FmaxC:=20*Mass+2*Ftmax;
SpringKB:=60*Mass+1000;
DmaxB:=0.05;
FmaxB:=10*Mass+2*Ftmax;
beta:=0.3;
end
else
if (CouplerType=Articulated) then
begin
SpringKC:=60*Mass+1000;
DmaxC:=0.05;
FmaxC:=20000000+2*Ftmax;
SpringKB:=70*Mass+1000;;
DmaxB:=0.05;
FmaxB:=4000000+2*Ftmax;
beta:=0.55;
end;
{ CouplerTune:=(1+Mass)/100000; }
end
else if Pos('TurboPos:',lines)>0 then {turbo zalezne od pozycji nastawnika}
begin
s:=ExtractKeyWord(lines,'TurboPos=');
TurboTest:=s2b(DUE(s));
end
else if Pos('Cntrl.',lines)>0 then {nastawniki}
begin
s:=DUE(ExtractKeyWord(lines,'BrakeSystem='));
if s='Pneumatic' then BrakeSystem:=Pneumatic
else if s='ElectroPneumatic' then BrakeSystem:=ElectroPneumatic
else BrakeSystem:=Individual;
if BrakeSystem<>Individual then
begin
s:=ExtractKeyWord(lines,'BCPN=');
BrakeCtrlPosNo:=s2b(DUE(s));
for b:=1 to 4 do
begin
s:=ExtractKeyWord(lines,'BDelay'+Cut_Space(b2s(b),CutLeft)+'=');
BrakeDelay[b]:=s2b(DUE(s));
end;
s:=DUE(ExtractKeyWord(lines,'BrakeDelays='));
if s='GPR' then BrakeDelays:=bdelay_G+bdelay_P+bdelay_R
else if s='PR' then BrakeDelays:=bdelay_P+bdelay_R
else if s='GP' then BrakeDelays:=bdelay_G+bdelay_P
else if s='R' then begin BrakeDelays:=bdelay_R; BrakeDelayFlag:=bdelay_R; end
else if s='P' then begin BrakeDelays:=bdelay_P; BrakeDelayFlag:=bdelay_P; end
else if s='G' then begin BrakeDelays:=bdelay_G; BrakeDelayFlag:=bdelay_G; end
else if s='GPR+Mg' then BrakeDelays:=bdelay_G+bdelay_P+bdelay_R+bdelay_M
else if s='PR+Mg' then BrakeDelays:=bdelay_P+bdelay_R+bdelay_M;
s:=DUE(ExtractKeyWord(lines,'BrakeOpModes='));
if s='PN' then BrakeOpModes:=bom_PS+bom_PN
else if s='PNEPMED' then BrakeOpModes:=bom_PS+bom_PN+bom_EP+bom_MED;
{ else if s='DPR+Mg' then begin Brakedelays:=bdelay_R; BrakeMethod:=3; end
else if s='DGPR+Mg' then begin Brakedelays:=bdelay_G+bdelay_R; BrakeMethod:=3; end
else if s='DGPR' then begin Brakedelays:=bdelay_G+bdelay_R; BrakeMethod:=1; end
else if s='DPR' then begin Brakedelays:=bdelay_R; BrakeMethod:=1; end
else if s='DGP' then begin Brakedelays:=bdelay_G; BrakeMethod:=1; end;}
// else if s='GPR' then Brakedelays=bdelay_G+bdelay_R
s:=DUE(ExtractKeyWord(lines,'BrakeHandle='));
if s='FV4a' then BrakeHandle:=FV4a
else if s='test' then BrakeHandle:=testH
else if s='D2' then BrakeHandle:=D2
else if s='MHZ_EN57' then BrakeHandle:=MHZ_EN57
else if s='M394' then BrakeHandle:=M394
else if s='Knorr' then BrakeHandle:=Knorr
else if s='Westinghouse' then BrakeHandle:=West
else if s='FVel6' then BrakeHandle:=FVel6
else if s='St113' then BrakeHandle:=St113;
s:=DUE(ExtractKeyWord(lines,'LocBrakeHandle='));
if s='FD1' then BrakeLocHandle:=FD1
else if s='Knorr' then BrakeLocHandle:=Knorr
else if s='Westinghouse' then BrakeLocHandle:=West;
s:=DUE(ExtractKeyWord(lines,'MaxBPMass='));
if s<>'' then
MBPM:=s2rE(s)*1000;
if BrakeCtrlPosNo>0 then
begin
s:=DUE(ExtractKeyWord(lines,'ASB='));
if s='Manual' then ASBType:=1 else
if s='Automatic' then ASBType:=2;
end
else
begin
s:=DUE(ExtractKeyWord(lines,'ASB='));
if s='Yes' then ASBType:=128;
end;
end;
s:=DUE(ExtractKeyWord(lines,'LocalBrake='));
if s='ManualBrake' then LocalBrake:=ManualBrake
else
if s='PneumaticBrake' then LocalBrake:=PneumaticBrake
else
if s='HydraulicBrake' then LocalBrake:=HydraulicBrake
else LocalBrake:=NoBrake;
s:=DUE(ExtractKeyWord(lines,'ManualBrake='));
if s='Yes' then MBrake:=true
else MBrake:=false;
s:=DUE(ExtractKeyWord(lines,'DynamicBrake='));
if s='Passive' then DynamicBrakeType:=dbrake_passive
else
if s='Switch' then DynamicBrakeType:=dbrake_switch
else
if s='Reversal' then DynamicBrakeType:=dbrake_reversal
else
if s='Automatic' then DynamicBrakeType:=dbrake_automatic
else DynamicBrakeType:=dbrake_none;
s:=ExtractKeyWord(lines,'MCPN=');
MainCtrlPosNo:=s2b(DUE(s));
s:=ExtractKeyWord(lines,'SCPN=');
ScndCtrlPosNo:=s2b(DUE(s));
s:=ExtractKeyWord(lines,'SCIM=');
ScndinMain:=boolean(s2b(DUE(s)));
s:=DUE(ExtractKeyWord(lines,'AutoRelay='));
if s='Optional' then
AutoRelayType:=2
else
if s='Yes' then
AutoRelayType:=1
else
AutoRelayType:=0;
s:=DUE(ExtractKeyWord(lines,'CoupledCtrl='));
if s='Yes' then
CoupledCtrl:=true {wspolny wal}
else CoupledCtrl:=false;
s:=DUE(ExtractKeyWord(lines,'ScndS='));
if s='Yes' then
ScndS:=true {brak pozycji rownoleglej przy niskiej nastawie PSR}
else ScndS:=false;
s:=ExtractKeyWord(lines,'IniCDelay=');
InitialCtrlDelay:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'SCDelay=');
CtrlDelay:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'SCDDelay=');
if s<>'' then CtrlDownDelay:=s2r(DUE(s)) else CtrlDownDelay:=CtrlDelay; //hunter-101012: jesli nie ma SCDDelay;
s:=DUE(ExtractKeyWord(lines,'FSCircuit=')); //hunter-111012: dla siodemek 303E
if s='Yes' then
FastSerialCircuit:=1
else
FastSerialCircuit:=0;
s:=ExtractKeyWord(lines,'SBD=');
StopBrakeDecc:=s2r(DUE(s));
if BrakeCtrlPosNo>0 then
for i:=0 to BrakeCtrlPosNo+1 do
begin
s:=ReadWord(fin);
k:=s2iE(s);
if ConversionError=0 then
with BrakePressureTable[k] do
begin
read(fin,PipePressureVal,BrakePressureVal,FlowSpeedVal);
s:=ReadWord(fin);
if s='Pneumatic' then BrakeType:=Pneumatic
else if s='ElectroPneumatic' then BrakeType:=ElectroPneumatic
else BrakeType:=Individual;
{ readln(fin); }
end;
end;
end
else if Pos('Light:',lines)>0 then {zrodlo mocy dla oswietlenia}
begin
s:=DUE(ExtractKeyWord(lines,'Light='));
if s<>'' then
begin
LightPowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'L',LightPowerSource);
s:=DUE(ExtractKeyWord(lines,'AlterLight='));
if s<>'' then
begin
AlterLightPowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'AlterL',AlterLightPowerSource)
end
else AlterLightPowerSource.SourceType:=NotDefined;
end ;
s:=ExtractKeyWord(lines,'Volt=');
if s<>'' then
NominalVoltage:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'LMaxVoltage=');
if s<>'' then
begin
BatteryVoltage:=s2r(DUE(s));
NominalBatteryVoltage:=s2r(DUE(s));
end;
//else LightPowerSource.SourceType:=NotDefined;
end
else if Pos('Security:',lines)>0 then
begin
//if (TrainType<>dt_EZT)or(Power>1) then //dla EZT tylko w silnikowym
with SecuritySystem do
begin
s:=DUE(ExtractKeyWord(lines,'AwareSystem='));
if Pos('Active',s)>0 then
SetFlag(SystemType,1);
if Pos('CabSignal',s)>0 then
SetFlag(SystemType,2);
s:=ExtractKeyWord(lines,'AwareDelay=');
if s<>'' then
AwareDelay:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'AwareMinSpeed=');
if s<>'' then
AwareMinSpeed:=s2r(DUE(s))
else
AwareMinSpeed:=0.1*Vmax; //domyślnie 10% Vmax
s:=ExtractKeyWord(lines,'SoundSignalDelay=');
if s<>'' then
SoundSignalDelay:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'EmergencyBrakeDelay=');
if s<>'' then
EmergencyBrakeDelay:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'RadioStop=');
if s<>'' then
if Pos('Yes',s)>0 then
RadioStop:=true;
end
end
else if Pos('Clima:',lines)>0 then {zrodlo mocy dla ogrzewania itp}
begin
s:=DUE(ExtractKeyWord(lines,'Heating='));
if s<>'' then
begin
HeatingPowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'H',HeatingPowerSource);
s:=DUE(ExtractKeyWord(lines,'AlterHeating='));
if s<>'' then
begin
AlterHeatPowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'AlterH',AlterHeatPowerSource)
end
else AlterHeatPowerSource.SourceType:=NotDefined;
end
else HeatingPowerSource.SourceType:=NotDefined;
end
else if Pos('Power:',lines)>0 then {zrodlo mocy dla silnikow trakcyjnych itp}
begin
s:=DUE(ExtractKeyWord(lines,'EnginePower='));
if s<>'' then
begin
EnginePowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'',EnginePowerSource);
if (EnginePowerSource.SourceType=Generator) and (EnginePowerSource.GeneratorEngine=WheelsDriven) then
ConversionError:=-666; {perpetuum mobile?}
if (Power=0) then //jeśli nie ma mocy, np. rozrządcze EZT
EnginePowerSource.SourceType:=NotDefined; //to silnik nie ma zasilania
end
else EnginePowerSource.SourceType:=NotDefined;
//if EnginePowerSource.SourceType=NotDefined then
begin
s:=DUE(ExtractKeyWord(lines,'SystemPower='));
if s<>'' then
begin
SystemPowerSource.SourceType:=PowerSourceDecode(s);
PowerParamDecode(lines,'',SystemPowerSource);
end
else SystemPowerSource.SourceType:=NotDefined;
end
//else SystemPowerSource.SourceType:=InternalSource;
end
else if Pos('Engine:',lines)>0 then {stale parametry silnika}
begin
EngineType:=EngineDecode(DUE(ExtractKeyWord(lines,'EngineType=')));
case EngineType of
ElectricSeriesMotor:
begin
s:=ExtractKeyWord(lines,'Volt=');
NominalVoltage:=s2r(DUE(s));
s:=DUE(ExtractKeyWord(lines,'Trans='));
Transmision.NToothW:=s2b(copy(s,Pos(':',s)+1,Length(s)));
Transmision.NToothM:=s2b(copy(s,1,Pos(':',s)-1));
if s<>'' then
with Transmision do
if NToothM>0 then
Ratio:=NToothW/NToothM
else Ratio:=1;
s:=ExtractKeyWord(lines,'WindingRes=');
WindingRes:=s2r(DUE(s));
if WindingRes=0 then WindingRes:=0.01;
s:=ExtractKeyWord(lines,'nmax=');
nmax:=s2rE(DUE(s))/60.0;
end;
WheelsDriven:
begin
s:=DUE(ExtractKeyWord(lines,'Trans='));
Transmision.NToothW:=s2b(copy(s,Pos(':',s)+1,Length(s)));
Transmision.NToothM:=s2b(copy(s,1,Pos(':',s)-1));
if s<>'' then
with Transmision do
if NToothM>0 then
Ratio:=NToothW/NToothM
else Ratio:=1;
s:=ExtractKeyWord(lines,'Ftmax=');
Ftmax:=s2rE(DUE(s));
end;
Dumb:
begin
s:=ExtractKeyWord(lines,'Ftmax=');
Ftmax:=s2rE(DUE(s));
end;
DieselEngine:
begin
s:=DUE(ExtractKeyWord(lines,'Trans='));
Transmision.NToothW:=s2b(copy(s,Pos(':',s)+1,Length(s)));
Transmision.NToothM:=s2b(copy(s,1,Pos(':',s)-1));
if s<>'' then
with Transmision do
if NToothM>0 then
Ratio:=NToothW/NToothM
else Ratio:=1;
s:=ExtractKeyWord(lines,'nmin=');
dizel_nmin:=s2r(DUE(s))/60.0;
s:=ExtractKeyWord(lines,'nmax=');
nmax:=s2rE(DUE(s))/60.0;
s:=ExtractKeyWord(lines,'nmax_cutoff=');
dizel_nmax_cutoff:=s2r(DUE(s))/60.0;
s:=ExtractKeyWord(lines,'AIM=');
dizel_AIM:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'ShuntMode=');
if s<>'' then
begin //dodatkowa przekładnia dla SM03 (2Ls150)
ShuntModeAllow:=true;
ShuntMode:=false;
AnPos:=s2rE(DUE(s)); //dodatkowe przełożenie
if (AnPos<1.0) then //"rozruch wysoki" ma dawać większą siłę
AnPos:=1.0/AnPos; //im większa liczba, tym wolniej jedzie
end;
end;
DieselElectric: //youBy
begin
s:=DUE(ExtractKeyWord(lines,'Trans='));
Transmision.NToothW:=s2b(copy(s,Pos(':',s)+1,Length(s)));
Transmision.NToothM:=s2b(copy(s,1,Pos(':',s)-1));
if s<>'' then
with Transmision do
if NToothM>0 then
Ratio:=NToothW/NToothM
else Ratio:=1;
s:=ExtractKeyWord(lines,'Ftmax=');
Ftmax:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Flat=');
Flat:=Boolean(s2b(DUE(s)));
s:=ExtractKeyWord(lines,'Vhyp=');
Vhyp:=s2rE(DUE(s))/3.6;
s:=ExtractKeyWord(lines,'Vadd=');
Vadd:=s2rE(DUE(s))/3.6;
s:=ExtractKeyWord(lines,'Cr=');
PowerCorRatio:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'RelayType=');
RelayType:=s2b(DUE(s));
s:=ExtractKeyWord(lines,'ShuntMode=');
ShuntModeAllow:=Boolean(s2b(DUE(s)));
if (ShuntModeAllow) then
begin
ShuntModeAllow:=true;
ShuntMode:=false;
AnPos:=0;
ImaxHi:=2;
ImaxLo:=1;
end;
end;
ElectricInductionMotor:
begin
rventnmax:=1;
s:=ExtractKeyWord(lines,'Volt=');
NominalVoltage:=s2r(DUE(s));
s:=DUE(ExtractKeyWord(lines,'Trans='));
Transmision.NToothW:=s2b(copy(s,Pos(':',s)+1,Length(s)));
Transmision.NToothM:=s2b(copy(s,1,Pos(':',s)-1));
if s<>'' then
with Transmision do
if NToothM>0 then
Ratio:=NToothW/NToothM
else Ratio:=1;
s:=ExtractKeyWord(lines,'dfic='); eimc[eimc_s_dfic]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'dfmax='); eimc[eimc_s_dfmax]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'p='); eimc[eimc_s_p]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'cfu='); eimc[eimc_s_cfu]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'cim='); eimc[eimc_s_cim]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'icif='); eimc[eimc_s_icif]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Uzmax='); eimc[eimc_f_Uzmax]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Uzh='); eimc[eimc_f_Uzh]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'DU='); eimc[eimc_f_DU]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'I0='); eimc[eimc_f_I0]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'fcfu='); eimc[eimc_f_cfu]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'F0='); eimc[eimc_p_F0]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'a1='); eimc[eimc_p_a1]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Pmax='); eimc[eimc_p_Pmax]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Fh='); eimc[eimc_p_Fh]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Ph='); eimc[eimc_p_Ph]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Vh0='); eimc[eimc_p_Vh0]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Vh1='); eimc[eimc_p_Vh1]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Imax='); eimc[eimc_p_Imax]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'abed='); if DUE(s)<>'' then eimc[eimc_p_abed]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'edep='); if DUE(s)<>'' then eimc[eimc_p_eped]:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'Flat='); if DUE(s)='Yes' then Flat:=true else Flat:=false;
end;
else ConversionError:=-13; {not implemented yet!}
end;
end
{ Typy przelacznika 'Winger 010304 }
else if Pos('Switches:',lines)>0 then
begin
s:=DUE(ExtractKeyWord(lines,'Pantograph='));
PantSwitchType:=s;
s:=DUE(ExtractKeyWord(lines,'Converter='));
ConvSwitchType:=s;
{case PantSwitchType of
Continuos:
begin
PantSwitchType:='continuos';
end;
Impulse:
begin
PantSwitchType:='impulse';
end; }
end
else if Pos('MotorParamTable:',lines)>0 then
case EngineType of
ElectricSeriesMotor:
begin
for k:=0 to ScndCtrlPosNo do
begin
with MotorParam[k] do
read(fin, bl, mfi,mIsat, fi,Isat);
if AutoRelayType=0 then
MotorParam[k].AutoSwitch:=false
else begin
readln(fin,i);
MotorParam[k].AutoSwitch:=Boolean(i);
end;
if bl<>k then
ConversionError:=-2
end;
end;
//youBy
DieselElectric:
begin
// WW_MPTRelayNo:= ScndCtrlPosNo;
for k:=0 to ScndCtrlPosNo do
begin
with MotorParam[k] do
readln(fin, bl, mfi, mIsat, fi, Isat, MPTRelay[k].Iup, MPTRelay[k].Idown);
if bl<>k then
ConversionError:=-2
end;
end;
DieselEngine:
begin
s:=ExtractKeyWord(lines,'minVelfullengage=');
dizel_minVelfullengage:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'engageDia=');
dizel_engageDia:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'engageMaxForce=');
dizel_engageMaxForce:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'engagefriction=');
dizel_engagefriction:=s2r(DUE(s));
for k:=0 to ScndCtrlPosNo do
begin
with MotorParam[k] do
read(fin, bl, mIsat, fi,mfi);
if AutoRelayType=0 then
MotorParam[k].AutoSwitch:=false
else begin
readln(fin,i);
MotorParam[k].AutoSwitch:=Boolean(i);
end;
if bl<>k then
ConversionError:=-2
end;
end
else ConversionError:=-3;
end
//dwa dodatkowe parametry korekcyjne
else if Pos('MotorParamTable0:',lines)>0 then
begin
for k:=0 to ScndCtrlPosNo do
begin
with MotorParam[k] do
read(fin, bl, mfi,mIsat,mfi0, fi,Isat,fi0);
if AutoRelayType=0 then
MotorParam[k].AutoSwitch:=False
else begin
readln(fin,i);
MotorParam[k].AutoSwitch:=Boolean(i);
end;
if bl<>k then
ConversionError:=-2
end;
end
else if Pos('Circuit:',lines)>0 then
begin
s:=ExtractKeyWord(lines,'CircuitRes=');
CircuitRes:=s2r(DUE(s));
s:=ExtractKeyWord(lines,'IminLo=');
IminLo:=s2iE(DUE(s));
s:=ExtractKeyWord(lines,'IminHi=');
IminHi:=s2i(DUE(s));
s:=ExtractKeyWord(lines,'ImaxLo=');
ImaxLo:=s2iE(DUE(s));
s:=ExtractKeyWord(lines,'ImaxHi=');
ImaxHi:=s2i(DUE(s));
Imin:=IminLo;
Imax:=ImaxLo;
end
else if Pos('RList:',lines)>0 then
begin
s:=DUE(ExtractKeyWord(lines,'RVent='));
if s='Automatic' then RventType:=2
else
if s='Yes' then RventType:=1
else
RventType:=0;
if RventType>0 then
begin
s:=ExtractKeyWord(lines,'RVentnmax=');
RVentnmax:=s2rE(DUE(s))/60.0;
s:=ExtractKeyWord(lines,'RVentCutOff=');
RVentCutOff:=s2r(DUE(s));
end;
RListSize:=s2b(DUE(ExtractKeyWord(lines,'Size=')));
if RListSize>ResArraySize then
ConversionError:=-4
else
for k:=0 to RListSize do
begin
read(fin, RList[k].Relay, RList[k].R, RList[k].Bn, RList[k].Mn);
{ if AutoRelayType=0 then
RList[k].AutoSwitch:=false
else begin } {to sie przyda do pozycji przejsciowych}
read(fin,i);
RList[k].AutoSwitch:=Boolean(i);
if(ScndInMain)then
begin
readln(fin,i);
RList[k].ScndAct:=i;
end
else readln(fin);
end;
end
else if Pos('DList:',lines)>0 then {dla spalinowego silnika}
begin
s:=ExtractKeyWord(lines,'Mmax=');
dizel_Mmax:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'nMmax=');
dizel_nMmax:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Mnmax=');
dizel_Mnmax:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'nmax=');
dizel_nmax:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'nominalfill=');
dizel_nominalfill:=s2rE(DUE(s));
s:=ExtractKeyWord(lines,'Mstand=');
dizel_Mstand:=s2rE(DUE(s));
RListSize:=s2b(DUE(ExtractKeyWord(lines,'Size=')));
if RListSize>ResArraySize then
ConversionError:=-4
else
for k:=0 to RListSize do
begin
readln(fin, RList[k].Relay, RList[k].R, RList[k].Mn);
end;
end
//youBy
else if (Pos('WWList:',lines)>0) then {dla spal-ele}
begin
RListSize:=s2b(DUE(ExtractKeyWord(lines,'Size=')));
for k:=0 to RListSize do
begin
if not (ShuntModeAllow) then
readln(fin, DEList[k].rpm, DEList[k].genpower, DEList[k].Umax, DEList[k].Imax)
else
begin
readln(fin, DEList[k].rpm, DEList[k].genpower, DEList[k].Umax, DEList[k].Imax, SST[k].Umin, SST[k].Umax, SST[k].Pmax);
SST[k].Pmin:=sqrt(sqr(SST[k].Umin)/47.6);
SST[k].Pmax:=Min0R(SST[k].Pmax,sqr(SST[k].Umax)/47.6);
end;
end;
end
else if (Pos('ffList:',lines)>0) then {dla asynchronow}
begin
RListSize:=s2b(DUE(ExtractKeyWord(lines,'Size=')));
for k:=0 to RListSize do
readln(fin, DEList[k].rpm, DEList[k].genpower)
end
else if (Pos('LightsList:',lines)>0) then {dla asynchronow}
begin
LightsPosNo:=s2b(DUE(ExtractKeyWord(lines,'Size=')));
LightsWrap:=('Yes')=(DUE(ExtractKeyWord(lines,'Wrap=')));
LightsDefPos:=s2b(DUE(ExtractKeyWord(lines,'Default=')));
for k:=1 to LightsPosNo do
readln(fin, Lights[0][k], Lights[1][k])
end;
end;
end; {koniec filtru importu parametrow}
if ConversionError=0 then
OK:=true
else
OK:=false;
end; {otwarty plik}
if OK then
if OKflag<>param_ok{+wheels_ok}+dimensions_ok then
begin
OK:=false;
ConversionError:=-OKflag; {brakowalo jakiejs waznej linii z parametrami}
end;
if OK and (Mass<=0) then
begin
OK:=false;
ConversionError:=-666;
end;
LoadChkFile:=OK;
if ConversionError<>-8 then
close(fin);
end; {loadchkfile}
END.