16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 11:19:19 +02:00
Files
maszyna/McZapkie/_mover.pas
firleju c84bf7319b 1. Poprawione asynchrony.
2. Możliwość zdefiniowania koloru tła ekranu ładowania w eu07.ini.
3. Dodanie logowania ruchu ramek WM_COPYDATA do oddzielnego pliku.
4. Dodana ramka skrócona aktywnych AI.
5. Dodana ramka sterowania uszkodzeniami pojazdów.
6. Dodanie kręciołka od świateł (w tym trakcja wielokrotna).
7. Rozbudowa asynchronów, m.in. tempomat, zadawanie siły (w kN), przeciwpoślizg, czyste ED itd.
8. Dodanie animacji drtzwi odskokowo-przesuwnych.
9. Dodanie możliwości uszkadzania pojazdów (EN57).
10. Uruchomienie sprzęgu WN, zwłaszcza w asynchronach - do przejrzenia logowanie braków napięcia.
11. Wyłączanie radiostopu przez wyłączanie radia, a nie przez ruch zaworem maszynisty.
12. Usunięcie wyłącznika ciśnieniowego w EN57 (proteza, trzeba zrobić wpis na to).
13. Wstępna wersja hamowania rekuperacyjnego wraz z przechodzeniem na hamowanie oporowe.
14. Cała masa nowych zmiennych stanu dostępna dla ekranu (Pythona).
15. Nowa stara smuga z dawnego SPKSu.
16. Inne, które mogłem zapomnieć lub nie uszczegółowić.
17. Poprawione wyświetlanie haslera
2016-01-28 22:47:40 +01:00

7546 lines
290 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;
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
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}
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}
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 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 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);
dpMainValve:=Handle.GetPF(BrakeCtrlPosR, 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 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.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+100) 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 ((dtrans<0.25) and (LocHandle.GetCP<0.25) and (AnPos<0.01)) or ((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)>Adhesive(RunningTrack.friction)*TotalMassxg) then begin PosRatio:=0; tmp:=4; SandDoseOn; end;//przeciwposlizg
if (abs((PosRatio+9.80*dizel_fill)*dmoment*100)>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.02*(Voltage-EnginePowerSource.CollectorParameters.MaxV));
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(PantFrontVolt,PantRearVolt);
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;
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;
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;
//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,'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;
{ 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='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;
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.