From 398f832ea1e320a4a3429dfa3920a269fba64eaf Mon Sep 17 00:00:00 2001 From: firleju Date: Sat, 8 Oct 2016 09:13:40 +0200 Subject: [PATCH] =?UTF-8?q?mover=20przet=C5=82umaczony=20przez=20Q.=20Kome?= =?UTF-8?q?ntarze=20dodane=20do=20sta=C5=82ych=20i=20zmiennych.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- McZapkie/MOVER.h | 1020 ++++++ McZapkie/Mover.cpp | 7350 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 8370 insertions(+) create mode 100644 McZapkie/MOVER.h create mode 100644 McZapkie/Mover.cpp diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h new file mode 100644 index 00000000..0d686011 --- /dev/null +++ b/McZapkie/MOVER.h @@ -0,0 +1,1020 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#ifndef MoverH +#define MoverH +//--------------------------------------------------------------------------- +//#include "Mover.hpp" //Q: 20160805 - odlaczenie pliku fizyki .pas od kompilacji +#include "Oerlikon_ESt.h" +#include "hamulce.h" +#include + + +/* +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 +... +*/ + +#include "dumb3d.h" +using namespace Math3D; + +const Steel2Steel_friction = 0.15; //tarcie statyczne +const g = 9.81; //przyspieszenie ziemskie +const SandSpeed = 0.1; //ile kg/s} +const RVentSpeed = 0.4; //rozpedzanie sie wentylatora obr/s^2} +const RVentMinI = 50.0; //przy jakim pradzie sie wylaczaja} +const Pirazy2 = 6.2831853071794f; +#define PI 3.1415926535897f + +enum TProblem // lista problemów taboru, które uniemożliwiają jazdę +{ // flagi bitowe + pr_Hamuje = 1, // pojazd ma załączony hamulec lub zatarte osie + pr_Pantografy = 2, // pojazd wymaga napompowania pantografów + pr_Ostatni = 0x80000000 // ostatnia flaga bitowa +}; + +/*ogolne*/ +struct TLocation +{ + double X; + double Y; + double Z; /*lokacja*/ +}; +struct TRotation +{ + double Rx; + double Ry; + double Rz; /*rotacja*/ +}; +struct TDimension +{ + double W; + double L; + double H; /*wymiary*/ +}; + +struct TCommand +{ + std::string Command; /*komenda*/ + double Value1; + double Value2; /*argumenty komendy*/ + TLocation Location; +}; + +/*tory*/ +struct TTrackShape +{/*ksztalt odcinka - promien, dlugosc, nachylenie, przechylka*/ + double R; + double Len; + double dHtrack; + double dHrail; +}; + +struct TTrackParam +{/*parametry odcinka - szerokosc, tarcie statyczne, kategoria, obciazalnosc w t/os, uszkodzenia*/ + double Width; + double friction; + int CategoryFlag; + int QualityFlag; + int DamageFlag; + double Velmax; /*dla uzytku maszynisty w ai_driver*/ +}; + +struct TTractionParam +{ + double TractionVoltage; /*napiecie*/ + double TractionFreq; /*czestotliwosc*/ + double TractionMaxCurrent; /*obciazalnosc*/ + double TractionResistivity; /*rezystancja styku*/ +}; +/*powyzsze parametry zwiazane sa z torem po ktorym aktualnie pojazd jedzie*/ + +/*typy hamulcow zespolonych*/ +typedef enum TBrakeSystem { Individual, Pneumatic, ElectroPneumatic }; +/*podtypy hamulcow zespolonych*/ +typedef enum TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako }; +typedef enum 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 }; +typedef enum TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113, MHZ_P, MHZ_T, MHZ_EN57 }; +/*typy hamulcow indywidualnych*/ +typedef enum TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake }; +/*dla osob/towar: opoznienie hamowania/odhamowania*/ +typedef double TBrakeDelayTable[4]; + +struct TBrakePressure +{ + double PipePressureVal; + double BrakePressureVal; + double FlowSpeedVal; + TBrakeSystem BrakeType; +} ; + +typedef TBrakePressure TBrakePressureTable[MainBrakeMaxPos]; + + +/*typy napedow*/ +typedef enum TEngineTypes { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric }; +/*postac dostarczanej energii*/ +typedef enum TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower }; +/*rodzaj paliwa*/ +typedef enum TFuelType { Undefined, Coal, Oil }; +/*rodzaj rusztu*/ +struct TGrateType { + TFuelType FuelType; + double GrateSurface; + double FuelTransportSpeed; + double IgnitionTemperature; + double MaxTemperature; +}; +/*rodzaj kotla*/ +struct TBoilerType { + double BoilerVolume; + double BoilerHeatSurface; + double SuperHeaterSurface; + double MaxWaterVolume; double MinWaterVolume; + double MaxPressure; +}; +/*rodzaj odbieraka pradu*/ +struct TCurrentCollector { + long CollectorsNo; //musi być tu, bo inaczej się kopie + double MinH; double MaxH; //zakres ruchu pantografu, nigdzie nie używany + double CSW; //szerokość części roboczej (styku) ślizgacza + double MinV; double MaxV; //minimalne i maksymalne akceptowane napięcie + double OVP; //czy jest przekaznik nadnapieciowy + double InsetV; //minimalne napięcie wymagane do załączenia + double MinPress; //minimalne ciśnienie do załączenia WS + double MaxPress; //maksymalne ciśnienie za reduktorem +}; +/*typy źródeł mocy*/ +typedef enum TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater }; + + +struct _mover__1 +{ + double MaxCapacity; + TPowerSource RechargeSource; +} ; + +struct _mover__2 +{ + TPowerType PowerTrans; + double SteamPressure; +} ; + +struct _mover__3 +{ + TGrateType Grate; + TBoilerType Boiler; +} ; + +/*parametry źródeł mocy*/ +struct TPowerParameters +{ + double MaxVoltage; + double MaxCurrent; + double IntR; + TPowerSource SourceType; + union + { + struct + { + _mover__3 RHeater; + + }; + struct + { + _mover__2 RPowerCable; + + }; + struct + { + TCurrentCollector CollectorParameters; + + }; + struct + { + _mover__1 RAccumulator; + + }; + struct + { + TEngineTypes GeneratorEngine; + + }; + struct + { + double InputVoltage; + + }; + struct + { + TPowerType PowerType; + + }; + + }; +} ; + +/*dla lokomotyw elektrycznych:*/ +struct TScheme +{ + int Relay; /*numer pozycji rozruchu samoczynnego*/ + double R; /*opornik rozruchowy*/ /*dla dizla napelnienie*/ + int Bn; + int Mn; /*ilosc galezi i silnikow w galezi*/ /*dla dizla Mn: czy luz czy nie*/ + bool AutoSwitch; /*czy dana pozycja nastawniana jest recznie czy autom.*/ + int ScndAct; /*jesli ma bocznik w nastawniku, to ktory bocznik na ktorej pozycji*/ +}; +typedef TScheme TSchemeTable[ResArraySize + 1]; /*tablica rezystorow rozr.*/ +struct TDEScheme +{ + double RPM; /*obroty diesla*/ + double GenPower; /*moc maksymalna*/ + double Umax; /*napiecie maksymalne*/ + double Imax; /*prad maksymalny*/ +}; +typedef TDEScheme TDESchemeTable[33]; /*tablica rezystorow rozr.*/ +struct TShuntScheme +{ + double Umin; + double Umax; + double Pmin; + double Pmax; +}; +typedef TShuntScheme TShuntSchemeTable[33]; +struct TMPTRelay +{/*lista przekaznikow bocznikowania*/ + double Iup; + double Idown; +}; +typedef TMPTRelay TMPTRelayTable[8]; + +struct TMotorParameters +{ + double mfi; + double mIsat; + double mfi0; // aproksymacja M(I) silnika} {dla dizla mIsat=przekladnia biegu + double fi; + double Isat; + double fi0; // aproksymacja E(n)=fi*n} {dla dizla fi, mfi: predkosci przelozenia biegu <-> + bool AutoSwitch; +}; + +struct TSecuritySystem +{ + int SystemType; /*0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa*/ + double AwareDelay; // czas powtarzania czuwaka + double AwareMinSpeed; // minimalna prędkość załączenia czuwaka, normalnie 10% Vmax + double SoundSignalDelay; + double EmergencyBrakeDelay; + int Status; /*0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne*/ + double SystemTimer; + double SystemSoundCATimer; + double SystemSoundSHPTimer; + double SystemBrakeCATimer; + double SystemBrakeSHPTimer; + double SystemBrakeCATestTimer; // hunter-091012 + int VelocityAllowed; + int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/ + bool RadioStop; // czy jest RadioStop +}; + +struct TTransmision +{//liczba zebow przekladni + int NToothM; + int NToothW; + double Ratio; +} ; + +enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic }; + + +//-- var, const, procedure --------------------------------------------------- +static bool const Go = true; +static bool const Hold = false; /*dla CheckLocomotiveParameters*/ +static int const ResArraySize = 64; /*dla silnikow elektrycznych*/ +static int const MotorParametersArraySize = 10; +static int const maxcc = 4; /*max. ilosc odbierakow pradu*/ +static int const LocalBrakePosNo = 10; /*ilosc nastaw hamulca pomocniczego*/ +static int const MainBrakeMaxPos = 10; /*max. ilosc nastaw hamulca zasadniczego*/ +static int const ManualBrakePosNo = 20; /*ilosc nastaw hamulca recznego*/ +static int const LightsSwitchPosNo = 16; + +/*uszkodzenia toru*/ +static int const dtrack_railwear = 2; +static int const dtrack_freerail = 4; +static int const dtrack_thinrail = 8; +static int const dtrack_railbend = 16; +static int const dtrack_plants = 32; +static int const dtrack_nomove = 64; +static int const dtrack_norail = 128; + +/*uszkodzenia taboru*/ +static int const dtrain_thinwheel = 1; /*dla lokomotyw*/ +static int const dtrain_loadshift = 1; /*dla wagonow*/ +static int const dtrain_wheelwear = 2; +static int const dtrain_bearing = 4; +static int const dtrain_coupling = 8; +static int const dtrain_ventilator = 16; /*dla lokomotywy el.*/ +static int const dtrain_loaddamage = 16; /*dla wagonow*/ +static int const dtrain_engine = 32; /*dla lokomotyw*/ +static int const dtrain_loaddestroyed = 32;/*dla wagonow*/ +static int const dtrain_axle = 64; +static int const dtrain_out = 128; /*wykolejenie*/ + + /*wagi prawdopodobienstwa dla funkcji FuzzyLogic*/ +#define p_elengproblem (1.000000E-02) +#define p_elengdamage (1.000000E-01) +#define p_coupldmg (2.000000E-02) +#define p_derail (1.000000E-03) +#define p_accn (1.000000E-01) +#define p_slippdmg (1.000000E-03) + + /*typ sprzegu*/ +static int const ctrain_virtual = 0; //gdy pojazdy na tym samym torze się widzą wzajemnie +static int const ctrain_coupler = 1; //sprzeg fizyczny +static int const ctrain_pneumatic = 2; //przewody hamulcowe +static int const ctrain_controll = 4; //przewody sterujące (ukrotnienie) +static int const ctrain_power = 8; //przewody zasilające (WN) +static int const ctrain_passenger = 16; //mostek przejściowy +static int const ctrain_scndpneumatic = 32; //przewody 8 atm (żółte; zasilanie powietrzem) +static int const ctrain_heating = 64; //przewody ogrzewania WN +static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna + + /*typ hamulca elektrodynamicznego*/ +static int const dbrake_none = 0; +static int const dbrake_passive = 1; +static int const dbrake_switch = 2; +static int const dbrake_reversal = 4; +static int const dbrake_automatic = 8; + +/*status czuwaka/SHP*/ +//hunter-091012: rozdzielenie alarmow, dodanie testu czuwaka +static int const s_waiting = 1; //działa +static int const s_aware = 2; //czuwak miga +static int const s_active = 4; //SHP świeci +static int const s_CAalarm = 8; //buczy +static int const s_SHPalarm = 16; //buczy +static int const s_CAebrake = 32; //hamuje +static int const s_SHPebrake = 64; //hamuje +static int const s_CAtest = 128; + +/*dzwieki*/ +static int const sound_none = 0; +static int const sound_loud = 1; +static int const sound_couplerstretch = 2; +static int const sound_bufferclamp = 4; +static int const sound_bufferbump = 8; +static int const sound_relay = 16; +static int const sound_manyrelay = 32; +static int const sound_brakeacc = 64; + +static bool const PhysicActivationFlag = false; + +//szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType +//zamienione na flagi bitowe, aby szybko wybierać grupę (np. EZT+SZT) +static int const dt_Default = 0; +static int const dt_EZT = 1; +static int const dt_ET41 = 2; +static int const dt_ET42 = 4; +static int const dt_PseudoDiesel = 8; +static int const dt_ET22 = 0x10; //używane od Megapacka +static int const dt_SN61 = 0x20; //nie używane w warunkach, ale ustawiane z CHK +static int const dt_EP05 = 0x40; +static int const dt_ET40 = 0x80; +static int const dt_181 = 0x100; + +//stałe dla asynchronów +static int const eimc_s_dfic = 0; +static int const eimc_s_dfmax = 1; +static int const eimc_s_p = 2; +static int const eimc_s_cfu = 3; +static int const eimc_s_cim = 4; +static int const eimc_s_icif = 5; +static int const eimc_f_Uzmax = 7; +static int const eimc_f_Uzh = 8; +static int const eimc_f_DU = 9; +static int const eimc_f_I0 = 10; +static int const eimc_f_cfu = 11; +static int const eimc_p_F0 = 13; +static int const eimc_p_a1 = 14; +static int const eimc_p_Pmax = 15; +static int const eimc_p_Fh = 16; +static int const eimc_p_Ph = 17; +static int const eimc_p_Vh0 = 18; +static int const eimc_p_Vh1 = 19; +static int const eimc_p_Imax = 20; +static int const eimc_p_abed = 21; +static int const eimc_p_eped = 22; + +//zmienne dla asynchronów +static int const eimv_FMAXMAX = 0; +static int const eimv_Fmax = 1; +static int const eimv_ks = 2; +static int const eimv_df = 3; +static int const eimv_fp = 4; +static int const eimv_U = 5; +static int const eimv_pole = 6; +static int const eimv_Ic = 7; +static int const eimv_If = 8; +static int const eimv_M = 9; +static int const eimv_Fr = 10; +static int const eimv_Ipoj = 11; +static int const eimv_Pm = 12; +static int const eimv_Pe = 13; +static int const eimv_eta = 14; +static int const eimv_fkr = 15; +static int const eimv_Uzsmax = 16; +static int const eimv_Pmax = 17; +static int const eimv_Fzad = 18; +static int const eimv_Imax = 19; +static int const eimv_Fful = 20; + +static int const bom_PS = 1; +static int const bom_PN = 2; +static int const bom_EP = 4; +static int const bom_MED = 8; + +class TMoverParameters; // wyforwardowanie klasy coby typ byl widoczny w ponizszej strukturze +struct TCoupling { + /*parametry*/ + double SpringKB; double SpringKC; double beta; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */ + double DmaxB; double FmaxB; double DmaxC; double FmaxC; /*tolerancja scisku/rozciagania, sila rozerwania*/ + TCouplerType CouplerType; /*typ sprzegu*/ + /*zmienne*/ + int CouplingFlag; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/ + int AllowedFlag; //Ra: znaczenie jak wyżej, maska dostępnych + bool Render; /*ABu: czy rysowac jak zaczepiony sprzeg*/ + double CoupleDist; /*ABu: optymalizacja - liczenie odleglosci raz na klatkę, bez iteracji*/ + TMoverParameters Connected; /*co jest podlaczone*/ + int ConnectedNr; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył + double CForce; /*sila z jaka dzialal*/ + double Dist; /*strzalka ugiecia zderzaków*/ + bool CheckCollision; /*czy sprawdzac sile czy pedy*/ +}; + +class TMoverParameters +{ // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :) + public: + + double dMoveLen; + std::string filename; + /*---opis lokomotywy, wagonu itp*/ + /*--opis serii--*/ + int CategoryFlag; /*1 - pociag, 2 - samochod, 4 - statek, 8 - samolot*/ + /*--sekcja stalych typowych parametrow*/ + std::string TypeName; /*nazwa serii/typu*/ + //TrainType: string; {typ: EZT/elektrowoz - Winger 040304} + int TrainType; /*Ra: powinno być szybciej niż string*/ + TEngineTypes EngineType; /*typ napedu*/ + TPowerParameters EnginePowerSource; /*zrodlo mocy dla silnikow*/ + TPowerParameters SystemPowerSource; /*zrodlo mocy dla systemow sterowania/przetwornic/sprezarek*/ + TPowerParameters HeatingPowerSource; /*zrodlo mocy dla ogrzewania*/ + TPowerParameters AlterHeatPowerSource; /*alternatywne zrodlo mocy dla ogrzewania*/ + TPowerParameters LightPowerSource; /*zrodlo mocy dla oswietlenia*/ + TPowerParameters AlterLightPowerSource;/*alternatywne mocy dla oswietlenia*/ + double Vmax; double Mass; double Power; /*max. predkosc kontrukcyjna, masa wlasna, moc*/ + double Mred; /*Ra: zredukowane masy wirujące; potrzebne do obliczeń hamowania*/ + double TotalMass; /*wyliczane przez ComputeMass*/ + double HeatingPower; double LightPower; /*moc pobierana na ogrzewanie/oswietlenie*/ + double BatteryVoltage; /*Winger - baterie w elektrykach*/ + bool Battery; /*Czy sa zalavzone baterie*/ + bool EpFuse; /*Czy sa zalavzone baterie*/ + bool Signalling; /*Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu*/ + bool DoorSignalling; /*Czy jest zalaczona sygnalizacja blokady drzwi*/ + bool Radio; /*Czy jest zalaczony radiotelefon*/ + double NominalBatteryVoltage; /*Winger - baterie w elektrykach*/ + TDimension Dim; /*wymiary*/ + double Cx; /*wsp. op. aerodyn.*/ + double Floor; //poziom podłogi dla ładunków + double WheelDiameter; /*srednica kol napednych*/ + double WheelDiameterL; //Ra: srednica kol tocznych przednich + double WheelDiameterT; //Ra: srednica kol tocznych tylnych + double TrackW; /*nominalna szerokosc toru [m]*/ + double AxleInertialMoment; /*moment bezwladnosci zestawu kolowego*/ + std::string AxleArangement; /*uklad osi np. Bo'Bo' albo 1'C*/ + int NPoweredAxles; /*ilosc osi napednych liczona z powyzszego*/ + int NAxles; /*ilosc wszystkich osi j.w.*/ + int BearingType; /*lozyska: 0 - slizgowe, 1 - toczne*/ + double ADist; double BDist; /*odlegosc osi oraz czopow skretu*/ + /*hamulce:*/ + int NBpA; /*ilosc el. ciernych na os: 0 1 2 lub 4*/ + int SandCapacity; /*zasobnik piasku [kg]*/ + TBrakeSystem BrakeSystem;/*rodzaj hamulca zespolonego*/ + TBrakeSubSystem BrakeSubsystem; + TBrakeValve BrakeValve; + TBrakeHandle BrakeHandle; + TBrakeHandle BrakeLocHandle; + double MBPM; /*masa najwiekszego cisnienia*/ + + TBrake Hamulec; + TDriverHandle Handle; + TDriverHandle LocHandle; + TReservoir Pipe; TReservoir Pipe2; + + TLocalBrake LocalBrake; /*rodzaj hamulca indywidualnego*/ + TBrakePressureTable BrakePressureTable; /*wyszczegolnienie cisnien w rurze*/ + TBrakePressure BrakePressureActual; //wartości ważone dla aktualnej pozycji kranu + int ASBType; /*0: brak hamulca przeciwposlizgowego, 1: reczny, 2: automat*/ + int TurboTest; + double MaxBrakeForce; /*maksymalna sila nacisku hamulca*/ + double MaxBrakePress[5]; //pomocniczy, proz, sred, lad, pp + double P2FTrans; + double TrackBrakeForce; /*sila nacisku hamulca szynowego*/ + int BrakeMethod; /*flaga rodzaju hamulca*/ + /*max. cisnienie w cyl. ham., stala proporcjonalnosci p-K*/ + double HighPipePress; double LowPipePress; double DeltaPipePress; + /*max. i min. robocze cisnienie w przewodzie glownym oraz roznica miedzy nimi*/ + double CntrlPipePress; //ciśnienie z zbiorniku sterującym + double BrakeVolume; double BrakeVVolume; double VeselVolume; + /*pojemnosc powietrza w ukladzie hamulcowym, w ukladzie glownej sprezarki [m^3] */ + int BrakeCylNo; /*ilosc cylindrow ham.*/ + double BrakeCylRadius; double BrakeCylDist; + double BrakeCylMult[3]; + int LoadFlag; + /*promien cylindra, skok cylindra, przekladnia hamulcowa*/ + double BrakeCylSpring; /*suma nacisku sprezyn powrotnych, kN*/ + double BrakeSlckAdj; /*opor nastawiacza skoku tloka, kN*/ + double BrakeRigEff; /*sprawnosc przekladni dzwigniowej*/ + double RapidMult; /*przelozenie rapidu*/ + int BrakeValveSize; + std::string BrakeValveParams; + double Spg; + double MinCompressor; double MaxCompressor; double CompressorSpeed; + /*cisnienie wlaczania, zalaczania sprezarki, wydajnosc sprezarki*/ + TBrakeDelayTable BrakeDelay; /*opoznienie hamowania/odhamowania t/o*/ + int BrakeCtrlPosNo; /*ilosc pozycji hamulca*/ + /*nastawniki:*/ + int MainCtrlPosNo; /*ilosc pozycji nastawnika*/ + int ScndCtrlPosNo; + int LightsPosNo; int LightsDefPos; + bool LightsWrap; + int Lights[2][ /*?*//*1..16*/ (16) - (1) + 1]; + bool ScndInMain; /*zaleznosc bocznika od nastawnika*/ + bool MBrake; /*Czy jest hamulec reczny*/ + double StopBrakeDecc; + TSecuritySystem SecuritySystem; + + /*-sekcja parametrow dla lokomotywy elektrycznej*/ + TSchemeTable RList; /*lista rezystorow rozruchowych i polaczen silnikow, dla dizla: napelnienia*/ + int RlistSize; + TMotorParameters MotorParam[MotorParametersArraySize + 1]; + /*rozne parametry silnika przy bocznikowaniach*/ + /*dla lokomotywy spalinowej z przekladnia mechaniczna: przelozenia biegow*/ + TTransmision Transmision; + // record {liczba zebow przekladni} + // NToothM, NToothW : byte; + // Ratio: real; {NToothW/NToothM} + // end; + double NominalVoltage; /*nominalne napiecie silnika*/ + double WindingRes; + double u; //wspolczynnik tarcia yB wywalic!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + double CircuitRes; /*rezystancje silnika i obwodu*/ + int IminLo; int IminHi; /*prady przelacznika automatycznego rozruchu, uzywane tez przez ai_driver*/ + int ImaxLo; int ImaxHi; /*maksymalny prad niskiego i wysokiego rozruchu*/ + double nmax; /*maksymalna dop. ilosc obrotow /s*/ + double InitialCtrlDelay; double CtrlDelay; /* -//- -//- miedzy kolejnymi poz.*/ + double CtrlDownDelay; /* -//- -//- przy schodzeniu z poz.*/ /*hunter-101012*/ + int FastSerialCircuit;/*0 - po kolei zamyka styczniki az do osiagniecia szeregowej, 1 - natychmiastowe wejscie na szeregowa*/ /*hunter-111012*/ + int AutoRelayType; /*0 -brak, 1 - jest, 2 - opcja*/ + bool CoupledCtrl; /*czy mainctrl i scndctrl sa sprzezone*/ + //CouplerNr: TCouplerNr; {ABu: nr sprzegu podlaczonego w drugim obiekcie} + bool IsCoupled; /*czy jest sprzezony ale jedzie z tylu*/ + int DynamicBrakeType; /*patrz dbrake_**/ + int RVentType; /*0 - brak, 1 - jest, 2 - automatycznie wlaczany*/ + double RVentnmax; /*maks. obroty wentylatorow oporow rozruchowych*/ + double RVentCutOff; /*rezystancja wylaczania wentylatorow dla RVentType=2*/ + int CompressorPower; /*0: bezp. z obwodow silnika, 1: z przetwornicy, reczne, 2: w przetwornicy, stale, 5: z silnikowego*/ + int SmallCompressorPower; /*Winger ZROBIC*/ + bool Trafo; /*pojazd wyposażony w transformator*/ + + /*-sekcja parametrow dla lokomotywy spalinowej z przekladnia mechaniczna*/ + double dizel_Mmax; double dizel_nMmax; double dizel_Mnmax; double dizel_nmax; double dizel_nominalfill; + /*parametry aproksymacji silnika spalinowego*/ + double dizel_Mstand; /*moment oporow ruchu silnika dla enrot=0*/ + /* dizel_auto_min, dizel_auto_max: real; {predkosc obrotowa przelaczania automatycznej skrzyni biegow*/ + double dizel_nmax_cutoff; /*predkosc obrotowa zadzialania ogranicznika predkosci*/ + double dizel_nmin; /*najmniejsza dopuszczalna predkosc obrotowa*/ + double dizel_minVelfullengage; /*najmniejsza predkosc przy jezdzie ze sprzeglem bez poslizgu*/ + double dizel_AIM; /*moment bezwladnosci walu itp*/ + double dizel_engageDia; double dizel_engageMaxForce; double dizel_engagefriction; /*parametry sprzegla*/ + + /*- dla lokomotyw spalinowo-elektrycznych -*/ + double AnPos; // pozycja sterowania dokladnego (analogowego) + bool AnalogCtrl; // + bool AnMainCtrl; // + bool ShuntModeAllow; + bool ShuntMode; + + bool Flat; + double Vhyp; + TDESchemeTable DElist; + double Vadd; + TMPTRelayTable MPTRelay; + int RelayType; + TShuntSchemeTable SST; + double PowerCorRatio; //Wspolczynnik korekcyjny + + + /*- dla uproszczonego modelu silnika (dumb) oraz dla drezyny*/ + double Ftmax; + + /*- dla lokomotyw z silnikami indukcyjnymi -*/ + double eimc[26]; + + /*-dla wagonow*/ + long MaxLoad; /*masa w T lub ilosc w sztukach - ladownosc*/ + std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/ + double OverLoadFactor; /*ile razy moze byc przekroczona ladownosc*/ + double LoadSpeed; double UnLoadSpeed;/*szybkosc na- i rozladunku jednostki/s*/ + int DoorOpenCtrl; int DoorCloseCtrl; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/ + double DoorStayOpen; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/ + bool DoorClosureWarning; /*czy jest ostrzeganie przed zamknieciem*/ + double DoorOpenSpeed; double DoorCloseSpeed; /*predkosc otwierania i zamykania w j.u. */ + double DoorMaxShiftL; double DoorMaxShiftR; double DoorMaxPlugShift;/*szerokosc otwarcia lub kat*/ + int DoorOpenMethod; /*sposob otwarcia - 1: przesuwne, 2: obrotowe, 3: trójelementowe*/ + double PlatformSpeed; /*szybkosc stopnia*/ + double PlatformMaxShift; /*wysuniecie stopnia*/ + int PlatformOpenMethod; /*sposob animacji stopnia*/ + bool ScndS; /*Czy jest bocznikowanie na szeregowej*/ + + /*--sekcja zmiennych*/ + /*--opis konkretnego egzemplarza taboru*/ + TLocation Loc; //pozycja pojazdów do wyznaczenia odległości pomiędzy sprzęgami + TRotation Rot; + std::string Name; /*nazwa wlasna*/ + TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami + double HVCouplers[2][2]; //przewod WN + int ScanCounter; /*pomocnicze do skanowania sprzegow*/ + bool EventFlag; /*!o true jesli cos nietypowego sie wydarzy*/ + int SoundFlag; /*!o patrz stale sound_ */ + double DistCounter; /*! licznik kilometrow */ + double V; //predkosc w [m/s] względem sprzęgów (dodania gdy jedzie w stronę 0) + double Vel; //moduł prędkości w [km/h], używany przez AI + double AccS; //efektywne przyspieszenie styczne w [m/s^2] (wszystkie siły) + double AccN; //przyspieszenie normalne w [m/s^2] + double AccV; + double nrot; + /*! rotacja kol [obr/s]*/ + double EnginePower; /*! chwilowa moc silnikow*/ + double dL; double Fb; double Ff; /*przesuniecie, sila hamowania i tarcia*/ + double FTrain; double FStand; /*! sila pociagowa i oporow ruchu*/ + double FTotal; /*! calkowita sila dzialajaca na pojazd*/ + double UnitBrakeForce; /*!s siła hamowania przypadająca na jeden element*/ + double Ntotal; /*!s siła nacisku klockow*/ + bool SlippingWheels; bool SandDose; /*! poslizg kol, sypanie piasku*/ + double Sand; /*ilosc piasku*/ + double BrakeSlippingTimer; /*pomocnicza zmienna do wylaczania przeciwposlizgu*/ + double dpBrake; double dpPipe; double dpMainValve; double dpLocalValve; + /*! przyrosty cisnienia w kroku czasowym*/ + double ScndPipePress; /*cisnienie w przewodzie zasilajacym*/ + double BrakePress; /*!o cisnienie w cylindrach hamulcowych*/ + double LocBrakePress; /*!o cisnienie w cylindrach hamulcowych z pomocniczego*/ + double PipeBrakePress; /*!o cisnienie w cylindrach hamulcowych z przewodu*/ + double PipePress; /*!o cisnienie w przewodzie glownym*/ + double EqvtPipePress; /*!o cisnienie w przewodzie glownym skladu*/ + double Volume; /*objetosc spr. powietrza w zbiorniku hamulca*/ + double CompressedVolume; /*objetosc spr. powietrza w ukl. zasilania*/ + double PantVolume; /*objetosc spr. powietrza w ukl. pantografu*/ + double Compressor; /*! cisnienie w ukladzie zasilajacym*/ + bool CompressorFlag; /*!o czy wlaczona sprezarka*/ + bool PantCompFlag; /*!o czy wlaczona sprezarka pantografow*/ + bool CompressorAllow; /*! zezwolenie na uruchomienie sprezarki NBMX*/ + bool ConverterFlag; /*! czy wlaczona przetwornica NBMX*/ + bool ConverterAllow; /*zezwolenie na prace przetwornicy NBMX*/ + int BrakeCtrlPos; /*nastawa hamulca zespolonego*/ + double BrakeCtrlPosR; /*nastawa hamulca zespolonego - plynna dla FV4a*/ + double BrakeCtrlPos2; /*nastawa hamulca zespolonego - kapturek dla FV4a*/ + int LocalBrakePos; /*nastawa hamulca indywidualnego*/ + int ManualBrakePos; /*nastawa hamulca recznego*/ + double LocalBrakePosA; + int BrakeStatus; /*0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R*/ + bool EmergencyBrakeFlag; /*hamowanie nagle*/ + int BrakeDelayFlag; /*nastawa opoznienia ham. osob/towar/posp/exp 0/1/2/4*/ + int BrakeDelays; /*nastawy mozliwe do uzyskania*/ + int BrakeOpModeFlag; /*nastawa trybu pracy PS/PN/EP/MED 1/2/4/8*/ + int BrakeOpModes; /*nastawy mozliwe do uzyskania*/ + bool DynamicBrakeFlag; /*czy wlaczony hamulec elektrodymiczny*/ + // NapUdWsp: integer; + double LimPipePress; /*stabilizator cisnienia*/ + double ActFlowSpeed; /*szybkosc stabilizatora*/ + + + int DamageFlag; //kombinacja bitowa stalych dtrain_* } + int EngDmgFlag; //kombinacja bitowa stalych usterek} + int DerailReason; //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} + TCommand CommandIn; + /*komenda przekazywana przez PutCommand*/ + /*i wykonywana przez RunInternalCommand*/ + std::string CommandOut; /*komenda przekazywana przez ExternalCommand*/ + std::string CommandLast; //Ra: ostatnio wykonana komenda do podglądu + double ValueOut; /*argument komendy która ma byc przekazana na zewnatrz*/ + + TTrackShape RunningShape;/*geometria toru po ktorym jedzie pojazd*/ + TTrackParam RunningTrack;/*parametry toru po ktorym jedzie pojazd*/ + double OffsetTrackH; double OffsetTrackV; /*przesuniecie poz. i pion. w/m osi toru*/ + + /*-zmienne dla lokomotyw*/ + bool Mains; /*polozenie glownego wylacznika*/ + int MainCtrlPos; /*polozenie glownego nastawnika*/ + int ScndCtrlPos; /*polozenie dodatkowego nastawnika*/ + int LightsPos; + int ActiveDir; //czy lok. jest wlaczona i w ktorym kierunku: + //względem wybranej kabiny: -1 - do tylu, +1 - do przodu, 0 - wylaczona + int CabNo; //numer kabiny, z której jest sterowanie: 1 lub -1; w przeciwnym razie brak sterowania - rozrzad + int DirAbsolute; //zadany kierunek jazdy względem sprzęgów (1=w strone 0,-1=w stronę 1) + int ActiveCab; //numer kabiny, w ktorej jest obsada (zwykle jedna na skład) + double LastSwitchingTime; /*czas ostatniego przelaczania czegos*/ + //WarningSignal: byte; {0: nie trabi, 1,2: trabi} + bool DepartureSignal; /*sygnal odjazdu*/ + bool InsideConsist; + /*-zmienne dla lokomotywy elektrycznej*/ + TTractionParam RunningTraction;/*parametry sieci trakcyjnej najblizej lokomotywy*/ + double enrot; double Im; double Itot; double IHeating; double ITraction; double TotalCurrent; double Mm; double Mw; double Fw; double Ft; + /*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) + int Imin; int Imax; /*prad przelaczania automatycznego rozruchu, prad bezpiecznika*/ + double Voltage; /*aktualne napiecie sieci zasilajacej*/ + int MainCtrlActualPos; /*wskaznik RList*/ + int ScndCtrlActualPos; /*wskaznik MotorParam*/ + bool DelayCtrlFlag; //czy czekanie na 1. pozycji na załączenie? + double LastRelayTime; /*czas ostatniego przelaczania stycznikow*/ + bool AutoRelayFlag; /*mozna zmieniac jesli AutoRelayType=2*/ + bool FuseFlag; /*!o bezpiecznik nadmiarowy*/ + bool ConvOvldFlag; /*! nadmiarowy przetwornicy i ogrzewania*/ + bool StLinFlag; /*!o styczniki liniowe*/ + bool ResistorsFlag; /*!o jazda rezystorowa*/ + double RventRot; /*!s obroty wentylatorow rozruchowych*/ + bool UnBrake; /*w EZT - nacisniete odhamowywanie*/ + double PantPress; /*Cisnienie w zbiornikach pantografow*/ + bool s_CAtestebrake; //hunter-091012: zmienna dla testu ca + + + /*-zmienne dla lokomotywy spalinowej z przekladnia mechaniczna*/ + double dizel_fill; /*napelnienie*/ + double dizel_engagestate; /*sprzeglo skrzyni biegow: 0 - luz, 1 - wlaczone, 0.5 - wlaczone 50% (z poslizgiem)*/ + double dizel_engage; /*sprzeglo skrzyni biegow: aktualny docisk*/ + double dizel_automaticgearstatus; /*0 - bez zmiany, -1 zmiana na nizszy +1 zmiana na wyzszy*/ + bool dizel_enginestart; /*czy trwa rozruch silnika*/ + double dizel_engagedeltaomega; /*roznica predkosci katowych tarcz sprzegla*/ + + /*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/ + double eimv[21]; + + /*-zmienne dla drezyny*/ + double PulseForce; /*przylozona sila*/ + double PulseForceTimer; + int PulseForceCount; + + /*dla drezyny, silnika spalinowego i parowego*/ + double eAngle; + + /*-dla wagonow*/ + long Load; /*masa w T lub ilosc w sztukach - zaladowane*/ + std::string LoadType; /*co jest zaladowane*/ + int LoadStatus; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model + double LastLoadChangeTime; //raz (roz)ładowania + + bool DoorBlocked; //Czy jest blokada drzwi + bool DoorLeftOpened; //stan drzwi + bool DoorRightOpened; + bool PantFrontUp; //stan patykow 'Winger 160204 + bool PantRearUp; + bool PantFrontSP; //dzwiek patykow 'Winger 010304 + bool PantRearSP; + int PantFrontStart; //stan patykow 'Winger 160204 + int PantRearStart; + double PantFrontVolt; //pantograf pod napieciem? 'Winger 160404 + double PantRearVolt; + std::string PantSwitchType; + std::string ConvSwitchType; + + bool Heating; //ogrzewanie 'Winger 020304 + int DoubleTr; //trakcja ukrotniona - przedni pojazd 'Winger 160304 + + bool PhysicActivation; + + /*ABu: stale dla wyznaczania sil (i nie tylko) po optymalizacji*/ + double FrictConst1; + double FrictConst2s; + double FrictConst2d; + double TotalMassxg; /*TotalMass*g*/ + + vector3 vCoulpler[2]; // powtórzenie współrzędnych sprzęgów z DynObj :/ + vector3 DimHalf; // połowy rozmiarów do obliczeń geometrycznych + // int WarningSignal; //0: nie trabi, 1,2: trabi syreną o podanym numerze + int WarningSignal; // tymczasowo 8bit, ze względu na funkcje w MTools + double fBrakeCtrlPos; // płynna nastawa hamulca zespolonego + bool bPantKurek3; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką + int iProblem; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać + int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu + private: + double CouplerDist(Byte Coupler); + + public: + TMoverParameters(double VelInitial, AnsiString TypeNameInit, AnsiString NameInit, int LoadInitial, AnsiString LoadTypeInitial, int Cab); + // obsługa sprzęgów + double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2); + double Distance(const vector3 &Loc1, const vector3 &Loc2, const vector3 &Dim1, const vector3 &Dim2); + bool AttachA(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false); + bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false); + int DettachStatus(int ConnectNo); + bool Dettach(int ConnectNo); + void SetCoupleDist(); + bool DirectionForward(); + void BrakeLevelSet(double b); + bool BrakeLevelAdd(double b); + bool IncBrakeLevel(); // wersja na użytek AI + bool DecBrakeLevel(); + bool ChangeCab(int direction); + bool CurrentSwitch(int direction); + void UpdateBatteryVoltage(double dt); + double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot); + double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const TLocation &NewLoc, TRotation &NewRot); + double ShowEngineRotation(int VehN); + + // Q ******************************************************************************************* + double GetTrainsetVoltage(void); + bool Physic_ReActivation(void); + double LocalBrakeRatio(void); + double ManualBrakeRatio(void); + double PipeRatio(void); + double RealPipeRatio(void); + double BrakeVP(void); + + bool SendCtrlBroadcast(AnsiString CtrlCommand, double ctrlvalue); + bool SendCtrlToNext(AnsiString CtrlCommand, double ctrlvalue, double dir); + bool SetInternalCommand(AnsiString NewCommand, double NewValue1, double NewValue2); + double GetExternalCommand(AnsiString &Command); + bool RunCommand(AnsiString command, double CValue1, double CValue2); + bool RunInternalCommand(void); + void PutCommand(AnsiString NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation); + bool CabActivisation(void); + bool CabDeactivisation(void); + bool IncMainCtrl(int CtrlSpeed); + bool DecMainCtrl(int CtrlSpeed); + bool IncScndCtrl(int CtrlSpeed); + bool DecScndCtrl(int CtrlSpeed); + bool AddPulseForce(int Multipler); + bool SandDoseOn(void); + void SSReset(void); + bool SecuritySystemReset(void); + void SecuritySystemCheck(double dt); + bool BatterySwitch(bool State); + bool EpFuseSwitch(bool State); + bool IncBrakeLevelOld(void); + bool DecBrakeLevelOld(void); + bool IncLocalBrakeLevel(Byte CtrlSpeed); + bool DecLocalBrakeLevel(Byte CtrlSpeed); + bool IncLocalBrakeLevelFAST(void); + bool DecLocalBrakeLevelFAST(void); + bool IncManualBrakeLevel(Byte CtrlSpeed); + bool DecManualBrakeLevel(Byte CtrlSpeed); + bool DynamicBrakeSwitch(bool Switch); + bool EmergencyBrakeSwitch(bool Switch); + bool AntiSlippingBrake(void); + bool BrakeReleaser(Byte state); + bool SwitchEPBrake(Byte state); + bool AntiSlippingButton(void); + bool IncBrakePress(double &brake, double PressLimit, double dp); + bool DecBrakePress(double &brake, double PressLimit, double dp); + bool BrakeDelaySwitch(Byte BDS); + bool IncBrakeMult(void); + bool DecBrakeMult(void); + void UpdateBrakePressure(double dt); + void UpdatePipePressure(double dt); + void CompressorCheck(double dt); + void UpdatePantVolume(double dt); //Ra + void UpdateScndPipePressure(double dt); + double GetDVc(double dt); + void ComputeConstans(void); + double ComputeMass(void); + void ComputeTotalForce(double dt, double dt1, bool FullVer); + double Adhesive(double staticfriction); + double TractionForce(double dt); + double FrictionForce(double R, Byte TDamage); + double BrakeForce(const TTrackParam &Track); + double CouplerForce(Byte CouplerN, double dt); + void CollisionDetect(Byte CouplerN, double dt); + double ComputeRotatingWheel(double WForce, double dt, double n); + bool DirectionBackward(void); + bool MainSwitch(bool State); + bool ConverterSwitch(bool State); + bool CompressorSwitch(bool State); + void ConverterCheck(); + bool FuseOn(void); + bool FuseFlagCheck(void); + void FuseOff(void); + int ShowCurrent(Byte AmpN); + double v2n(void); + double current(double n, double U); + + double Momentum(double I); + double MomentumF(double I, double Iw, Byte SCP); + bool CutOffEngine(void); + bool MaxCurrentSwitch(bool State); + bool ResistorsFlagCheck(void); + bool MinCurrentSwitch(bool State); + bool AutoRelaySwitch(bool State); + bool AutoRelayCheck(void); + bool PantFront(bool State); + bool PantRear(bool State); + bool dizel_EngageSwitch(double state); + bool dizel_EngageChange(double dt); + bool dizel_AutoGearCheck(void); + double dizel_fillcheck(Byte mcp); + double dizel_Momentum(double dizel_fill, double n, double dt); + bool dizel_Update(double dt); + bool LoadingDone(double LSpeed, AnsiString LoadInit); + bool DoorLeft(bool State); + bool DoorRight(bool State); + bool DoorBlockedFlag(void); + bool ChangeOffsetH(double DeltaOffset); + + bool LoadFIZ(AnsiString chkpath); //Q 20160717 bool LoadChkFile(AnsiString chkpath); + bool readMPT(int ln, AnsiString xline); //Q 20160717 + bool readRLIST(int ln, AnsiString xline); //Q 20160718 + bool readBPT(int ln, AnsiString xline); //Q 20160721 + void BrakeValveDecode(AnsiString s); //Q 20160719 + void BrakeSubsystemDecode(); //Q 20160719 + void PowerParamDecode(AnsiString lines, AnsiString prefix, TPowerParameters &PowerParamDecode); //Q 20160719 + TPowerSource PowerSourceDecode(AnsiString s); //Q 20160719 + TPowerType PowerDecode(AnsiString s); //Q 20160719 + TEngineTypes EngineDecode(AnsiString s); //Q 20160721 + bool CreateBrakeSys(); //Q 20160722 + bool CheckLocomotiveParametersQ(bool ReadyFlag, int Dir); + AnsiString EngineDescription(int what); + int ShowCurrentP(Byte AmpN); //Q 20160722 +}; + +#endif diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp new file mode 100644 index 00000000..7ac5d038 --- /dev/null +++ b/McZapkie/Mover.cpp @@ -0,0 +1,7350 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ +#include "system.hpp" +#include "classes.hpp" + +#include +#include +#include +#include // std::ifstream +#include +#include +#include +#include // sprintf() +#include +#include +#include +#include +#include + +#include "Mover.h" +#include "globals.h" +#include "qutils.h" +#include "mctools.hpp" +#include "logs.h" +#include "hamulce.hpp" +#include "Oerlikon_ESt.hpp" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +// Ra: tu należy przenosić funcje z mover.pas, które nie są z niego wywoływane. +// Jeśli jakieś zmienne nie są używane w mover.pas, też można je przenosić. +// Przeniesienie wszystkiego na raz zrobiło by zbyt wielki chaos do ogarnięcia. + +const dEpsilon = 0.01; // 1cm (zależy od typu sprzęgu...) +const double CouplerTune = 0.1; //skalowanie tlumiennosci + + + +long Trunc(float f) +{ + return (long) f; +} + +long ROUND(float f) +{ + return Trunc(f+0.5); +} + +double sqr(double val) // SQR() zle liczylo w current() ... +{ + return val * val; +} + + +// ************************************************************************************************* +// Q: 20160716 +// ************************************************************************************************* +double TMoverParameters::current(double n, double U) +{ +//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 + + double R, MotorCurrent; + double Rz, Delta, Isf; + int Mn; + double Bn; + Byte SP; + double U1; //napiecie z korekta + + MotorCurrent = 0; +//i dzialanie hamulca ED w EP09 +//- if (DynamicBrakeType == dbrake_automatic) +//- { +//- if ((( static_cast(Hamulec)->GetEDBCP() < 0.25) && (Vadd < 1)) || (BrakePress > 2.1)) +//- DynamicBrakeFlag = false; +//- else if ((BrakePress > 0.25) && (static_cast(Hamulec)->GetEDBCP() > 0.25)) +//- DynamicBrakeFlag = true; +//- DynamicBrakeFlag = (DynamicBrakeFlag && ConverterFlag); +//- } + +//wylacznik cisnieniowy yBARC - to jest chyba niepotrzebne tutaj Q: no to usuwam... + +//BrakeSubsystem = ss_LSt; +//if (BrakeSubsystem == ss_LSt) WriteLog("LSt"); + if (BrakeSubsystem == ss_LSt) + if (DynamicBrakeFlag) + { + static_cast(Hamulec)->SetED(abs(Im / 350)); //hamulec ED na EP09 dziala az do zatrzymania lokomotywy +//- WriteLog("A"); + } + else + { + static_cast(Hamulec)->SetED(0); +//- WriteLog("B"); + } + + ResistorsFlag = (RList[MainCtrlActualPos].R > 0.01); // and (!DelayCtrlFlag) + ResistorsFlag = (ResistorsFlag || ((DynamicBrakeFlag == true) && (DynamicBrakeType == dbrake_automatic)) ); + + if ((TrainType == dt_ET22) && (DelayCtrlFlag) && (MainCtrlActualPos > 1)) + Bn = 1 - 1 / RList[MainCtrlActualPos].Bn; + else + Bn = 1; // to jest wykonywane dla EU07 + + R = RList[MainCtrlActualPos].R * Bn + CircuitRes; + + if ((TrainType != dt_EZT) || (Imin != IminLo) || (!ScndS)) //yBARC - boczniki na szeregu poprawnie + Mn = RList[MainCtrlActualPos].Mn; // to jest wykonywane dla EU07 + else + Mn = RList[MainCtrlActualPos].Mn * RList[MainCtrlActualPos].Bn; + +// writepaslog("#", "C++-----------------------------------------------------------------------------"); +// writepaslog("MCAP ", IntToStr(MainCtrlActualPos)); +// writepaslog("SCAP ", IntToStr(ScndCtrlActualPos)); +// writepaslog("n ", FloatToStr(n)); +// writepaslog("StLinFlag ", BoolToYN(StLinFlag)); +// writepaslog("DelayCtrlFlag ", booltoYN(DelayCtrlFlag)); +// writepaslog("Bn ", FloatToStr(Bn)); +// writepaslog("R ", FloatToStr(R)); +// writepaslog("Mn ", IntToStr(Mn)); +// writepaslog("RList[MCAP].Bn ", FloatToStr(RList[MainCtrlActualPos].Bn)); +// writepaslog("RList[MCAP].Mn ", FloatToStr(RList[MainCtrlActualPos].Mn)); +// writepaslog("RList[MCAP].R ", FloatToStr(RList[MainCtrlActualPos].R)); + +//z Megapacka ... bylo tutaj zakomentowane Q: no to usuwam... + +//- if (DynamicBrakeFlag && (!FuseFlag) && (DynamicBrakeType == dbrake_automatic) && ConverterFlag && Mains) //hamowanie EP09 //TUHEX +//- { +//- WriteLog("TUHEX"); +//- MotorCurrent = -Max0R(MotorParam[0].fi * (Vadd / (Vadd + MotorParam[0].Isat) - MotorParam[0].fi0), 0) * n * 2 / ep09resED; //TODO: zrobic bardziej uniwersalne nie tylko dla EP09 +//- } +//- else + if ((RList[MainCtrlActualPos].Bn == 0) || (!StLinFlag)) + MotorCurrent = 0; //wylaczone + else + { //wlaczone... + SP = ScndCtrlActualPos; + + if (ScndCtrlActualPos < 255) //tak smiesznie bede wylaczal + { + if (ScndInMain) + if (!(RList[MainCtrlActualPos].ScndAct == 255)) + SP = RList[MainCtrlActualPos].ScndAct; + + Rz = Mn * WindingRes + R; + +//- if (DynamicBrakeFlag) //hamowanie +//- { +//- +//- if (DynamicBrakeType > 1) +//- { +//- +//- if ((DynamicBrakeType == dbrake_switch) && (TrainType == dt_ET42)) +//- { //z Megapacka +//- Rz = WindingRes + R; +//- MotorCurrent = -MotorParam[SP].fi * n / Rz; //{hamowanie silnikiem na oporach rozruchowych} +//- } +//- } +//- else +//- MotorCurrent = 0; //odciecie pradu od silnika +//- } +//- else + { + U1 = U + Mn * n * MotorParam[SP].fi0 * MotorParam[SP].fi; +// writepaslog("U1 ", FloatToStr(U1)); +// writepaslog("Isat ", FloatToStr(MotorParam[SP].Isat)); +// writepaslog("fi ", FloatToStr(MotorParam[SP].fi)); + Isf = Sign(U1) * MotorParam[SP].Isat; +// writepaslog("Isf ", FloatToStr(Isf)); + Delta = sqr(Isf * Rz + Mn * MotorParam[SP].fi * n - U1) + 4 * U1 * Isf * Rz; // 105 * 1.67 + Mn * 140.9 * 20.532 - U1 +// DeltaQ = Isf * Rz + Mn * MotorParam[SP].fi * n - U1 + 4 * U1 * Isf * Rz; +// writepaslog("Delta ", FloatToStr(Delta)); +// writepaslog("DeltaQ ", FloatToStr(DeltaQ)); +// writepaslog("U ", FloatToStr(U)); + if (Mains) + { + if (U > 0) + MotorCurrent = (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n + sqrt(Delta)) / (2.0 * Rz); + else + MotorCurrent = (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n - sqrt(Delta)) / (2.0 * Rz); + } + else + MotorCurrent = 0; + } //else DBF + + } //255 + else + MotorCurrent = 0; + } +// writepaslog("MotorCurrent ", FloatToStr(MotorCurrent)); + +//- if ((DynamicBrakeType == dbrake_switch) && ((BrakePress > 2.0) || (PipePress < 3.6))) +//- { +//- WriteLog("DynamicBrakeType=" + IntToStr( dbrake_switch )); +//- Im = 0; +//- MotorCurrent = 0; +//- Itot = 0; +//- } +//- else + { + Im = MotorCurrent; + } + + EnginePower = abs(Itot) * (1 + RList[MainCtrlActualPos].Mn) * abs(U); + + //awarie + MotorCurrent = abs(Im); //zmienna pomocnicza + + if (MotorCurrent > 0) + { + + //-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) || FuzzyLogic(abs(n), nmax * 1.11, p_elengproblem))) + + //-if (SetFlag(DamageFlag, dtrain_engine)) + //- EventFlag = true; + + //! dorobic grzanie oporow rozruchowych i silnika + } + + return Im; +} + + +// ************************************************************************************************* +// główny konstruktor +// ************************************************************************************************* +TMoverParameters::TMoverParameters(double VelInitial, AnsiString TypeNameInit, AnsiString NameInit, int LoadInitial, AnsiString LoadTypeInitial, int Cab) //: T_MoverParameters(VelInitial, TypeNameInit, NameInit, LoadInitial, LoadTypeInitial, Cab) +{ + int b, k; + WriteLog("----------------------------------------------------------------------------------------"); + WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "], [" + LoadTypeInitial + "]"); + + DimHalf.x = 0.5 * Dim.W; // połowa szerokości, OX jest w bok? + DimHalf.y = 0.5 * Dim.L; // połowa długości, OY jest do przodu? + DimHalf.z = 0.5 * Dim.H; // połowa wysokości, OZ jest w górę? + // BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odcięcie (CHK jest jeszcze nie + // wczytane!) + bPantKurek3 = true; // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym + iProblem = 0; // pojazd w pełni gotowy do ruchu + iLights[0] = iLights[1] = 0; //światła zgaszone + + + //inicjalizacja stalych + dMoveLen = 0; + CategoryFlag = 1; + EngineType = None; + for (b = 0; b < ResArraySize; b++) + { + RList[b].Relay =0; + RList[b].R =0; + RList[b].Bn =0; + RList[b].Mn =0; + RList[b].AutoSwitch =false; + } + WheelDiameter =1.0; + BrakeCtrlPosNo =0; + LightsPosNo =0; + LightsDefPos =1; + for (k=-1; k < Hamulce::MainBrakeMaxPos; k++) + { + BrakePressureTable[k].PipePressureVal =0; + BrakePressureTable[k].BrakePressureVal =0; + BrakePressureTable[k].FlowSpeedVal =0; + } + + // with BrakePressureTable[-2] do {pozycja odciecia} + { + BrakePressureTable[-2].PipePressureVal =-1; + BrakePressureTable[-2].BrakePressureVal =-1; + BrakePressureTable[-2].FlowSpeedVal =0; + } + Transmision.Ratio = 1; + NBpA = 0; + DynamicBrakeType = 0; + ASBType = 0; + AutoRelayType = 0; + for (b=0; b < 1; b++) //Ra: kto tu zrobił "for b:=1 to 2 do" ??? + { + Couplers[b].CouplerType = NoCoupler; + Couplers[b].SpringKB =1; Couplers[b].SpringKC =1; + Couplers[b].DmaxB =0.1; Couplers[b].FmaxB =1000; + Couplers[b].DmaxC =0.1; Couplers[b].FmaxC =1000; + } + Power =0; + MaxLoad =0; + LoadAccepted =""; + LoadSpeed =0; + UnLoadSpeed =0; + HeatingPower =0; + LightPower =0; + + HeatingPowerSource.MaxVoltage =0; + HeatingPowerSource.MaxCurrent =0; + HeatingPowerSource.IntR =0.001; + HeatingPowerSource.SourceType =NotDefined; + HeatingPowerSource.PowerType =NoPower; + HeatingPowerSource.RPowerCable.PowerTrans =NoPower; + + + AlterHeatPowerSource.MaxVoltage =0; + AlterHeatPowerSource.MaxCurrent =0; + AlterHeatPowerSource.IntR =0.001; + AlterHeatPowerSource.SourceType =NotDefined; + AlterHeatPowerSource.PowerType =NoPower; + AlterHeatPowerSource.RPowerCable.PowerTrans =NoPower; + + + LightPowerSource.MaxVoltage =0; + LightPowerSource.MaxCurrent =0; + LightPowerSource.IntR =0.001; + LightPowerSource.SourceType =NotDefined; + LightPowerSource.PowerType =NoPower; + LightPowerSource.RPowerCable.PowerTrans =NoPower; + + + AlterLightPowerSource.MaxVoltage =0; + AlterLightPowerSource.MaxCurrent =0; + AlterLightPowerSource.IntR =0.001; + AlterLightPowerSource.SourceType =NotDefined; + AlterLightPowerSource.PowerType =NoPower; + AlterLightPowerSource.RPowerCable.PowerTrans =NoPower; + + TypeName =TypeNameInit; + HighPipePress =0; + LowPipePress =0; + DeltaPipePress =0; + BrakeCylNo =0; + BrakeCylRadius =0; + BrakeCylDist =0; + for (b=0; b<3; b++) 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; + + 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; b < 1; b++) + { + Couplers[b].AllowedFlag =3; //domyślnie hak i hamulec, inne trzeba włączyć jawnie w FIZ + Couplers[b].CouplingFlag =0; + Couplers[b].Connected = NULL; + Couplers[b].ConnectedNr =0; //Ra: to nie ma znaczenia jak nie podłączony + Couplers[b].Render =false; + Couplers[b].CForce =0; + Couplers[b].Dist =0; + Couplers[b].CheckCollision =false; + } + 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; + 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; + + + RunningShape.R =0; + RunningShape.Len =1; + RunningShape.dHtrack =0; + RunningShape.dHrail =0; + + RunningTrack.CategoryFlag =CategoryFlag; + RunningTrack.Width =TrackW; + RunningTrack.friction = Steel2Steel_friction; + RunningTrack.QualityFlag =20; + RunningTrack.DamageFlag =0; + RunningTrack.Velmax =100; //dla uzytku maszynisty w ai_driver} + + RunningTraction.TractionVoltage =0; + RunningTraction.TractionFreq =0; + RunningTraction.TractionMaxCurrent =0; + RunningTraction.TractionResistivity =1; + + OffsetTrackH =0; + OffsetTrackV =0; + + + CommandIn.Command =""; + CommandIn.Value1 =0; + CommandIn.Value2 =0; + CommandIn.Location.X =0; + CommandIn.Location.Y =0; + CommandIn.Location.Z =0; + + + //czesciowo stale, czesciowo zmienne} + + SecuritySystem.SystemType =0; + SecuritySystem.AwareDelay =-1; + SecuritySystem.SoundSignalDelay =-1; + SecuritySystem.EmergencyBrakeDelay =-1; + SecuritySystem.Status =0; + SecuritySystem.SystemTimer =0; + SecuritySystem.SystemBrakeCATimer =0; + SecuritySystem.SystemBrakeSHPTimer =0; //hunter-091012 + SecuritySystem.VelocityAllowed =-1; + SecuritySystem.NextVelocityAllowed =-1; + SecuritySystem.RadioStop =false; //domyślnie nie ma + SecuritySystem.AwareMinSpeed =0.1*Vmax; + + //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; + +}; + +double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2, + const TDimension &Dim1, const TDimension &Dim2) +{ // zwraca odległość pomiędzy pojazdami (Loc1) i (Loc2) z uwzględnieneim ich długości (kule!) + return hypot(Loc2.X - Loc1.X, Loc1.Y - Loc2.Y) - 0.5 * (Dim2.L + Dim1.L); +}; + +double TMoverParameters::Distance(const vector3 &s1, const vector3 &s2, const vector3 &d1, + const vector3 &d2){ + // obliczenie odległości prostopadłościanów o środkach (s1) i (s2) i wymiarach (d1) i (d2) + // return 0.0; //będzie zgłaszać warning - funkcja do usunięcia, chyba że się przyda... +}; + +double TMoverParameters::CouplerDist(Byte Coupler) +{ // obliczenie odległości pomiędzy sprzęgami (kula!) + return Couplers[Coupler].CoupleDist = + Distance(Loc, Couplers[Coupler].Connected->Loc, Dim, + Couplers[Coupler].Connected->Dim); // odległość pomiędzy sprzęgami (kula!) +}; + +bool TMoverParameters::AttachA(Byte ConnectNo, Byte ConnectToNr, TMoverParameters *ConnectTo, + Byte CouplingType, bool Forced) +{ //łączenie do swojego sprzęgu (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr) + // Ra: zwykle wykonywane dwukrotnie, dla każdego pojazdu oddzielnie + // Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do + // składu + if (ConnectTo) // jeśli nie pusty + { + if (ConnectToNr != 2) + Couplers[ConnectNo].ConnectedNr = ConnectToNr; // 2=nic nie podłączone + TCouplerType ct = ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr] + .CouplerType; // typ sprzęgu podłączanego pojazdu + Couplers[ConnectNo].Connected = + ConnectTo; // tak podpiąć (do siebie) zawsze można, najwyżej będzie wirtualny + CouplerDist(ConnectNo); // przeliczenie odległości pomiędzy sprzęgami + if (CouplingType == ctrain_virtual) + return false; // wirtualny więcej nic nie robi + if (Forced ? true : ((Couplers[ConnectNo].CoupleDist <= dEpsilon) && + (Couplers[ConnectNo].CouplerType != NoCoupler) && + (Couplers[ConnectNo].CouplerType == ct))) + { // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie + if (Couplers[ConnectNo].CouplingFlag == + ctrain_virtual) // jeśli wcześniej nie było połączone + { // ustalenie z której strony rysować sprzęg + Couplers[ConnectNo].Render = true; // tego rysować + ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Render = false; // a tego nie + }; + Couplers[ConnectNo].CouplingFlag = CouplingType; // ustawienie typu sprzęgu + // if (CouplingType!=ctrain_virtual) //Ra: wirtualnego nie łączymy zwrotnie! + //{//jeśli łączenie sprzęgiem niewirtualnym, ustawiamy połączenie zwrotne + ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag = CouplingType; + ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Connected = this; + ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CoupleDist = + Couplers[ConnectNo].CoupleDist; + return true; + //} + // podłączenie nie udało się - jest wirtualne + } + } + return false; // brak podłączanego pojazdu, zbyt duża odległość, niezgodny typ sprzęgu, brak + // sprzęgu, brak haka +}; + +bool TMoverParameters::Attach(Byte ConnectNo, Byte ConnectToNr, TMoverParameters *ConnectTo, + Byte CouplingType, bool Forced) +{ //łączenie do (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr) + return AttachA(ConnectNo, ConnectToNr, (TMoverParameters *)ConnectTo, CouplingType, Forced); +}; + +int TMoverParameters::DettachStatus(Byte ConnectNo) +{ // Ra: sprawdzenie, czy odległość jest dobra do rozłączania + // powinny być 3 informacje: =0 sprzęg już rozłączony, <0 da się rozłączyć. >0 nie da się + // rozłączyć + if (!Couplers[ConnectNo].Connected) + return 0; // nie ma nic, to rozłączanie jest OK + if ((Couplers[ConnectNo].CouplingFlag & ctrain_coupler) == 0) + return -Couplers[ConnectNo].CouplingFlag; // hak nie połączony - rozłączanie jest OK + if (TestFlag(DamageFlag, dtrain_coupling)) + return -Couplers[ConnectNo].CouplingFlag; // hak urwany - rozłączanie jest OK + // ABu021104: zakomentowane 'and (CouplerType<>Articulated)' w warunku, nie wiem co to bylo, ale + // za to teraz dziala odczepianie... :) } + // if (CouplerType==Articulated) return false; //sprzęg nie do rozpięcia - może być tylko urwany + // Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim); + CouplerDist(ConnectNo); + if (Couplers[ConnectNo].CouplerType == Screw ? Couplers[ConnectNo].CoupleDist < 0.0 : true) + return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty + return (Couplers[ConnectNo].CoupleDist > 0.2) ? -Couplers[ConnectNo].CouplingFlag : + Couplers[ConnectNo].CouplingFlag; +}; + +bool TMoverParameters::Dettach(Byte ConnectNo) +{ // rozlaczanie + if (!Couplers[ConnectNo].Connected) + return true; // nie ma nic, to odczepiono + // with Couplers[ConnectNo] do + int i = DettachStatus(ConnectNo); // stan sprzęgu + if (i < 0) + { // gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony) + // Couplers[ConnectNo].Connected=NULL; //lepiej zostawic bo przeciez trzeba kontrolowac + // zderzenia odczepionych + Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag = + 0; // pozostaje sprzęg wirtualny + Couplers[ConnectNo].CouplingFlag = 0; // pozostaje sprzęg wirtualny + return true; + } + else if (i > 0) + { // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym + // nic) + Couplers[ConnectNo].CouplingFlag &= ctrain_coupler; + Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag = + Couplers[ConnectNo].CouplingFlag; + } + return false; // jeszcze nie rozłączony +}; + +void TMoverParameters::SetCoupleDist() +{ // przeliczenie odległości sprzęgów + if (Couplers[0].Connected) + { + CouplerDist(0); + if (CategoryFlag & 2) + { // Ra: dla samochodów zderzanie kul to za mało + } + } + if (Couplers[1].Connected) + { + CouplerDist(1); + if (CategoryFlag & 2) + { // Ra: dla samochodów zderzanie kul to za mało + } + } +}; + +bool TMoverParameters::DirectionForward() +{ + if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos == 0)) + { + ++ActiveDir; + DirAbsolute = ActiveDir * CabNo; + if (DirAbsolute) + if (Battery) // jeśli bateria jest już załączona + BatterySwitch(true); // to w ten oto durny sposób aktywuje się CA/SHP + SendCtrlToNext("Direction", ActiveDir, CabNo); + return true; + } + else if ((ActiveDir == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT)) + return MinCurrentSwitch(true); //"wysoki rozruch" EN57 + return false; +}; + +// Nastawianie hamulców + +void TMoverParameters::BrakeLevelSet(double b) +{ // ustawienie pozycji hamulca na wartość (b) w zakresie od -2 do BrakeCtrlPosNo + // jedyny dopuszczalny sposób przestawienia hamulca zasadniczego + if (fBrakeCtrlPos == b) + return; // nie przeliczać, jak nie ma zmiany + fBrakeCtrlPos = b; + BrakeCtrlPosR = b; + if (fBrakeCtrlPos < Handle->GetPos(bh_MIN)) + fBrakeCtrlPos = Handle->GetPos(bh_MIN); // odcięcie + else if (fBrakeCtrlPos > Handle->GetPos(bh_MAX)) + fBrakeCtrlPos = Handle->GetPos(bh_MAX); + int x = floor(fBrakeCtrlPos); // jeśli odwołujemy się do BrakeCtrlPos w pośrednich, to musi być + // obcięte a nie zaokrągone + while ((x > BrakeCtrlPos) && (BrakeCtrlPos < BrakeCtrlPosNo)) // jeśli zwiększyło się o 1 + if (!IncBrakeLevelOld()) // T_MoverParameters:: + break; // wyjście awaryjne + while ((x < BrakeCtrlPos) && (BrakeCtrlPos >= -1)) // jeśli zmniejszyło się o 1 + if (!DecBrakeLevelOld()) // T_MoverParameters:: + break; + BrakePressureActual = BrakePressureTable[BrakeCtrlPos + 2]; // skopiowanie pozycji + /* + //youBy: obawiam sie, ze tutaj to nie dziala :P + //Ra 2014-03: było tak zrobione, że działało - po każdej zmianie pozycji była wywoływana ta + funkcja + // if (BrakeSystem==Pneumatic?BrakeSubsystem==Oerlikon:false) //tylko Oerlikon akceptuje ułamki + if(false) + if (fBrakeCtrlPos>0.0) + {//wartości pośrednie wyliczamy tylko dla hamowania + double u=fBrakeCtrlPos-double(x); //ułamek ponad wartość całkowitą + if (u>0.0) + {//wyliczamy wartości ważone + BrakePressureActual.PipePressureVal+=-u*BrakePressureActual.PipePressureVal+u*BrakePressureTable[BrakeCtrlPos+1+2].PipePressureVal; + //BrakePressureActual.BrakePressureVal+=-u*BrakePressureActual.BrakePressureVal+u*BrakePressureTable[BrakeCtrlPos+1].BrakePressureVal; + //to chyba nie będzie tak działać, zwłaszcza w EN57 + BrakePressureActual.FlowSpeedVal+=-u*BrakePressureActual.FlowSpeedVal+u*BrakePressureTable[BrakeCtrlPos+1+2].FlowSpeedVal; + } + } + */ +}; + +bool TMoverParameters::BrakeLevelAdd(double b) +{ // dodanie wartości (b) do pozycji hamulca (w tym ujemnej) + // zwraca false, gdy po dodaniu było by poza zakresem + BrakeLevelSet(fBrakeCtrlPos + b); + return b > 0.0 ? (fBrakeCtrlPos < BrakeCtrlPosNo) : + (BrakeCtrlPos > -1.0); // true, jeśli można kontynuować +}; + +bool TMoverParameters::IncBrakeLevel() +{ // nowa wersja na użytek AI, false gdy osiągnięto pozycję BrakeCtrlPosNo + return BrakeLevelAdd(1.0); +}; + +bool TMoverParameters::DecBrakeLevel() +{ + return BrakeLevelAdd(-1.0); +}; // nowa wersja na użytek AI, false gdy osiągnięto pozycję -1 + +bool TMoverParameters::ChangeCab(int direction) +{ // zmiana kabiny i resetowanie ustawien + if (abs(ActiveCab + direction) < 2) + { + // if (ActiveCab+direction=0) then LastCab:=ActiveCab; + ActiveCab = ActiveCab + direction; + if ((BrakeSystem == Pneumatic) && (BrakeCtrlPosNo > 0)) + { + // if (BrakeHandle==FV4a) //!!!POBIERAĆ WARTOŚĆ Z KLASY ZAWORU!!! + // BrakeLevelSet(-2); //BrakeCtrlPos=-2; + // else if ((BrakeHandle==FVel6)||(BrakeHandle==St113)) + // BrakeLevelSet(2); + // else + // BrakeLevelSet(1); + BrakeLevelSet(Handle->GetPos(bh_NP)); + LimPipePress = PipePress; + ActFlowSpeed = 0; + } + else + // if (TrainType=dt_EZT) and (BrakeCtrlPosNo>0) then + // BrakeCtrlPos:=5; //z Megapacka + // else + // BrakeLevelSet(0); //BrakeCtrlPos=0; + BrakeLevelSet(Handle->GetPos(bh_NP)); + // if not TestFlag(BrakeStatus,b_dmg) then + // BrakeStatus:=b_off; //z Megapacka + MainCtrlPos = 0; + ScndCtrlPos = 0; + // Ra: to poniżej jest bez sensu - można przejść nie wyłączając + // if ((EngineType!=DieselEngine)&&(EngineType!=DieselElectric)) + //{ + // Mains=false; + // CompressorAllow=false; + // ConverterAllow=false; + //} + // ActiveDir=0; + // DirAbsolute=0; + return true; + } + return false; +}; + +bool TMoverParameters::CurrentSwitch(int direction) +{ // rozruch wysoki (true) albo niski (false) + // Ra: przeniosłem z Train.cpp, nie wiem czy ma to sens + if (MaxCurrentSwitch(direction)) + { + if (TrainType != dt_EZT) + return (MinCurrentSwitch(direction)); + } + if (EngineType == DieselEngine) // dla 2Ls150 + if (ShuntModeAllow) + if (ActiveDir == 0) // przed ustawieniem kierunku + ShuntMode = direction; + return false; +}; + +void TMoverParameters::UpdatePantVolume(double dt) +{ // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze + // nie tak + if (EnginePowerSource.SourceType == CurrentCollector) // tylko jeśli pantografujący + { + // Ra 2014-07: zasadniczo, to istnieje zbiornik rozrządu i zbiornik pantografów - na razie + // mamy razem + // Ra 2014-07: kurek trójdrogowy łączy spr.pom. z pantografami i wyłącznikiem ciśnieniowym + // WS + // Ra 2014-07: zbiornika rozrządu nie pompuje się tu, tylko pantografy; potem można zamknąć + // WS i odpalić resztę + if ((TrainType == dt_EZT) ? (PantPress < ScndPipePress) : + bPantKurek3) // kurek zamyka połączenie z ZG + { // zbiornik pantografu połączony ze zbiornikiem głównym - małą sprężarką się tego nie + // napompuje + // Ra 2013-12: Niebugocław mówi, że w EZT nie ma potrzeby odcinać kurkiem + PantPress = EnginePowerSource.CollectorParameters + .MaxPress; // ograniczenie ciśnienia do MaxPress (tylko w pantografach!) + if (PantPress > ScndPipePress) + PantPress = ScndPipePress; // oraz do ScndPipePress + PantVolume = (PantPress + 1) * 0.1; // objętość, na wypadek odcięcia kurkiem + } + else + { // zbiornik główny odcięty, można pompować pantografy + if (PantCompFlag && Battery) // włączona bateria i mała sprężarka + PantVolume += dt * (TrainType == dt_EZT ? 0.003 : 0.005) * + (2 * 0.45 - ((0.1 / PantVolume / 10) - 0.1)) / + 0.45; // napełnianie zbiornika pantografów + // Ra 2013-12: Niebugocław mówi, że w EZT nabija 1.5 raz wolniej niż jak było 0.005 + PantPress = (10.0 * PantVolume) - 1.0; // tu by się przydała objętość zbiornika + } + if (!PantCompFlag && (PantVolume > 0.1)) + PantVolume -= dt * 0.0003; // nieszczelności: 0.0003=0.3l/s + if (Mains) // nie wchodzić w funkcję bez potrzeby + if (EngineType == ElectricSeriesMotor) // nie dotyczy... czego właściwie? + if (PantPress < EnginePowerSource.CollectorParameters.MinPress) + if ((TrainType & (dt_EZT | dt_ET40 | dt_ET41 | dt_ET42)) ? + (GetTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV) : + true) // to jest trochę proteza; zasilanie członu może być przez sprzęg + // WN + if (MainSwitch(false)) + EventFlag = true; // wywalenie szybkiego z powodu niskiego ciśnienia + if (TrainType != dt_EZT) // w EN57 pompuje się tylko w silnikowym + // pierwotnie w CHK pantografy miały również rozrządcze EZT + for (int b = 0; b <= 1; ++b) + if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) + if (Couplers[b].Connected->PantVolume < + PantVolume) // bo inaczej trzeba w obydwu członach przestawiać + Couplers[b].Connected->PantVolume = + PantVolume; // przekazanie ciśnienia do sąsiedniego członu + // czy np. w ET40, ET41, ET42 pantografy członów mają połączenie pneumatyczne? + // Ra 2014-07: raczej nie - najpierw się załącza jeden człon, a potem można podnieść w + // drugim + } + else + { // a tu coś dla SM42 i SM31, aby pokazywać na manometrze + PantPress = CntrlPipePress; + } +}; + +void TMoverParameters::UpdateBatteryVoltage(double dt) +{ // przeliczenie obciążenia baterii + double sn1, sn2, sn3, sn4, sn5; // Ra: zrobić z tego amperomierz NN + if ((BatteryVoltage > 0) && (EngineType != DieselEngine) && (EngineType != WheelsDriven) && + (NominalBatteryVoltage > 0)) + { + if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery) + { // 110V + if (!ConverterFlag) + sn1 = (dt * 2.0); // szybki spadek do ok 90V + else + sn1 = 0; + if (ConverterFlag) + sn2 = -(dt * 2.0); // szybki wzrost do 110V + else + sn2 = 0; + if (Mains) + sn3 = (dt * 0.05); + else + sn3 = 0; + if (iLights[0] & 63) // 64=blachy, nie ciągną prądu //rozpisać na poszczególne + // żarówki... + sn4 = dt * 0.003; + else + sn4 = 0; + if (iLights[1] & 63) // 64=blachy, nie ciągną prądu + sn5 = dt * 0.001; + else + sn5 = 0; + }; + if ((NominalBatteryVoltage / BatteryVoltage >= 1.22) && Battery) + { // 90V + if (PantCompFlag) + sn1 = (dt * 0.0046); + else + sn1 = 0; + if (ConverterFlag) + sn2 = -(dt * 50); // szybki wzrost do 110V + else + sn2 = 0; + if (Mains) + sn3 = (dt * 0.001); + else + sn3 = 0; + if (iLights[0] & 63) // 64=blachy, nie ciągną prądu + sn4 = (dt * 0.0030); + else + sn4 = 0; + if (iLights[1] & 63) // 64=blachy, nie ciągną prądu + sn5 = (dt * 0.0010); + else + sn5 = 0; + }; + if (!Battery) + { + if (NominalBatteryVoltage / BatteryVoltage < 1.22) + sn1 = dt * 50; + else + sn1 = 0; + sn2 = dt * 0.000001; + sn3 = dt * 0.000001; + sn4 = dt * 0.000001; + sn5 = dt * 0.000001; // bardzo powolny spadek przy wyłączonych bateriach + }; + BatteryVoltage -= (sn1 + sn2 + sn3 + sn4 + sn5); + if (NominalBatteryVoltage / BatteryVoltage > 1.57) + if (MainSwitch(false) && (EngineType != DieselEngine) && (EngineType != WheelsDriven)) + EventFlag = true; // wywalanie szybkiego z powodu zbyt niskiego napiecia + if (BatteryVoltage > NominalBatteryVoltage) + BatteryVoltage = NominalBatteryVoltage; // wstrzymanie ładowania pow. 110V + if (BatteryVoltage < 0.01) + BatteryVoltage = 0.01; + } + else if (NominalBatteryVoltage == 0) + BatteryVoltage = 0; + else + BatteryVoltage = 90; +}; + +/* Ukrotnienie EN57: +1 //układ szeregowy +2 //układ równoległy +3 //bocznik 1 +4 //bocznik 2 +5 //bocznik 3 +6 //do przodu +7 //do tyłu +8 //1 przyspieszenie +9 //minus obw. 2 przyspieszenia +10 //jazda na oporach +11 //SHP +12A //podnoszenie pantografu przedniego +12B //podnoszenie pantografu tylnego +13A //opuszczanie pantografu przedniego +13B //opuszczanie wszystkich pantografów +14 //załączenie WS +15 //rozrząd (WS, PSR, wał kułakowy) +16 //odblok PN +18 //sygnalizacja przetwornicy głównej +19 //luzowanie EP +20 //hamowanie EP +21 //rezerwa** (1900+: zamykanie drzwi prawych) +22 //zał. przetwornicy głównej +23 //wył. przetwornicy głównej +24 //zał. przetw. oświetlenia +25 //wył. przetwornicy oświetlenia +26 //sygnalizacja WS +28 //sprężarka +29 //ogrzewanie +30 //rezerwa* (1900+: zamykanie drzwi lewych) +31 //otwieranie drzwi prawych +32H //zadziałanie PN siln. trakcyjnych +33 //sygnał odjazdu +34 //rezerwa (sygnalizacja poślizgu) +35 //otwieranie drzwi lewych +ZN //masa +*/ + + +// ***************************************************************************** +// Q: 20160714 +// ***************************************************************************** +double TMoverParameters::LocalBrakeRatio(void) +{ +double LBR; + + if (Hamulce::LocalBrakePosNo > 0) + LBR = LocalBrakePos / Hamulce::LocalBrakePosNo; + else + LBR = 0; +// if (TestFlag(BrakeStatus, b_antislip)) +// LBR = Max0R(LBR, PipeRatio) + 0.4; + return LBR; +} + + +// ***************************************************************************** +// Q: 20160714 +// ***************************************************************************** +double TMoverParameters::ManualBrakeRatio(void) +{ + double MBR; + + if (ManualBrakePosNo > 0) + MBR = ManualBrakePos / ManualBrakePosNo; + else + MBR = 0; + return MBR; +} + + +// ***************************************************************************** +// Q: 20160713 +// ***************************************************************************** +double TMoverParameters::BrakeVP(void) +{ + if (BrakeVVolume > 0) + return Volume / (10.0 * BrakeVVolume); + else return 0; +} + + +// ***************************************************************************** +// Q: 20160713 +// ***************************************************************************** + +double TMoverParameters::RealPipeRatio(void) +{ + double rpp; + + if (DeltaPipePress > 0) + rpp = (CntrlPipePress - PipePress) / (DeltaPipePress); + else + rpp = 0; + return rpp; +} + + +// ***************************************************************************** +// Q: 20160713 +// ***************************************************************************** +double TMoverParameters::PipeRatio(void) +{ + double pr; + + if (DeltaPipePress > 0) + if (false) //SPKS!! + { + if ((3 * PipePress) > (HighPipePress + LowPipePress + LowPipePress)) + 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 + } + else + pr = (HighPipePress - Max0R(LowPipePress, Min0R(HighPipePress, PipePress))) / DeltaPipePress; + else + pr = 0; + return pr; +} + + + +// ************************************************************************************************* +// Q: 20160716 +// ************************************************************************************************* +void TMoverParameters::CollisionDetect(Byte CouplerN, double dt) +{ + double CCF,Vprev,VprevC; + bool VirtualCoupling; + + CCF = 0; +// with Couplers[CouplerN] do + if (Couplers[CouplerN].Connected != NULL) + { + VirtualCoupling = (Couplers[CouplerN].CouplingFlag == ctrain_virtual); + Vprev = V; + VprevC = Couplers[CouplerN].Connected->V; + switch (CouplerN) + { + case 0 : CCF = ComputeCollision(V, Couplers[CouplerN].Connected->V, TotalMass, Couplers[CouplerN].Connected->TotalMass, (Couplers[CouplerN].beta + Couplers[CouplerN].Connected->Couplers[Couplers[CouplerN].ConnectedNr].beta) / 2.0, VirtualCoupling) / (dt); break;//yB: ej ej ej, a po + case 1 : CCF = ComputeCollision(Couplers[CouplerN].Connected->V, V, Couplers[CouplerN].Connected->TotalMass, TotalMass, (Couplers[CouplerN].beta + Couplers[CouplerN].Connected->Couplers[Couplers[CouplerN].ConnectedNr].beta) / 2.0, VirtualCoupling) / (dt); break;//czemu tu jest +0.01?? + } + AccS = AccS + (V - Vprev) / dt; //korekta przyspieszenia o siły wynikające ze zderzeń? + Couplers[CouplerN].Connected->AccS = Couplers[CouplerN].Connected->AccS + (Couplers[CouplerN].Connected->V - VprevC) / dt; + if ((Couplers[CouplerN].Dist > 0) && (!VirtualCoupling)) + if (FuzzyLogic(abs(CCF), 5 * (Couplers[CouplerN].FmaxC + 1), p_coupldmg)) + { //! zerwanie sprzegu + if (SetFlag(DamageFlag,dtrain_coupling)) + EventFlag = true; + + if ((Couplers[CouplerN].CouplingFlag && ctrain_pneumatic>0)) + EmergencyBrakeFlag = true; //hamowanie nagle - zerwanie przewodow hamulcowych + Couplers[CouplerN].CouplingFlag = 0; + + switch (CouplerN) //wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone + { + case 0 : Couplers[CouplerN].Connected->Couplers[1].CouplingFlag = 0; break; + case 1 : Couplers[CouplerN].Connected->Couplers[0].CouplingFlag = 0; break; + } + } + } +} + +double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot) +{ + const Vepsilon = 1e-5; + const Aepsilon = 1e-3; //ASBSpeed=0.8; + Byte b; + double Vprev, AccSprev, d; + +// T_MoverParameters::ComputeMovement(dt, dt1, Shape, Track, ElectricTraction, NewLoc, NewRot); // najpierw kawalek z funkcji w pliku mover.pas + + ClearPendingExceptions; // ma byc + + if (!TestFlag(DamageFlag, dtrain_out)) + { //Ra: to przepisywanie tu jest bez sensu + RunningShape = Shape; + RunningTrack = Track; + RunningTraction = ElectricTraction; + + if (!DynamicBrakeFlag) + RunningTraction.TractionVoltage = ElectricTraction.TractionVoltage-abs(ElectricTraction.TractionResistivity*(Itot+HVCouplers[0][0]+HVCouplers[1][0])); + else + RunningTraction.TractionVoltage = ElectricTraction.TractionVoltage-abs(ElectricTraction.TractionResistivity*Itot*0); //zasadniczo ED oporowe nie zmienia napięcia w sieci + } + + if (CategoryFlag == 4) + OffsetTrackV = TotalMass / (Dim.L * Dim.W * 1000.0); + else + if (TestFlag(CategoryFlag, 1) && TestFlag(RunningTrack.CategoryFlag, 1)) + if (TestFlag(DamageFlag, dtrain_out)) + { + OffsetTrackV = -0.2; + OffsetTrackH = Sign(RunningShape.R) * 0.2; + } + + Loc = NewLoc; + Rot = NewRot; + NewRot.Rx = 0; NewRot.Ry = 0; NewRot.Rz = 0; + + if (dL == 0) //oblicz przesuniecie} + { + 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)) + AccS =-Sign(V) * g * 1; // random(0.0, 0.1) + + //przyspieszenie normalne + if (abs(Shape.R) > 0.01) + AccN = sqr(V) / Shape.R + g * Shape.dHrail / TrackW; //Q: zamieniam SQR() na sqr() + else AccN = g * Shape.dHrail / TrackW; + + //szarpanie + if (FuzzyLogic((10+Track.DamageFlag)*Mass*Vel/Vmax,500000,p_accn)) //Ra: czemu tu masa bez ładunku? + AccV = sqrt((1+Track.DamageFlag)*random(Trunc(50*Mass/1000000.0))*Vel/(Vmax*(10+(Track.QualityFlag & 31)))); // TODO: Trunc na floor + else + AccV = AccV/2.0; + + if (AccV > 1.0) + AccN = AccN + (7 - random(2)) * (100.0 + Track.DamageFlag / 2.0) * AccV / 2000.0; + + //wykolejanie na luku oraz z braku szyn + if (TestFlag(CategoryFlag,1)) + { + if (FuzzyLogic((AccN / g) * (1 + 0.1 * (Track.DamageFlag && dtrack_freerail)), TrackW / Dim.H,1) || TestFlag(Track.DamageFlag, dtrack_norail)) + if (SetFlag(DamageFlag, dtrain_out)) + { + EventFlag = true; + Mains = false; + RunningShape.R = 0; + if (TestFlag(Track.DamageFlag, dtrack_norail)) + DerailReason = 1; //Ra: powód wykolejenia: brak szyn + else + DerailReason = 2; //Ra: powód wykolejenia: przewrócony na łuku + } + //wykolejanie na poszerzeniu toru + if (FuzzyLogic(abs(Track.Width - TrackW), TrackW / 10.0,1)) + if (SetFlag(DamageFlag, dtrain_out)) + { + EventFlag = true; + Mains = false; + RunningShape.R = 0; + DerailReason = 3; //Ra: powód wykolejenia: za szeroki tor + } + } + //wykolejanie wkutek niezgodnosci kategorii toru i pojazdu + if (!TestFlag(RunningTrack.CategoryFlag, CategoryFlag)) + if (SetFlag(DamageFlag,dtrain_out)) + { + EventFlag = true; + Mains = false; + DerailReason = 4; //Ra: powód wykolejenia: nieodpowiednia trajektoria + } + + V = V + (3 * AccS - AccSprev) * dt / 2.0; //przyrost predkosci + + if (TestFlag(DamageFlag, dtrain_out)) + if (Vel < 1) + { + V = 0; + AccS = 0; + } + + if ((V*Vprev<=0) && (abs(FStand) > abs(FTrain))) //tlumienie predkosci przy hamowaniu + { //zahamowany + V = 0; + //AccS:=0; //Ra 2014-03: ale siła grawitacji działa, więc nie może być zerowe + } + +// { 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; b < 1; b++) + if (Couplers[b].CheckCollision) + CollisionDetect(b, dt); //zmienia niejawnie AccS, V !!! + + } //liczone dL, predkosc i przyspieszenie + + + if (Power > 1.0) // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich + UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów + + if (EngineType == WheelsDriven) + d = CabNo * dL; // na chwile dla testu + else + d = dL; + DistCounter = DistCounter + fabs(dL) / 1000.0; + dL = 0; + + // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze + + // sprawdzanie i ewentualnie wykonywanie->kasowanie poleceń + if (LoadStatus > 0) // czas doliczamy tylko jeśli trwa (roz)ładowanie + LastLoadChangeTime = LastLoadChangeTime + dt; // czas (roz)ładunku + + RunInternalCommand(); + + // automatyczny rozruch + if (EngineType == ElectricSeriesMotor) + + if (AutoRelayCheck()) + SetFlag(SoundFlag, sound_relay); + + if (EngineType == DieselEngine) + if (dizel_Update(dt)) + SetFlag(SoundFlag, sound_relay); + // uklady hamulcowe: + if (VeselVolume > 0) + Compressor = CompressedVolume / VeselVolume; + else + { + Compressor = 0; + CompressorFlag = false; + }; + ConverterCheck(); + if (CompressorSpeed > 0.0) // sprężarka musi mieć jakąś niezerową wydajność + CompressorCheck(dt); //żeby rozważać jej załączenie i pracę + UpdateBrakePressure(dt); + UpdatePipePressure(dt); + UpdateBatteryVoltage(dt); + UpdateScndPipePressure(dt); // druga rurka, youBy + // hamulec antypoślizgowy - wyłączanie + if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8 + Hamulec->ASB(0); + // SetFlag(BrakeStatus,-b_antislip); + BrakeSlippingTimer = BrakeSlippingTimer + dt; + // sypanie piasku - wyłączone i piasek się nie kończy - błędy AI + // if AIControllFlag then + // if SandDose then + // if Sand>0 then + // begin + // Sand:=Sand-NPoweredAxles*SandSpeed*dt; + // if Random
10) and (not DebugmodeFlag) then + if (!DebugModeFlag) + SecuritySystemCheck(dt1); + return d; +}; + +double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const TLocation &NewLoc, TRotation &NewRot) +{ // trzeba po mału przenosić tu tę funkcję + + double Vprev, AccSprev, d; + Byte b; + // T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot); + + ClearPendingExceptions; // nie bylo + + Loc = NewLoc; + Rot = NewRot; + NewRot.Rx = 0; + NewRot.Ry = 0; + NewRot.Rz = 0; + + if (dL == 0) //oblicz przesuniecie + { + 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)) + AccS = -Sign(V) * g * 1; // * random(0.0, 0.1) + //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)) + { + AccV = sqrt((1+Track.DamageFlag) * random(int(floor(50 * Mass / 1000000.0))) * Vel / (Vmax * (10 + (Track.QualityFlag & 31)))); // Trunc na floor, czy dobrze? + } + else + AccV = AccV / 2.0; + + if (AccV > 1.0) + AccN = AccN + (7 - random(2)) * (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)) + if (Vel < 1) + { + V = 0; + AccS = 0; //Ra 2014-03: ale siła grawitacji działa, więc nie może być zerowe + } + + if ((V * Vprev <= 0) && (abs(FStand) > abs(FTrain))) //tlumienie predkosci przy hamowaniu + { //zahamowany} + V = 0; + AccS = 0; + } + dL = (3 * V - Vprev) * dt / 2.0; //metoda Adamsa-Bashfortha + //ale jesli jest kolizja (zas. zach. pedu) to... + for (b = 0; b < 1; b++) + if (Couplers[b].CheckCollision) + CollisionDetect(b,dt); //zmienia niejawnie AccS, V !!! + } //liczone dL, predkosc i przyspieszenie +//QQQ + + if (Power > 1.0) // w rozrządczym nie (jest błąd w FIZ!) + UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów + if (EngineType == WheelsDriven) + d = CabNo * dL; // na chwile dla testu + else + d = dL; + DistCounter = DistCounter + fabs(dL) / 1000.0; + dL = 0; + + // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze + + // sprawdzanie i ewentualnie wykonywanie->kasowanie poleceń + if (LoadStatus > 0) // czas doliczamy tylko jeśli trwa (roz)ładowanie + LastLoadChangeTime = LastLoadChangeTime + dt; // czas (roz)ładunku + + RunInternalCommand(); + + if (EngineType == DieselEngine) + if (dizel_Update(dt)) + SetFlag(SoundFlag, sound_relay); + // uklady hamulcowe: + if (VeselVolume > 0) + Compressor = CompressedVolume / VeselVolume; + else + { + Compressor = 0; + CompressorFlag = false; + }; + ConverterCheck(); + if (CompressorSpeed > 0.0) // sprężarka musi mieć jakąś niezerową wydajność + CompressorCheck(dt); //żeby rozważać jej załączenie i pracę + UpdateBrakePressure(dt); + UpdatePipePressure(dt); + UpdateScndPipePressure(dt); // druga rurka, youBy + UpdateBatteryVoltage(dt); + // hamulec antyposlizgowy - wyłączanie + if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8 + Hamulec->ASB(0); + BrakeSlippingTimer = BrakeSlippingTimer + dt; + return d; +}; + + + +double TMoverParameters::ShowEngineRotation(int VehN) +{ // pokazywanie obrotów silnika, również dwóch dalszych pojazdów (3×SN61) + int b; + switch (VehN) + { // numer obrotomierza + case 1: + return fabs(enrot); + case 2: + for (b = 0; b <= 1; ++b) + if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) + if (Couplers[b].Connected->Power > 0.01) + return fabs(Couplers[b].Connected->enrot); + break; + case 3: // to nie uwzględnia ewentualnego odwrócenia pojazdu w środku + for (b = 0; b <= 1; ++b) + if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) + if (Couplers[b].Connected->Power > 0.01) + if (TestFlag(Couplers[b].Connected->Couplers[b].CouplingFlag, ctrain_controll)) + if (Couplers[b].Connected->Couplers[b].Connected->Power > 0.01) + return fabs(Couplers[b].Connected->Couplers[b].Connected->enrot); + break; + }; + return 0.0; +}; + +void TMoverParameters::ConverterCheck() +{ // sprawdzanie przetwornicy + if (ConverterAllow && Mains) + ConverterFlag = true; + else + ConverterFlag = false; +}; + +int TMoverParameters::ShowCurrent(Byte AmpN) +{ // odczyt amperażu + switch (EngineType) + { + case ElectricInductionMotor: + switch (AmpN) + { // do asynchronicznych + case 1: + return WindingRes * Mm / Vadd; + case 2: + return dizel_fill * WindingRes; + default: + return ShowCurrentP(AmpN); //T_MoverParameters:: + } + break; + case DieselElectric: + return fabs(Im); + break; + default: + return ShowCurrentP(AmpN); //T_MoverParameters:: + } +}; + + +// ************************************************************************************************* +// queuedEU +// ************************************************************************************************* + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* + +bool TMoverParameters::IncMainCtrl(int CtrlSpeed) +{ + bool OK = false; + if ((MainCtrlPosNo > 0) && (CabNo != 0)) + { + if (MainCtrlPos < MainCtrlPosNo) + { + if ( (TrainType != dt_ET22) || ((TrainType == dt_ET22) && (ScndCtrlPos == 0)) ) //w ET22 nie da się kręcić nastawnikiem przy włączonym boczniku + switch (EngineType ) + { + case None: + case Dumb: + case DieselElectric: + case ElectricInductionMotor: + { + if ( ((CtrlSpeed == 1) && (TrainType != dt_EZT)) || ((CtrlSpeed == 1) && (TrainType == dt_EZT) && (ActiveDir != 0)) ) + { //w EZT nie da się załączyć pozycji bez ustawienia kierunku + MainCtrlPos++; + OK = true; + } + else + if (((CtrlSpeed > 1) && (TrainType != dt_EZT)) || ((CtrlSpeed > 1) && (TrainType == dt_EZT) && (ActiveDir != 0))) + OK = (IncMainCtrl(1) && IncMainCtrl(CtrlSpeed - 1)); + break; + }; + + case ElectricSeriesMotor: + { + if ((CtrlSpeed == 1) && (ActiveDir != 0)) + { + MainCtrlPos++; + OK = true; + if (Imax == ImaxHi) + if (RList[MainCtrlPos].Bn > 1) + { + if(TrainType == dt_ET42) + { + MainCtrlPos--; + OK = false; + } + if (MaxCurrentSwitch(false)) + SetFlag(SoundFlag, sound_relay); //wylaczanie wysokiego rozruchu // Q TODO: +// if (EngineType=ElectricSeriesMotor) and (MainCtrlPos=1) then +// MainCtrlActualPos:=1; +// + } + if ((CtrlSpeed == 1) && (ActiveDir == -1) && (RList[MainCtrlPos].Bn > 1) && (TrainType != dt_PseudoDiesel)) + { //blokada wejścia na równoległą podczas jazdy do tyłu + MainCtrlPos--; + OK = false; + } + // + // if (TrainType == "et40") + // if (Abs(Im) > IminHi) + // { + // MainCtrlPos--; //Blokada nastawnika po przekroczeniu minimalnego pradu + // OK = false; + // } + //} + if(DynamicBrakeFlag) + if(TrainType == dt_ET42) + if (MainCtrlPos > 20) + { + MainCtrlPos--; + OK = false; + } + } + else + if ((CtrlSpeed > 1) && (ActiveDir != 0) && (TrainType != dt_ET40)) + { //szybkie przejście na bezoporową + + while ((RList[MainCtrlPos].R > 0) && IncMainCtrl(1)) + + //OK:=true ; {takie chamskie, potem poprawie} <-Ra: kto miał to poprawić i po co? + if (ActiveDir == -1) + while ((RList[MainCtrlPos].Bn > 1) && IncMainCtrl(1)) + MainCtrlPos--; + OK = false; + //if (TrainType=dt_ET40) then + // while Abs (Im)>IminHi do + // dec(MainCtrlPos); + // OK:=false ; + // + if(DynamicBrakeFlag) + if(TrainType == dt_ET42) + while(MainCtrlPos > 20) + MainCtrlPos--; + OK = false; + + } + // return OK; + + break; + }; + + case DieselEngine: + { + if (CtrlSpeed == 1) + { + MainCtrlPos++; + OK = true; + if (MainCtrlPos > 0) + CompressorAllow = true; + else + CompressorAllow = false; + + } + else + if (CtrlSpeed > 1) + { + while (MainCtrlPos < MainCtrlPosNo) + IncMainCtrl(1); + OK = true; + } + break; + }; + + case WheelsDriven: + { + OK = AddPulseForce(CtrlSpeed); + break; + }; + + } //switch EngineType of + } + else //MainCtrlPos>=MainCtrlPosNo + if (CoupledCtrl) //wspólny wał nastawnika jazdy i bocznikowania + { + if (ScndCtrlPos < ScndCtrlPosNo) //3<3 -> false + { + ScndCtrlPos++; + OK = true; + } + else OK = false; + } + if (OK) + { + SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //??? + SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo); + } + } + 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) + { + if (DelayCtrlFlag) + { + if ((LastRelayTime >= InitialCtrlDelay) && (MainCtrlPos == 1)) + LastRelayTime = 0; + } + else if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + } + return OK; +} + + +// ***************************************************************************** +// Q: 20160710 +// ***************************************************************************** +bool TMoverParameters::DecMainCtrl(int CtrlSpeed) +{ + bool OK = false; + if ((MainCtrlPosNo > 0) && (CabNo != 0)) + { + if (MainCtrlPos > 0) + { + if ((TrainType != dt_ET22) || (ScndCtrlPos == 0)) //Ra: ET22 blokuje nastawnik przy boczniku + { + if (CoupledCtrl && (ScndCtrlPos > 0)) + { + ScndCtrlPos--; //wspolny wal + OK = true; + } + else + switch (EngineType) + { + case None: + case Dumb: + case DieselElectric: + case ElectricInductionMotor: + { + if (((CtrlSpeed == 1) && /*(ScndCtrlPos==0) and*/ (EngineType != DieselElectric)) || ((CtrlSpeed == 1) && (EngineType == DieselElectric))) + { + MainCtrlPos--; + OK = true; + } + else + if (CtrlSpeed > 1) + OK = (DecMainCtrl(1) && DecMainCtrl(2)); //CtrlSpeed-1); + break; + } + + case ElectricSeriesMotor: + { + if (CtrlSpeed == 1) /*and (ScndCtrlPos=0)*/ + { + 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; + } + else + if (CtrlSpeed > 1) /*and (ScndCtrlPos=0)*/ + { + OK = true; + if (RList[MainCtrlPos].R == 0) //Q: tu zrobilem = ;] + DecMainCtrl(1); + while ((RList[MainCtrlPos].R > 0) && DecMainCtrl(1)); //takie chamskie, potem poprawie} + } + break; + } + + case DieselEngine: + { + if (CtrlSpeed == 1) + { + MainCtrlPos--; + OK = true; + } + else + if (CtrlSpeed > 1) + { + while ((MainCtrlPos > 0) || (RList[MainCtrlPos].Mn > 0)) + DecMainCtrl(1); + OK = true; + } + break; + } + } // switch EngineType + } + } + else + if (EngineType == WheelsDriven) + OK = AddPulseForce(-CtrlSpeed); + else + OK = false; + + if (OK) + { + /*OK:=*/ SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //hmmmm...???!!! + /*OK:=*/ SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo); + } + } + else + OK = false; + //if OK then LastRelayTime:=0; + //hunter-101012: poprawka + if (OK) + { + if (DelayCtrlFlag) + { + if (LastRelayTime >= InitialCtrlDelay) + LastRelayTime = 0; + } + else if (LastRelayTime > CtrlDownDelay) + LastRelayTime = 0; + } + return OK; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::IncScndCtrl(int CtrlSpeed) +{ +bool OK = false; + + if ((MainCtrlPos == 0) && (CabNo != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) &&(DynamicBrakeFlag)) + { + OK = DynamicBrakeSwitch(false); + } + else + if ((ScndCtrlPosNo > 0) && (CabNo != 0) && !((TrainType == dt_ET42) && ((Imax==ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPos > 0)) )) ) + { +// if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos 1) + { + ScndCtrlPos = ScndCtrlPosNo; //takie chamskie, potem poprawie + } + OK = true; + } + else //nie mozna zmienic + OK = false; + if (OK) + { + /*OK:=*/ SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //??? + /*OK:=*/ SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo); + } + } + else //nie ma sterowania + OK = false; + //if OK then LastRelayTime:=0; + //hunter-101012: poprawka + if (OK) + if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + + return OK; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::DecScndCtrl(int CtrlSpeed) +{ + bool OK = false; + + if ((MainCtrlPos == 0) && (CabNo != 0) && (TrainType == dt_ET42) && (ScndCtrlPos ==0) && !(DynamicBrakeFlag) && (CtrlSpeed == 1) ) + { + //Ra: AI wywołuje z CtrlSpeed=2 albo gdy ScndCtrlPos>0 + OK = DynamicBrakeSwitch(true); + } + else + if ((ScndCtrlPosNo > 0) && (CabNo != 0)) + { + if ((ScndCtrlPos > 0) && (!CoupledCtrl) && ((EngineType != DieselElectric) || (!AutoRelayFlag)) ) + { + if (CtrlSpeed == 1) + { + ScndCtrlPos--; + } + else + if (CtrlSpeed > 1) + { + ScndCtrlPos = 0; //takie chamskie, potem poprawie + } + OK = true; + } + else + OK = false; + if (OK) + { + /*OK:=*/ SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //??? + /*OK:=*/ SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo); + } + } + else + OK = false; + //if OK then LastRelayTime:=0; + //hunter-101012: poprawka + if (OK) + if (LastRelayTime > CtrlDownDelay) + LastRelayTime = 0; + + return OK; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::CabActivisation(void) //załączenie rozrządu +{ + bool OK = false; + + OK = (CabNo == 0); //numer kabiny, z której jest sterowanie + if (OK) + { + CabNo = ActiveCab; //sterowanie jest z kabiny z obsadą + DirAbsolute = ActiveDir * CabNo; + SendCtrlToNext("CabActivisation", 1, CabNo); + } + return OK; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::CabDeactivisation(void) //wyłączenie rozrządu +{ + bool OK = false; + + OK = (CabNo == ActiveCab); //o ile obsada jest w kabinie ze sterowaniem + if (OK) + { + CabNo = 0; + DirAbsolute = ActiveDir * CabNo; + DepartureSignal = false; //nie buczeć z nieaktywnej kabiny + SendCtrlToNext("CabActivisation", 0, ActiveCab); //CabNo==0! + } + return OK; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::AddPulseForce(int Multipler) +{ + bool APF; + if ((EngineType == WheelsDriven) && (EnginePowerSource.SourceType == InternalSource) && (EnginePowerSource.PowerType == BioPower)) + { + ActiveDir = CabNo; + DirAbsolute = ActiveDir * CabNo; + if (Vel > 0) + PulseForce = Min0R(1000.0 * Power / (abs(V) + 0.1), Ftmax); + else PulseForce = Ftmax; + if (PulseForceCount > 1000.0) + PulseForce = 0; + else + PulseForce = PulseForce * Multipler; + PulseForceCount = PulseForceCount + abs(Multipler); + APF = (PulseForce > 0); + } + else APF = false; + return APF; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::SandDoseOn(void) +{ + bool SDO; + if (SandCapacity > 0) + { + SDO = true; + if (SandDose) + SandDose = false; + else + if (Sand > 0) SandDose = true; + if (CabNo != 0) + SendCtrlToNext("SandDoseOn", 1, CabNo); + } + else + SDO = false; + + return SDO; +} + +void TMoverParameters::SSReset(void) + { + SecuritySystem.SystemTimer = 0; + + if (TestFlag(SecuritySystem.Status, s_aware)) + { + 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; + } + else if (TestFlag(SecuritySystem.Status,s_active)) + { + 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; + } +} + +// ***************************************************************************** +// Q: 20160710 +// ***************************************************************************** +//hunter-091012: rozbicie alarmow, dodanie testu czuwaka +bool TMoverParameters::SecuritySystemReset(void) //zbijanie czuwaka/SHP +{ +//zbijanie czuwaka/SHP +bool SSR = false; + // with SecuritySystem do + if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0)) + { + SSR = true; + if ((TrainType == dt_EZT) || (ActiveDir != 0)) //Ra 2014-03: w EZT nie trzeba ustawiać kierunku + if (!TestFlag(SecuritySystem.Status, s_CAebrake) || !TestFlag(SecuritySystem.Status, s_SHPebrake)) + SSReset(); + //else + // if EmergencyBrakeSwitch(false) then + // Reset; + } + else + SSR = false; +// SendCtrlToNext('SecurityReset',0,CabNo); + return SSR; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +void TMoverParameters::SecuritySystemCheck(double dt) +{ +//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 +//SecuritySystem SS; + + if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) && (Battery)) //Ra: EZT ma teraz czuwak w rozrządczym + { + //CA + if (Vel >= SecuritySystem.AwareMinSpeed) //domyślnie predkość większa od 10% Vmax, albo podanej jawnie w FIZ + { + SecuritySystem.SystemTimer = SecuritySystem.SystemTimer+dt; + if (TestFlag(SecuritySystem.SystemType, 1) && TestFlag(SecuritySystem.Status, s_aware)) //jeśli świeci albo miga + SecuritySystem.SystemSoundCATimer = SecuritySystem.SystemSoundCATimer + dt; + if (TestFlag(SecuritySystem.SystemType, 1) && TestFlag(SecuritySystem.Status, s_CAalarm)) //jeśli buczy + SecuritySystem.SystemBrakeCATimer = SecuritySystem.SystemBrakeCATimer + dt; + if (TestFlag(SecuritySystem.SystemType, 1)) + if ((SecuritySystem.SystemTimer > SecuritySystem.AwareDelay) && (SecuritySystem.AwareDelay >= 0)) //-1 blokuje + if (!SetFlag(SecuritySystem.Status, s_aware)) //juz wlaczony sygnal swietlny + if ((SecuritySystem.SystemSoundCATimer > SecuritySystem.SoundSignalDelay) && (SecuritySystem.SoundSignalDelay >= 0)) + if (!SetFlag(SecuritySystem.Status, s_CAalarm)) //juz wlaczony sygnal dzwiekowy + if ((SecuritySystem.SystemBrakeCATimer > SecuritySystem.EmergencyBrakeDelay) && (SecuritySystem.EmergencyBrakeDelay >= 0)) + SetFlag(SecuritySystem.Status, s_CAebrake); + + + //SHP + if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_active)) //jeśli świeci albo miga + SecuritySystem.SystemSoundSHPTimer = SecuritySystem.SystemSoundSHPTimer + dt; + if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_SHPalarm)) //jeśli buczy + SecuritySystem.SystemBrakeSHPTimer = SecuritySystem.SystemBrakeSHPTimer + dt; + if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_active)) + if ((Vel > SecuritySystem.VelocityAllowed) && (SecuritySystem.VelocityAllowed >= 0)) + SetFlag(SecuritySystem.Status, s_SHPebrake); + else + if (((SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay) && (SecuritySystem.SoundSignalDelay >= 0)) || ((Vel>SecuritySystem.NextVelocityAllowed) && (SecuritySystem.NextVelocityAllowed >= 0)) ) + if (!SetFlag(SecuritySystem.Status, s_SHPalarm)) //juz wlaczony sygnal dzwiekowy} + if ((SecuritySystem.SystemBrakeSHPTimer > SecuritySystem.EmergencyBrakeDelay) && (SecuritySystem.EmergencyBrakeDelay >= 0)) + SetFlag(SecuritySystem.Status, s_SHPebrake); + + } //else SystemTimer:=0; + + //TEST CA + if (TestFlag(SecuritySystem.Status, s_CAtest)) //jeśli świeci albo miga + SecuritySystem.SystemBrakeCATestTimer = SecuritySystem.SystemBrakeCATestTimer+dt; + if (TestFlag(SecuritySystem.SystemType, 1)) + if (TestFlag(SecuritySystem.Status, s_CAtest)) //juz wlaczony sygnal swietlny + if ((SecuritySystem.SystemBrakeCATestTimer > SecuritySystem.EmergencyBrakeDelay) && (SecuritySystem.EmergencyBrakeDelay >= 0)) + 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 + } + else if (!Battery) + { //wyłączenie baterii deaktywuje sprzęt + //SecuritySystem.Status = 0; //deaktywacja czuwaka + } + +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::BatterySwitch(bool State) +{ + bool BS = false; + //Ra: ukrotnienie załączania baterii jest jakąś fikcją... + if (Battery != State) + { + Battery = State; + } + if (Battery == true) SendCtrlToNext("BatterySwitch", 1, CabNo); + else SendCtrlToNext("BatterySwitch", 0, CabNo); + BS = true; + + if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/ + SecuritySystem.Status = (SecuritySystem.Status || s_waiting); //aktywacja czuwaka + else + SecuritySystem.Status = 0; //wyłączenie czuwaka + + return BS; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::EpFuseSwitch(bool State) +{ + if (EpFuse != State) + { + EpFuse = State; + return true; + } + else + return false; +// if (EpFuse == true) SendCtrlToNext("EpFuseSwitch", 1, CabNo) +// else SendCtrlToNext("EpFuseSwitch", 0, CabNo); +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::DirectionBackward(void) +{ +bool DB = false; + if ((ActiveDir == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT)) + if (MinCurrentSwitch(false)) + { + DB = true; // + return DB; // exit; TODO: czy dobrze przetlumaczone? + } + if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos == 0)) + { + if (EngineType == WheelsDriven) + CabNo--; +// else + ActiveDir--; + DirAbsolute = ActiveDir * CabNo; + if (DirAbsolute != 0) + if (Battery) //jeśli bateria jest już załączona + BatterySwitch(true); //to w ten oto durny sposób aktywuje się CA/SHP + DB = true; + SendCtrlToNext("Direction", ActiveDir, CabNo); + } + else + DB = false; + return DB; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::AntiSlippingButton(void) +{ + bool OK = false; + + OK = SandDoseOn(); + return (AntiSlippingBrake() || OK); +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::MainSwitch(bool State) +{ + bool MS = false; + + MS = false; //Ra: przeniesione z końca + if ((Mains != State) && (MainCtrlPosNo > 0)) + { + if ((State == false) || ( (ScndCtrlPos == 0) && (ConvOvldFlag == false) && (LastSwitchingTime > CtrlDelay) && !TestFlag(DamageFlag, dtrain_out) )) + { + if (Mains) //jeśli był załączony + SendCtrlToNext("MainSwitch", int(State), CabNo); //wysłanie wyłączenia do pozostałych? + Mains = State; + if (Mains) //jeśli został załączony + SendCtrlToNext("MainSwitch", int(State), CabNo); //wyslanie po wlaczeniu albo przed wylaczeniem + MS = true; //wartość zwrotna + LastSwitchingTime = 0; + if ((EngineType == DieselEngine) && Mains) + { + dizel_enginestart = State; + } + //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 + } + + } + //else MainSwitch:=false; + return MS; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::ConverterSwitch(bool State) +{ + bool CS = false; //Ra: normalnie chyba false? + if (ConverterAllow != State) + { + ConverterAllow = State; + CS = true; + if (CompressorPower == 2) + CompressorAllow = ConverterAllow; + } + if (ConverterAllow == true) SendCtrlToNext("ConverterSwitch", 1, CabNo); + else SendCtrlToNext("ConverterSwitch", 0, CabNo); + + return CS; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::CompressorSwitch(bool State) +{ + bool CS = 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) && (CompressorPower < 2)) + { + CompressorAllow = State; + CS = true; + } + if (CompressorAllow == true) SendCtrlToNext("CompressorSwitch", 1, CabNo); + else SendCtrlToNext("CompressorSwitch", 0, CabNo); + + return CS; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::IncBrakeLevelOld(void) +{ +bool IBLO = false; + + if ((BrakeCtrlPosNo > 0) /*and (LocalBrakePos=0)*/) + { + if (BrakeCtrlPos < BrakeCtrlPosNo) + { + 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) +// if (BrakePressureActual.BrakeType==ElectroPneumatic) +// { +// BrakeStatus = ord(BrakeCtrlPos > 0); +// SendCtrlToNext("BrakeCtrl", BrakeCtrlPos, CabNo); +// } +// else SendCtrlToNext("BrakeCtrl", -2, CabNo); +// else +// if (!TestFlag(BrakeStatus,b_dmg)) +// BrakeStatus = b_on;} + +//youBy: EP po nowemu + + IBLO = true; + if ((BrakePressureActual.PipePressureVal < 0) && (BrakePressureTable[BrakeCtrlPos-1].PipePressureVal > 0)) + LimPipePress = PipePress; + + if (BrakeSystem == ElectroPneumatic) + if (BrakeSubsystem != ss_K) + { + if ((BrakeCtrlPos * BrakeCtrlPos) == 1) + { +// SendCtrlToNext('Brake',BrakeCtrlPos,CabNo); +// SetFlag(BrakeStatus,b_epused); + } + else + { +// SendCtrlToNext('Brake',0,CabNo); +// SetFlag(BrakeStatus,-b_epused); + } + } + + } + else + { + IBLO = false; +// if (BrakeSystem == Pneumatic) +// EmergencyBrakeSwitch(true); + } + } + else + IBLO = false; + + return IBLO; +} + + +// ***************************************************************************** +// Q: 20160711 +// ***************************************************************************** +bool TMoverParameters::DecBrakeLevelOld(void) +{ +bool DBLO = false; + + if ((BrakeCtrlPosNo > 0) /*&& (LocalBrakePos == 0)*/ ) + { + if (BrakeCtrlPos > -1 - Byte(BrakeHandle == FV4a)) + { + BrakeCtrlPos--; +// BrakeCtrlPosR:=BrakeCtrlPos; + if (EmergencyBrakeFlag) + { + EmergencyBrakeFlag = false; //!!! + SendCtrlToNext("Emergency_brake", 0, CabNo); + } + +//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) + if (BrakePressureActual.BrakeType == ElectroPneumatic) + { +// BrakeStatus =ord(BrakeCtrlPos > 0); + SendCtrlToNext("BrakeCtrl",BrakeCtrlPos,CabNo); + } + 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 + DBLO = true; +// if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) && (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0)) +// LimPipePress:=PipePress; + + if (BrakeSystem == ElectroPneumatic) + if (BrakeSubsystem != ss_K) + { + if ((BrakeCtrlPos * BrakeCtrlPos) == 1) + { +// SendCtrlToNext("Brake", BrakeCtrlPos, CabNo); +// SetFlag(BrakeStatus, b_epused); + } + else + { +// SendCtrlToNext("Brake", 0, CabNo); +// SetFlag(BrakeStatus, -b_epused); + } + } +// for b:=0 to 1 do {poprawic to!} +// with Couplers[b] do +// if CouplingFlag and ctrain_controll=ctrain_controll then +// Connected^.BrakeCtrlPos:=BrakeCtrlPos; +// + } + else + DBLO = false; + } + else + DBLO = false; + + return DBLO; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::IncLocalBrakeLevel(Byte CtrlSpeed) +{ + bool IBL; + if ((LocalBrakePos < Hamulce::LocalBrakePosNo) /*and (BrakeCtrlPos<1)*/ ) + { + while ((LocalBrakePos < Hamulce::LocalBrakePosNo) && (CtrlSpeed > 0)) + { + LocalBrakePos++; + CtrlSpeed--; + } + IBL = true; + } + else + IBL = false; + UnBrake =true; + + return IBL; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::DecLocalBrakeLevel(Byte CtrlSpeed) +{ +bool DBL; + if (LocalBrakePos > 0) + { + while ((CtrlSpeed>0) && (LocalBrakePos > 0)) + { + LocalBrakePos--; + CtrlSpeed--; + } + DBL = true; + } + else + DBL = false; + UnBrake = true; + +return DBL; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::IncLocalBrakeLevelFAST(void) +{ + bool ILBLF; + if (LocalBrakePos < Hamulce::LocalBrakePosNo) + { + LocalBrakePos = Hamulce::LocalBrakePosNo; + ILBLF = true; + } + else + ILBLF = false; + UnBrake = true; + return ILBLF; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::DecLocalBrakeLevelFAST(void) +{ + bool DLBLF; + if (LocalBrakePos > 0) + { + LocalBrakePos = 0; + DLBLF = true; + } + else + DLBLF = false; + UnBrake = true; + return DLBLF; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::IncManualBrakeLevel(Byte CtrlSpeed) +{ +bool IMBL; + if (ManualBrakePos < ManualBrakePosNo) /*and (BrakeCtrlPos<1)*/ + { + while ((ManualBrakePos < ManualBrakePosNo) && (CtrlSpeed > 0)) + { + ManualBrakePos++; + CtrlSpeed--; + } + IMBL = true; + } + else + IMBL = false; + + return IMBL; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::DecManualBrakeLevel(Byte CtrlSpeed) +{ + bool DMBL; + if (ManualBrakePos > 0) + { + while ((CtrlSpeed > 0) && (ManualBrakePos > 0)) + { + ManualBrakePos--; + CtrlSpeed--; + } + DMBL = true; + } + else + DMBL = false; + return DMBL; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::DynamicBrakeSwitch(bool Switch) +{ + Byte b; + bool DBS; + + if ((DynamicBrakeType == dbrake_switch) && (MainCtrlPos == 0)) + { + DynamicBrakeFlag = Switch; + DBS = true; + for (b = 0; b < 1; b++) + // with Couplers[b] do + if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll) ) + Couplers[b].Connected->DynamicBrakeFlag = DynamicBrakeFlag; + //end; + //if (DynamicBrakeType=dbrake_passive) and (TrainType=dt_ET42) then + //begin + //DynamicBrakeFlag:=false; + //DynamicBrakeSwitch:=false; + } + else + DBS = false; + + return DBS; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::EmergencyBrakeSwitch(bool Switch) +{ + bool EBS; + if ((BrakeSystem != Individual) && (BrakeCtrlPosNo > 0)) + { + if ((!EmergencyBrakeFlag) && Switch) + { + EmergencyBrakeFlag = Switch; + EBS = true; + } + else + { + if ((abs(V)<0.1) && (Switch == false)) //odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu + { + EmergencyBrakeFlag = Switch; + EBS = true; + } + else + EBS = false; + } + } + else + EBS = false; //nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp. + + return EBS; +} + + +// ************************************************************************************************* +// Q: 20160710 +// ************************************************************************************************* +bool TMoverParameters::AntiSlippingBrake(void) +{ + bool ASB = false; //Ra: przeniesione z końca + if (ASBType == 1) + { + ASB = true; //SPKS!! + Hamulec->ASB(1); + BrakeSlippingTimer = 0; + } + return ASB; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::BrakeReleaser(Byte state) +{ +bool OK; + Hamulec->Releaser(state); + if (CabNo != 0) //rekurencyjne wysłanie do następnego + OK = SendCtrlToNext("BrakeReleaser", state, CabNo); + return OK; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::SwitchEPBrake(Byte state) +{ + bool OK; + double temp; + + OK = false; + if ((BrakeHandle == St113) && (ActiveCab != 0)) + { + //if(state > 0) + // temp = (Handle as TSt113).GetCP // TODO: przetlumaczyc + //else + temp = 0; + Hamulec->SetEPS(temp); + SendCtrlToNext("Brake", temp, CabNo); + } +// OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused)); +// SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabNo); + return OK; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::IncBrakePress(double &brake, double PressLimit, double dp) +{ + bool IBP; +// if (DynamicBrakeType<>dbrake_switch) and (DynamicBrakeType<>dbrake_none) and ((BrakePress>2.0) or (PipePress<3.7{(LowPipePress+0.5)})) then + if ((DynamicBrakeType != dbrake_switch) && (DynamicBrakeType != dbrake_none) && (BrakePress > 2.0) && (TrainType != dt_EZT)) //yB radzi nie sprawdzać ciśnienia w przewodzie + //hunter-301211: dla EN57 silnikow nie odlaczamy + { + DynamicBrakeFlag = true; //uruchamianie hamulca ED albo odlaczanie silnikow + if ((DynamicBrakeType == dbrake_automatic) && (abs(Im) > 60)) //nie napelniaj wiecej, jak na EP09 + dp = 0.0; + } + if (brake + dp < PressLimit) + { + brake = brake + dp; + IBP = true; + } + else + { + IBP = false; + brake = PressLimit; + } + return IBP; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::DecBrakePress(double &brake, double PressLimit, double dp) +{ + bool DBP; + + if (brake-dp > PressLimit) + { + brake = brake - dp; + DBP = true; + } + else + { + DBP = false; + brake = PressLimit; + } +// if ((DynamicBrakeType != dbrake_switch) && ((BrakePress < 0.1) && (PipePress > 0.45 /*(LowPipePress+0.06)*/ ))) + if ((DynamicBrakeType != dbrake_switch) && (BrakePress < 0.1)) //yB radzi nie sprawdzać ciśnienia w przewodzie + DynamicBrakeFlag = false; //wylaczanie hamulca ED i/albo zalaczanie silnikow + + return DBP; +} + + +// ************************************************************************************************* +// Q: 20160711 +// ************************************************************************************************* +bool TMoverParameters::BrakeDelaySwitch(Byte BDS) +{ + bool rBDS; +// if (BrakeCtrlPosNo > 0) + if (Hamulec->SetBDF(BDS)) + { + BrakeDelayFlag = BDS; + rBDS = true; + BrakeStatus = (BrakeStatus & 191); + //kopowanie nastawy hamulca do kolejnego czlonu - do przemyślenia + if (CabNo != 0) + SendCtrlToNext("BrakeDelay", BrakeDelayFlag, CabNo); + } + else + rBDS = false; + return rBDS; +} + + +// ************************************************************************************************* +// Q: 20160712 +// ************************************************************************************************* +bool TMoverParameters::IncBrakeMult(void) +{ +bool IBM; + + if ((LoadFlag > 0) && (MBPM < 2) && (LoadFlag < 3)) + { + if ((MaxBrakePress[2] > 0) && (LoadFlag == 1)) + LoadFlag = 2; + else + LoadFlag = 3; + IBM = true; + if (BrakeCylMult[2] > 0) BrakeCylMult[0] = BrakeCylMult[2]; + } + else + IBM = false; + + return IBM; +} + + +// ************************************************************************************************* +// Q: 20160712 +// ************************************************************************************************* +bool TMoverParameters::DecBrakeMult(void) +{ + bool DBM; + if ((LoadFlag > 1) && (MBPM < 2)) + { + if ((MaxBrakePress[2] > 0) && (LoadFlag == 3)) + LoadFlag = 2; + else + LoadFlag = 1; + DBM = true; + if (BrakeCylMult[1] > 0) BrakeCylMult[0] = BrakeCylMult[1]; + } + else + DBM = false; + + return DBM; +} + + +// ************************************************************************************************* +// Q: 20160712 +// ************************************************************************************************* +void TMoverParameters::UpdateBrakePressure(double dt) +{ +const LBDelay = 5.0; //stala czasowa hamulca +double Rate, Speed, dp, sm; + + dpLocalValve = 0; + dpBrake = 0; + + BrakePress = Hamulec->GetBCP(); +// BrakePress:=(Hamulec as TEst4).ImplsRes.pa; + Volume = Hamulec->GetBRP(); + +} + + +// ************************************************************************************************* +// Q: 20160712 +// ************************************************************************************************* +void TMoverParameters::CompressorCheck(double dt) +{ + //if (CompressorSpeed>0.0) then //ten warunek został sprawdzony przy wywołaniu funkcji + if (VeselVolume>0) + { + if (MaxCompressor - MinCompressor < 0.0001) + { +// if (Mains && (MainCtrlPos > 1)) + if (CompressorAllow && Mains && (MainCtrlPos>0)) + { + if (Compressor < MaxCompressor) + if ((EngineType == DieselElectric) && (CompressorPower > 0)) + CompressedVolume =CompressedVolume + dt * CompressorSpeed * (2 * MaxCompressor-Compressor) / MaxCompressor*(DElist[MainCtrlPos].RPM / DElist[MainCtrlPosNo].RPM); + else + { + CompressedVolume = CompressedVolume + dt * CompressorSpeed * (2 * MaxCompressor-Compressor) / MaxCompressor; + TotalCurrent = 0.0015 * Voltage; //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę + } + else + { + CompressedVolume = CompressedVolume * 0.8; + SetFlag(SoundFlag, sound_relay); + SetFlag(SoundFlag, sound_loud); + } + } + } + else + { + if (CompressorFlag) //jeśli sprężarka załączona + { //sprawdzić możliwe warunki wyłączenia sprężarki + if (CompressorPower == 5) //jeśli zasilanie z sąsiedniego członu + { //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) + if (Couplers[1].Connected != NULL) + CompressorFlag = (Couplers[1].Connected->CompressorAllow && Couplers[1].Connected->ConverterFlag && Couplers[1].Connected->Mains); + else + CompressorFlag = false; //bez tamtego członu nie zadziała + } + else if (CompressorPower == 4) //jeśli zasilanie z poprzedniego członu + { //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) + if (Couplers[0].Connected != NULL) + CompressorFlag = (Couplers[0].Connected->CompressorAllow && Couplers[0].Connected->ConverterFlag && Couplers[0].Connected->Mains); + else + CompressorFlag = false; //bez tamtego członu nie zadziała + } + else + CompressorFlag = ((CompressorAllow) && ((ConverterFlag) || (CompressorPower == 0)) && (Mains)); + if (Compressor > MaxCompressor) //wyłącznik ciśnieniowy jest niezależny od sposobu zasilania + CompressorFlag = false; + } + else //jeśli nie załączona + if ((Compressor < MinCompressor) && (LastSwitchingTime > CtrlDelay)) //jeśli nie załączona, a ciśnienie za małe + { //załączenie przy małym ciśnieniu + if (CompressorPower == 5) //jeśli zasilanie z następnego członu + { //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) + if (Couplers[1].Connected != NULL) + CompressorFlag = (Couplers[1].Connected->CompressorAllow && Couplers[1].Connected->ConverterFlag && Couplers[1].Connected->Mains); + else + CompressorFlag = false; //bez tamtego członu nie zadziała + } + else if (CompressorPower == 4) //jeśli zasilanie z poprzedniego członu + { //zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) + if (Couplers[0].Connected != NULL) + CompressorFlag = (Couplers[0].Connected->CompressorAllow && Couplers[0].Connected->ConverterFlag && Couplers[0].Connected->Mains); + else + CompressorFlag = false; //bez tamtego członu nie zadziała + } + else + CompressorFlag = ((CompressorAllow) && ((ConverterFlag) || (CompressorPower == 0)) && (Mains)); + if (CompressorFlag) //jeśli została załączona + LastSwitchingTime = 0; //to trzeba ograniczyć ponowne włączenie + } +// for b:=0 to 1 do //z Megapacka +// with Couplers[b] do +// if TestFlag(CouplingFlag,ctrain_scndpneumatic) then +// Connected.CompressorFlag:=CompressorFlag; + if (CompressorFlag) + if ((EngineType == DieselElectric) && (CompressorPower > 0)) + CompressedVolume = CompressedVolume + dt * CompressorSpeed * (2 * MaxCompressor - Compressor) / MaxCompressor * (DElist[MainCtrlPos].RPM / DElist[MainCtrlPosNo].RPM); + else + { + CompressedVolume = CompressedVolume + dt * CompressorSpeed * (2 * MaxCompressor - Compressor) / MaxCompressor; + if ((CompressorPower == 5) && (Couplers[1].Connected != NULL)) + 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) && (Couplers[0].Connected != NULL)) + Couplers[0].Connected->TotalCurrent = 0.0015 * Couplers[0].Connected->Voltage; //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę + else + TotalCurrent = 0.0015 * Voltage; //tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę + } + } + } +} + + +// ************************************************************************************************* +// Q: 20160712 +// ************************************************************************************************* +void TMoverParameters::UpdatePipePressure(double dt) +{ + const LBDelay = 100; + const kL = 0.5; + double dV; + TMoverParameters *c; // T_MoverParameters + double temp; + Byte b; + + PipePress = Pipe->P(); +// PPP:=PipePress; + + dpMainValve = 0; + + if ((BrakeCtrlPosNo > 1) && (ActiveCab != 0)) +//with BrakePressureTable[BrakeCtrlPos] do + { + dpLocalValve = LocHandle->GetPF(LocalBrakePos / Hamulce::LocalBrakePosNo, Hamulec->GetBCP(), ScndPipePress, dt, 0); + if ((BrakeHandle == FV4a) && ((PipePress < 2.75) && ((Hamulec->GetStatus() && b_rls) == 0)) && (BrakeSubsystem == ss_LSt) && (TrainType != dt_EZT)) + temp = PipePress + 0.00001; + else + temp = ScndPipePress; + Handle->SetReductor(BrakeCtrlPos2); + + dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress); + if (dpMainValve < 0) // && (PipePressureVal > 0.01) //50 + if (Compressor > ScndPipePress) + { + CompressedVolume = CompressedVolume + dpMainValve / 1500; + Pipe2->Flow(dpMainValve / 3); + } + else + Pipe2->Flow(dpMainValve); + } + +// if(EmergencyBrakeFlag)and(BrakeCtrlPosNo=0)then //ulepszony hamulec bezp. + if ((EmergencyBrakeFlag) || (TestFlag(SecuritySystem.Status, s_SHPebrake)) || (TestFlag(SecuritySystem.Status, s_CAebrake)) || (s_CAtestebrake == true)) //ulepszony hamulec bezp. + dpMainValve = dpMainValve / 1 + PF(0,PipePress, 0.15, 0.25) * dt; // Q: dodalem 4 paraMETR 0.25 bo wywalalo ze za malo parametrow + //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 + + +// if (Hamulec is typeid(TWest)) return 0; + + switch (BrakeValve) + { + case W: + { + if (BrakeLocHandle != NoHandle) + { + LocBrakePress = LocHandle->GetCP(); + + //(Hamulec as TWest).SetLBP(LocBrakePress); + static_cast(Hamulec)->SetLBP(LocBrakePress); + } + if (MBPM < 2) + //(Hamulec as TWest).PLC(MaxBrakePress[LoadFlag]) + static_cast(Hamulec)->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TWest).PLC(TotalMass); + static_cast(Hamulec)->PLC(TotalMass); + break; + } + + case LSt: + case EStED: + { + LocBrakePress = LocHandle->GetCP(); + for (int b=0; b<1; b++) + if (((TrainType && (dt_ET41 || dt_ET42))> 0) && (Couplers[b].Connected != NULL)) //nie podoba mi się to rozwiązanie, chyba trzeba dodać jakiś wpis do fizyki na to + if (((Couplers[b].Connected->TrainType && (dt_ET41 || dt_ET42)) > 0) && ((Couplers[b].CouplingFlag & 36) == 36)) + LocBrakePress = Max0R(Couplers[b].Connected->LocHandle->GetCP(), LocBrakePress); + + if((DynamicBrakeFlag) && (EngineType == ElectricInductionMotor)) + { + if(Vel > 10) LocBrakePress = 0; else + if(Vel > 5) LocBrakePress = (10-Vel)/5*LocBrakePress; + } + + //(Hamulec as TLSt).SetLBP(LocBrakePress); + static_cast(Hamulec)->SetLBP(LocBrakePress); + break; + } + + case CV1_L_TR: + { + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TCV1L_TR).SetLBP(LocBrakePress); + static_cast(Hamulec)->SetLBP(LocBrakePress); + break; + } + + // EP2: (Hamulec as TEStEP2).PLC(TotalMass); + case ESt3AL2: + case NESt3: + case ESt4: + case ESt3: + { + if (MBPM<2) + //(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag]) + static_cast(Hamulec)->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TNESt3).PLC(TotalMass); + static_cast(Hamulec)->PLC(TotalMass); + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TNESt3).SetLBP(LocBrakePress); + static_cast(Hamulec)->SetLBP(LocBrakePress); + break; + } + case KE: + { + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TKE).SetLBP(LocBrakePress); + static_cast(Hamulec)->SetLBP(LocBrakePress); + if (MBPM < 2) + //(Hamulec as TKE).PLC(MaxBrakePress[LoadFlag]) + static_cast(Hamulec)->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TKE).PLC(TotalMass); + static_cast(Hamulec)->PLC(TotalMass); + break; + } + } // switch + + if ((BrakeHandle == FVel6) && (ActiveCab != 0)) + { + if ((Battery) && (ActiveDir != 0) && (EpFuse)) //tu powinien byc jeszcze bezpiecznik EP i baterie - + //temp = (Handle as TFVel6).GetCP + temp = static_cast(Handle)->GetCP(); + else + temp = 0; + Hamulec->SetEPS(temp); + SendCtrlToNext("Brake", temp, CabNo); //Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach + } + + Pipe->Act(); + PipePress = Pipe->P(); + if ((BrakeStatus & 128) == 128) //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) + 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) + { + PipePress = -1; + Pipe->CreatePress(-1); + Pipe->Act(); + } + + if (CompressedVolume < 0) + CompressedVolume = 0; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +void TMoverParameters::UpdateScndPipePressure(double dt) +{ +const Spz=0.5067; +//T_MoverParameters *c; +TMoverParameters *c; +double dv1, dv2, dV; + + dv1 = 0; + dv2 = 0; + +//sprzeg 1 + if (Couplers[0].Connected != NULL) + if (TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) + { + c = Couplers[0].Connected; //skrot + dv1 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75, 0.25); + if (dv1 * dv1 > 0.00000000000001) c->Physic_ReActivation(); + c->Pipe2->Flow(-dv1); + } +//sprzeg 2 + if (Couplers[1].Connected != NULL) + if (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic)) + { + c = Couplers[1].Connected; //skrot + dv2 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75, 0.25); + if (dv2 * dv2 > 0.00000000000001) c->Physic_ReActivation(); + c->Pipe2->Flow(-dv2); + } + if((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) + if ((TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) && (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic))) + { + dV = 0.00025 * dt * PF(Couplers[0].Connected->ScndPipePress, Couplers[1].Connected->ScndPipePress, Spz * 0.25, 0.25); + Couplers[0].Connected->Pipe2->Flow(+dV); + Couplers[1].Connected->Pipe2->Flow(-dV); + } + + Pipe2->Flow(Hamulec->GetHPFlow(ScndPipePress, dt)); + + if (((Compressor > ScndPipePress) && (CompressorSpeed > 0.0001)) || (TrainType == dt_EZT)) + { + dV = PF(Compressor, ScndPipePress, Spz, 0.25) * dt; + CompressedVolume = CompressedVolume + dV / 1000; + Pipe2->Flow(-dV); + } + + Pipe2->Flow(dv1+dv2); + Pipe2->Act(); + ScndPipePress = Pipe2->P(); + + if (ScndPipePress <-1) + { + ScndPipePress = -1; + Pipe2->CreatePress(-1); + Pipe2->Act(); + } + +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +double TMoverParameters::GetDVc(double dt) +{ +// T_MoverParameters *c; + TMoverParameters *c; + double dv1, dv2, dV; + + dv1 = 0; + dv2 = 0; +//sprzeg 1 + if (Couplers[0].Connected != NULL) + if (TestFlag(Couplers[0].CouplingFlag, ctrain_pneumatic)) + { //*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), 0.25); + if (dv1 * dv1 > 0.00000000000001) c->Physic_ReActivation(); + c->Pipe->Flow(-dv1); + } +//sprzeg 2 + if (Couplers[1].Connected != NULL) + if (TestFlag(Couplers[1].CouplingFlag, ctrain_pneumatic)) + { + c = Couplers[1].Connected; //skrot + dv2 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1 + 0.015 / Spg * Dim.L), 0.25); + if (dv2 * dv2 > 0.00000000000001) c->Physic_ReActivation(); + c->Pipe->Flow(-dv2); + } + if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) + if ((TestFlag(Couplers[0].CouplingFlag,ctrain_pneumatic)) && (TestFlag(Couplers[1].CouplingFlag,ctrain_pneumatic))) + { + dV = 0.05 * dt * PF(Couplers[0].Connected->PipePress, Couplers[1].Connected->PipePress, (Spg * 0.85) / (1+ 0.03 * Dim.L), 0.25 ) * 0; + Couplers[0].Connected->Pipe->Flow(+dV); + Couplers[1].Connected->Pipe->Flow(-dV); + } +//suma + return dv2 + dv1; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +void TMoverParameters::ComputeConstans(void) +{ + double BearingF,RollF,HideModifier; + double Curvature; //Ra 2014-07: odwrotność promienia + + 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 && dtrain_bearing); + + HideModifier = 0;//Byte(Couplers[0].CouplingFlag>0)+Byte(Couplers[1].CouplingFlag>0); + + if (BearingType == 0) + RollF = 0.05; //slizgowe + else + RollF = 0.015; //toczne + RollF = RollF + BearingF / 200.0; + +// if (NPoweredAxles > 0) +// RollF = RollF * 1.5; //dodatkowe lozyska silnikow + + if (NPoweredAxles > 0) //drobna optymalka + { + RollF = RollF + 0.025; +// if (Ft * Ft < 1) +// HideModifier = HideModifier - 3; + } + Ff = TotalMassxg*(BearingF + RollF * V * V / 10.0) / 1000.0; + //dorobic liczenie temperatury lozyska! + FrictConst1 = ((TotalMassxg * RollF) / 10000.0) + (Cx * Dim.W * Dim.H); + Curvature = abs(RunningShape.R); //zero oznacza nieskończony promień + if (Curvature > 0.0) 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; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::ComputeMass(void) +{ + double M; + + if (Load>0) + { //zakładamy, że ładunek jest pisany małymi literami + if (LoadQuantity == "tonns") + M = Load * 1000; + else if (LoadType == "passengers") + M = Load * 80; + else if (LoadType == "luggage") + M = Load * 100; + else if (LoadType == "cars") + M = Load * 800; + else if (LoadType == "containers") + M = Load * 8000; + else if (LoadType == "transformers") + M = Load * 50000; + else + M = Load * 1000; + } + else + M = 0; + //Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają + return Mass + M + Mred; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) +{ +Byte b; + + if (PhysicActivation) + { +// 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) && (PipePress < 3.0) && (Vel > 45) && TestFlag(BrakeDelayFlag, bdelay_M)) //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) + LastRelayTime = LastRelayTime + dt1; +// end; + if (Mains && /*(abs(CabNo) < 2) &&*/ (EngineType == ElectricSeriesMotor)) //potem ulepszyc! pantogtrafy! + { //Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik + if (CabNo == 0) + Voltage = RunningTraction.TractionVoltage * ActiveDir; + else + Voltage = RunningTraction.TractionVoltage * DirAbsolute; //ActiveDir*CabNo; + } //bo nie dzialalo + else + Voltage = 0; + if (Mains && /*(abs(CabNo) < 2) &&*/ (EngineType == ElectricInductionMotor)) //potem ulepszyc! pantogtrafy! + Voltage = RunningTraction.TractionVoltage; + //end; + + if (Power > 0) + FTrain = TractionForce(dt); + else + FTrain = 0; + Fb =BrakeForce(RunningTrack); + if (Max0R(abs(FTrain), Fb) > TotalMassxg * Adhesive(RunningTrack.friction)) //poslizg + SlippingWheels = true; + if (SlippingWheels) + { +// 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)); + } +// else SlippingWheels:=false; +// FStand:=0; + for (b = 0; b<1; b++) + if (Couplers[b].Connected != NULL) /*and (Couplers[b].CouplerType<>Bare) and (Couplers[b].CouplerType<>Articulated)*/ + { //doliczenie sił z innych pojazdów + Couplers[b].CForce = CouplerForce(b, dt); + FTrain = FTrain + Couplers[b].CForce; + } + 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; + } + + //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) + //{ + if ((CabNo == 0) && (Vel < 0.0001) && (abs(AccS) < 0.0001) && (TrainType != dt_EZT)) + { + if (!PhysicActivation) + { + if (Couplers[0].Connected != NULL) + if ((Couplers[0].Connected->Vel > 0.0001) || (abs(Couplers[0].Connected->AccS) > 0.0001)) + Physic_ReActivation(); + if (Couplers[1].Connected != NULL) + if ((Couplers[1].Connected->Vel > 0.0001) || (abs(Couplers[1].Connected->AccS) > 0.0001)) + Physic_ReActivation(); + } + if (LastSwitchingTime > 5) //10+Random(100) then + PhysicActivation = false; //zeby nie brac pod uwage braku V po uruchomieniu programu + } + else + PhysicActivation = true; + //}; + +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::BrakeForce(const TTrackParam &Track) +{ + double K, Fb, NBrakeAxles, sm; +//const OerlikonForceFactor=1.5; + + K = 0; + if (NPoweredAxles > 0) + NBrakeAxles = NPoweredAxles; + else + NBrakeAxles = NAxles; + switch (LocalBrake) + { + case NoBrake : K = 0; + case ManualBrake : K = MaxBrakeForce * ManualBrakeRatio(); + case HydraulicBrake : K = MaxBrakeForce * LocalBrakeRatio(); + case PneumaticBrake:if (Compressor Ntotal) //histereza na nacisku klockow + Ntotal = u * BrakeRigEff; + else + { + u = (BrakePress * P2FTrans) * BrakeCylMult[0] - BrakeSlckAdj; + if (u * (2 - 1 * BrakeRigEff) < Ntotal) //histereza na nacisku klockow + Ntotal = u * (2 - 1 * BrakeRigEff); + } + + if (NBrakeAxles * NBpA > 0) + { + if (Ntotal > 0) //nie luz + K = K + Ntotal; //w kN + K = K * BrakeCylNo / (NBrakeAxles * NBpA); //w kN na os + } + if ((BrakeSystem == Pneumatic) || (BrakeSystem == ElectroPneumatic)) + { + u = Hamulec->GetFC(Vel, K); + UnitBrakeForce = u * K * 1000; //sila na jeden klocek w N + } + else + UnitBrakeForce = K * 1000; + if ((NBpA * UnitBrakeForce > TotalMassxg * Adhesive(RunningTrack.friction) / NAxles) && (abs(V) > 0.001)) + //poslizg + { +// Fb = Adhesive(Track.friction) * Mass * g; + SlippingWheels = true; + } +//{ 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; } + return Fb; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::FrictionForce(double R, Byte TDamage) +{ + double FF = 0; +//ABu 240205: chyba juz ekstremalnie zoptymalizowana funkcja liczaca sily tarcia + if (abs(V) > 0.01) + FF = (FrictConst1 * V * V) + FrictConst2d; + else + FF = (FrictConst1 * V * V) + FrictConst2s; + return FF; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::Adhesive(double staticfriction) +{ + double adhesive; + + + //ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS? + // w kazdym razie zaciemni kod na pewno :) + if (SlippingWheels == false) + { + if (SandDose) + adhesive = (Max0R(staticfriction*(100.0+Vel)/((50.0+Vel)*11.0),0.048))*(11.0-2.0 * random(0.0, 1.0)); + else + adhesive = (staticfriction*(100.0+Vel)/((50.0+Vel)*10))*(11.0-2.0 * random(0.0, 1.0)); + } + else + { + if (SandDose) + adhesive = (0.048)*(11-2 * random(0.0, 1.0)); + else + adhesive = (staticfriction*0.02)*(11-2 * random(0.0, 1.0)); + } + // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 + return adhesive; +} + + +//poprawka dla liczenia sil przy ustawieniu przeciwnym obiektow: +/* +double DirPatch(Byte Coupler1, Byte Coupler2) +{ + if (Coupler1 != Coupler2) return 1; + else return -1; +} + + +double DirF(Byte CouplerN) +{ + double rDirF; + switch (CouplerN) + { + case 0: return -1; break; + case 1: return 1; break; + default: return 0; + } + // if (CouplerN == 0) return -1; +// else if (CouplerN == 0) return 1; +// else return 0; +} +*/ + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::CouplerForce(Byte CouplerN, double dt) +{ +//wyliczenie siły na sprzęgu + double tempdist,newdist, distDelta, CF, dV, absdV, Fmax, BetaAvg; + Byte CNext; + const MaxDist = 405.0; //ustawione + 5 m, bo skanujemy do 400 m + const MinDist = 0.5; //ustawione +.5 m, zeby nie rozlaczac przy malych odleglosciach + const MaxCount = 1500; + bool rCF; + CF = 0; + //distDelta:=0; //Ra: value never used + CNext =Couplers[CouplerN].ConnectedNr; +// if (Couplers[CouplerN].CForce == 0) //nie bylo uzgadniane wiec policz + + Couplers[CouplerN].CheckCollision = false; + newdist = Couplers[CouplerN].CoupleDist; //odległość od sprzęgu sąsiada + //newdist:=Distance(Loc,Connected^.Loc,Dim,Connected^.Dim); + if (CouplerN == 0) + { + //ABu: bylo newdist+10*((... + tempdist = ((Couplers[CouplerN].Connected->dMoveLen * DirPatch(0, Couplers[CouplerN].ConnectedNr)) - dMoveLen); + newdist = newdist+10.0*tempdist; + //tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu + } + else + { + //ABu: bylo newdist+10*((... + tempdist = ((dMoveLen-(Couplers[CouplerN].Connected->dMoveLen * DirPatch(1, Couplers[CouplerN].ConnectedNr)))); + newdist = newdist + 10.0 * tempdist; + //tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu + } + + //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) && (Couplers[CouplerN].CoupleDist > 0)) + { + CF = 0; //kontrola zderzania sie - OK + ScanCounter++; + if ((newdist > MaxDist) || ((ScanCounter > MaxCount) && (newdist > MinDist))) + //***if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then + { //zerwij kontrolnie wirtualny sprzeg + //Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest wirtualny + Couplers[CouplerN].Connected = NULL; + ScanCounter = random(500); //Q: TODO: cy dobrze przetlumaczone? + //WriteLog(FloatToStr(ScanCounter)); + } + } + else + { + if (Couplers[CouplerN].CouplingFlag == ctrain_virtual) + { + BetaAvg = Couplers[CouplerN].beta; + Fmax =(Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB) * CouplerTune; + } + else //usrednij bo wspolny sprzeg + { + BetaAvg =(Couplers[CouplerN].beta + Couplers[CouplerN].Connected->Couplers[CNext].beta) / 2.0; + Fmax =(Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB + Couplers[CouplerN].Connected->Couplers[CNext].FmaxC + Couplers[CouplerN].Connected->Couplers[CNext].FmaxB)* CouplerTune/2.0; + } + dV = V-DirPatch(CouplerN,CNext) * Couplers[CouplerN].Connected->V; + absdV = abs(dV); + if ((newdist < -0.001) && (Couplers[CouplerN].Dist >= -0.001) && (absdV > 0.010)) //090503: dzwieki pracy zderzakow + { + if (SetFlag(SoundFlag, sound_bufferclamp)) + if (absdV > 0.5) + SetFlag(SoundFlag, sound_loud); + } + else + if ((newdist > 0.002) && (Couplers[CouplerN].Dist <= 0.002) && (absdV > 0.005)) //090503: dzwieki pracy sprzegu + { + if (Couplers[CouplerN].CouplingFlag > 0) + if (SetFlag(SoundFlag, sound_couplerstretch)) + if (absdV > 0.1) + SetFlag(SoundFlag, sound_loud); + } + distDelta = abs(newdist)-abs(Couplers[CouplerN].Dist); //McZapkie-191103: poprawka na histereze + Couplers[CouplerN].Dist = newdist; + if (Couplers[CouplerN].Dist > 0) + { + if (distDelta > 0) + CF =(-(Couplers[CouplerN].SpringKC + Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) * Couplers[CouplerN].Dist / 2.0) * DirF(CouplerN) - Fmax * dV * BetaAvg; + else + CF =(-(Couplers[CouplerN].SpringKC + Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) * Couplers[CouplerN].Dist / 2.0) * DirF(CouplerN) * BetaAvg - Fmax * dV * BetaAvg; + //liczenie sily ze sprezystosci sprzegu + if (Couplers[CouplerN].Dist > (Couplers[CouplerN].DmaxC + Couplers[CouplerN].Connected->Couplers[CNext].DmaxC)) //zderzenie + //***if tempdist>(DmaxC+Connected^.Couplers[CNext].DmaxC) then {zderzenie} + Couplers[CouplerN].CheckCollision = true; + } + if (Couplers[CouplerN].Dist < 0) + { + if (distDelta>0) + CF =(-(Couplers[CouplerN].SpringKB + Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) * Couplers[CouplerN].Dist/2.0) * DirF(CouplerN) - Fmax * dV * BetaAvg; + else + CF =(-(Couplers[CouplerN].SpringKB + Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) * Couplers[CouplerN].Dist/2.0) * DirF(CouplerN) * BetaAvg - Fmax * dV * BetaAvg; + //liczenie sily ze sprezystosci zderzaka + if (-Couplers[CouplerN].Dist > (Couplers[CouplerN].DmaxB + Couplers[CouplerN].Connected->Couplers[CNext].DmaxB)) //zderzenie + //***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie} + { + Couplers[CouplerN].CheckCollision = true; + if ((Couplers[CouplerN].CouplerType == Automatic) && (Couplers[CouplerN].CouplingFlag == 0)) //sprzeganie wagonow z samoczynnymi sprzegami} + //CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic; + Couplers[CouplerN].CouplingFlag = ctrain_coupler + ctrain_pneumatic+ctrain_controll; //EN57 + } + } + } + if (Couplers[CouplerN].CouplingFlag != ctrain_virtual) + //uzgadnianie prawa Newtona + Couplers[CouplerN].Connected->Couplers[1-CouplerN].CForce = -CF; + + return CF; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +double TMoverParameters::TractionForce(double dt) +{//oblicza sile trakcyjna lokomotywy (dla elektrowozu tez calkowity prad) + double PosRatio, dmoment, dtrans, tmp, tmpV; + Byte i; + + Ft = 0; + dtrans = 0; + dmoment = 0; +// tmpV =Abs(nrot * WheelDiameter / 2); +//youBy + if (EngineType == DieselElectric) + { + tmp = DElist[MainCtrlPos].RPM / 60.0; + if ((Heating) && (HeatingPower > 0) && (MainCtrlPosNo > MainCtrlPos)) + { + i = MainCtrlPosNo; + while (DElist[i-2].RPM / 60.0>tmp) + i = i - 1; + tmp = DElist[i].RPM / 60.0; + } + + if (enrot != tmp * Byte(ConverterFlag)) + if (abs(tmp * Byte(ConverterFlag) - enrot) < 0.001) + enrot = tmp*Byte(ConverterFlag); + else + if ((enrot Pirazy2) + //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) + { + switch (RVentType) //wentylatory rozruchowe} + { + case 1: + { + if (ActiveDir != 0) + RventRot = RventRot+ (RVentnmax - RventRot) * RVentSpeed * dt; + else + RventRot = RventRot * (1 - RVentSpeed * dt); + break; + } + case 2: + { + if ((abs(Itot) > RVentMinI) && (RList[MainCtrlActualPos].R > RVentCutOff + )) + RventRot = RventRot + (RVentnmax * abs(Itot) / (ImaxLo * RList[MainCtrlActualPos].Bn)-RventRot) * RVentSpeed * dt; + else + if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) + RventRot = RventRot+(RVentnmax * Im / ImaxLo - RventRot) * RVentSpeed * dt; + else + { + RventRot = RventRot * (1 - RVentSpeed * dt); + if (RventRot < 0.1) RventRot = 0; + } + break; + } + break; + } + + } + + if (ActiveDir != 0) + switch (EngineType) + { + case Dumb: + { + PosRatio = (MainCtrlPos + ScndCtrlPos) / (MainCtrlPosNo + ScndCtrlPosNo + 0.01); + if (Mains && (ActiveDir != 0) && (CabNo != 0)) + { + if (Vel > 0.1) + { + Ft = Min0R(1000.0 * Power / abs(V), Ftmax) * PosRatio; + } + else Ft = Ftmax * PosRatio; + Ft = Ft * DirAbsolute; //ActiveDir*CabNo; + } + else Ft = 0; + EnginePower = 1000 * Power * PosRatio; + break; + } // Dumb + + case WheelsDriven: + { + if (EnginePowerSource.SourceType == InternalSource) + if (EnginePowerSource.PowerType == BioPower) + Ft = Sign(sin(eAngle)) * PulseForce * Transmision.Ratio; + PulseForceTimer = PulseForceTimer + dt; + if (PulseForceTimer > CtrlDelay) + { + PulseForce = 0; + if (PulseForceCount > 0) + PulseForceCount--; + } + EnginePower = Ft * (1+Vel); + break; + } // WheelsDriven + + case ElectricSeriesMotor: + { +// enrot:=Transmision.Ratio*nrot; + //yB: szereg dwoch sekcji w ET42 + if ((TrainType == dt_ET42) && (Imax == ImaxHi)) + Voltage = Voltage / 2.0; + Mm = Momentum(current(enrot, Voltage)); //oblicza tez prad p/slinik + + //double qMm = Momentum(qcurrent(enrot, Voltage)); // Q: funkcja w C++ - porownanie poprawnosci + + + if (TrainType == dt_ET42) + { + if(Imax == ImaxHi) + Voltage = Voltage * 2; + if ((DynamicBrakeFlag) && (abs(Im)>300)) // przeiesione do mover.cpp + FuseOff(); + } + if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) + { + if (((Vadd + abs(Im)) > 760) || (static_cast(Hamulec)->GetEDBCP() < 0.25)) + { + Vadd = Vadd - 500 * dt; + if (Vadd < 1) + Vadd = 0; + } + else if ((DynamicBrakeFlag) && ((Vadd + abs(Im)) < 740)) + { + Vadd = Vadd + 70 * dt; + Vadd = Min0R(Max0R(Vadd, 60), 400); + } + if (Vadd > 0) Mm = MomentumF(Im, Vadd, 0); + } + + if ((TrainType == dt_ET22) && (DelayCtrlFlag)) //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) + Vhyp = Vhyp + dt * (abs(Im) / Imax - 0.9) * 10; //zwieksz czas oddzialywania na PN + else + Vhyp = 0; + if (Vhyp > CtrlDelay / 2) //jesli czas oddzialywania przekroczony + FuseOff(); //wywalanie bezpiecznika z powodu przetezenia silnikow + + //-if (Mains) then //nie wchodzić w funkcję bez potrzeby + //- if (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) || (DynamicBrakeType == dbrake_switch)) && (DynamicBrakeFlag)) + Itot = Im * 2; //2x2 silniki w EP09 + else if ((TrainType == dt_EZT) && (Imin == IminLo) && (ScndS)) //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 + break; + } + + case DieselEngine: + { + EnginePower = dmoment*enrot; + if (MainCtrlPos > 1) + 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; + break; + } +/* + case DieselElectric: //youBy + { +// tmpV:=V*CabNo*ActiveDir; + tmpV =nrot*Pirazy2*0.5*WheelDiameter*DirAbsolute; //*CabNo*ActiveDir; + //jazda manewrowa + if (ShuntMode) + { + 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; + } + else //jazda ciapongowa + { + + 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) && (ConverterFlag)) + if (tmpV < (Vhyp*(Power-HeatingPower*byte(Heating))/DElist[MainCtrlPosNo].GenPower)) //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; + + } + + if (FuseFlag) 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) > MotorParam[ScndCtrlPos].fi) + Im = NPoweredAxles * abs(abs(Mm) / MotorParam[ScndCtrlPos].mfi + MotorParam[ScndCtrlPos].mIsat); + else + Im = NPoweredAxles * sqrt(abs(Mm * MotorParam[ScndCtrlPos].Isat)); + + if (ShuntMode) + { + EnginePower = Voltage * Im/1000.0; + if (EnginePower > tmp) + { + EnginePower = tmp*1000.0; + Voltage = EnginePower / Im; + } + if (EnginePower < tmp) + Ft = Ft * EnginePower / tmp; + } + else + { + if (abs(Im) > DElist[MainCtrlPos].Imax) + { //nie ma nadmiarowego, tylko Imax i zwarcie na pradnicy + Ft = Ft/Im*DElist[MainCtrlPos].Imax; + Im = DElist[MainCtrlPos].Imax; + } + + if (Im > 0) //jak pod obciazeniem + if (Flat) //ograniczenie napiecia w pradnicy - plaszczak u gory + Voltage = 1000.0 * tmp / abs(Im); + else //charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa + { //sqr() TODO: sqr + Voltage = sqrt(abs(sqrt(DElist[MainCtrlPos].Umax) - sqrt(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)) Voltage = Im*0.05; + } + if ((Voltage > DElist[MainCtrlPos].Umax) || (Im == 0)) //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) && (EnginePower < tmp)) + Ft =Ft*EnginePower/tmp; + + } + + //--if (Imax>1) and (Im>Imax) then FuseOff; //przeniesione do mover.cpp + if (FuseFlag) Voltage = 0; + + //przekazniki bocznikowania, kazdy inny dla kazdej pozycji + if ((MainCtrlPos == 0) || (ShuntMode)) + ScndCtrlPos = 0; + + else if (AutoRelayFlag) + switch (RelayType) + { + case 0: + { + if (Im <= (MPTRelay[ScndCtrlPos].Iup*PosRatio)) and (ScndCtrlPos= (MPTRelay[ScndCtrlPos].Idown*PosRatio)) and (ScndCtrlPos>0) then + dec(ScndCtrlPos); + } + case 1: + { + if (MPTRelay[ScndCtrlPos].IupVel) and (ScndCtrlPos>0) then + dec(ScndCtrlPos); + } + case 2: + { + if (MPTRelay[ScndCtrlPos].Iup0) then + dec(ScndCtrlPos); + } + case 41: + { + if (MainCtrlPos=MainCtrlPosNo) and (tmpV*3.6>MPTRelay[ScndCtrlPos].Iup) and (ScndCtrlPosMPTRelay[ScndCtrlPos].Idown)and (ScndCtrlPos>0) then + dec(ScndCtrlPos); + } + case 45: + { + //wzrastanie + if (MainCtrlPos>11) and (ScndCtrlPosIm) then + inc(ScndCtrlPos) + else + else + if (MPTRelay[ScndCtrlPos].Iup0)and(MainCtrlPos<12)then + if (ScndCtrlPos=ScndCtrlPosNo)then + if (MPTRelay[ScndCtrlPos].IdownVel)then + dec(ScndCtrlPos); + if (MainCtrlPos<11)and(ScndCtrlPos>2) then ScndCtrlPos:=2; + if (MainCtrlPos<9)and(ScndCtrlPos>0) then ScndCtrlPos:=0; + } + case 46: + { + //wzrastanie + if (MainCtrlPos>9) and (ScndCtrlPosIm) then + inc(ScndCtrlPos) + else + else + if (MPTRelay[ScndCtrlPos-1].Iup>Im) and (MPTRelay[ScndCtrlPos].Iup0)then + if (ScndCtrlPos) mod 2 = 0 then + if (MPTRelay[ScndCtrlPos].IdownVel)then + dec(ScndCtrlPos); + if (MainCtrlPos<9)and(ScndCtrlPos>2) then ScndCtrlPos:=2; + if (MainCtrlPos<6)and(ScndCtrlPos>0) then ScndCtrlPos:=0; + } + } //switch RelayType + } // DieselElectric +*/ +/* + case ElectricInductionMotor: + { + if (Voltage>1800) and (MainS) then + begin + + if ((Hamulec as TLSt).GetEDBCP<0.25)and(LocHandle.GetCP<0.25) then + DynamicBrakeFlag:=false + else if ((BrakePress>0.25) and ((Hamulec as TLSt).GetEDBCP>0.25)) or (LocHandle.GetCP>0.25) then + DynamicBrakeFlag:=true; + + if(DynamicBrakeFlag)then + begin + if eimv[eimv_Fmax]*sign(V)*DirAbsolute<-1 then + PosRatio:=-sign(V)*DirAbsolute*eimv[eimv_Fr]/(eimc[eimc_p_Fh]*Max0R((Hamulec as TLSt).GetEDBCP,LocHandle.GetCP)/MaxBrakePress[0]{dizel_fill}) + else + PosRatio:=0; + PosRatio:=round(20*Posratio)/20; + if PosRatio<19.5/20 then PosRatio:=PosRatio*0.9; + (Hamulec as TLSt).SetED(PosRatio); + PosRatio:=-Max0R((Hamulec as TLSt).GetEDBCP,LocHandle.GetCP)/MaxBrakePress[0]*Max0R(0,Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0]))); + tmp:=5; + end + else + begin + PosRatio:=(MainCtrlPos/MainCtrlPosNo); + PosRatio:=1.0*(PosRatio*0+1)*PosRatio; + (Hamulec as TLSt).SetED(0); + if (PosRatio>dizel_fill) then tmp:=1 else tmp:=4; //szybkie malenie, powolne wzrastanie + end; + if SlippingWheels + then + begin + PosRatio:=0; + tmp:=10; + //--SandDoseOn; // przeniesione do mover.cpp + end;//przeciwposlizg + + dizel_fill:=dizel_fill+Max0R(Min0R(PosRatio-dizel_fill,0.1),-0.1)*2*(tmp{2{+4*byte(PosRatioeimc[eimc_p_Vh0])then + eimv[eimv_Fmax]:=-sign(V)*(DirAbsolute)*Min0R(eimc[eimc_p_Ph]*3.6/Vel,-eimc[eimc_p_Fh]*dizel_fill)//*Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0])) +// else +// eimv[eimv_Fmax]:=0 + else + eimv[eimv_Fmax]:=Min0R(Min0R(3.6*eimv[eimv_Pmax]/Max0R(Vel,1),eimc[eimc_p_F0]-Vel*eimc[eimc_p_a1]),eimv[eimv_FMAXMAX])*dizel_fill; + + 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]; +// 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]; + Itot:=eimv[eimv_Ipoj]; + + + 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) then + begin + if abs(tmpV)<32 then RventRot:=1.0 else + if abs(tmpV)<39 then RventRot:=0.33*abs(tmpV)/32 else + RventRot:=0.25*abs(tmpV)/39;//} + 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; + (Hamulec as TLSt).SetED(0);RventRot:=0.0; + end; + } // ElectricInductionMotor +*/ + + //None: begin end; + } //case EngineType + return Ft; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n) +{ +double newn,eps; +bool CRW; + if ((n == 0) && (WForce * Sign(V) < 0)) + newn = 0; + else + { + eps = WForce * WheelDiameter /(2.0 * AxleInertialMoment); + newn = n + eps * dt; + if ((newn * n <= 0) && (eps * n < 0)) + newn = 0; + } + CRW = newn; + return CRW; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::FuseFlagCheck(void) +{ + Byte b; + bool FFC; + + FFC = false; + if (Power > 0.01) FFC = FuseFlag; +//Q: TODO: zakomentowalem bo nie widzi funkcji +//- else //pobor pradu jezeli niema mocy +//- for (b=0; b < 1; b++) +//- if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) +//- if (Couplers[b].Connected->Power > 0.01) +//- FFC = Couplers[b].Connected->FuseFlagCheck(); + + return FFC; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::FuseOn(void) +{ + bool FO = false; + if ((MainCtrlPos == 0) && (ScndCtrlPos == 0) && (TrainType != dt_ET40) && Mains) + { //w ET40 jest blokada nastawnika, ale czy działa dobrze? + SendCtrlToNext("FuseSwitch", 1, CabNo); + if (((EngineType == ElectricSeriesMotor) || ((EngineType == DieselElectric))) && FuseFlag) + { + FuseFlag = false; //wlaczenie ponowne obwodu + FO = true; + SetFlag(SoundFlag, sound_relay); + SetFlag(SoundFlag, sound_loud); + } + } + return FO; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +void TMoverParameters::FuseOff(void) +{ + if (!FuseFlag) + { + FuseFlag = true; + EventFlag = true; + SetFlag(SoundFlag, sound_relay); + SetFlag(SoundFlag, sound_loud); + } +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +double TMoverParameters::v2n(void) +{ +//przelicza predkosc liniowa na obrotowa + const dmgn = 0.5; + double n, deltan; + + n =V / (PI * WheelDiameter); //predkosc obrotowa wynikajaca z liniowej [obr/s] + deltan = n - nrot; //"pochodna" prędkości obrotowej + if (SlippingWheels) + if (abs(deltan) < 0.01) + SlippingWheels = false; //wygaszenie poslizgu + if (SlippingWheels) //nie ma zwiazku z predkoscia liniowa V + { //McZapkie-221103: uszkodzenia kol podczas poslizgu + if (deltan > dmgn) + if (FuzzyLogic(deltan, dmgn, p_slippdmg)) + if (SetFlag(DamageFlag, dtrain_wheelwear)) //podkucie + EventFlag = true; + if (deltan < -dmgn) + if (FuzzyLogic(-deltan, dmgn, p_slippdmg)) + if (SetFlag(DamageFlag, dtrain_thinwheel)) //wycieranie sie obreczy + EventFlag = true; + n = nrot; //predkosc obrotowa nie zalezy od predkosci liniowej + } + return n; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +double TMoverParameters::Momentum(double I) +{ +//liczy moment sily wytwarzany przez silnik elektryczny} +Byte SP; + + SP = ScndCtrlActualPos; + if (ScndInMain) + if (!(RList[MainCtrlActualPos].ScndAct == 255)) + SP = RList[MainCtrlActualPos].ScndAct; + +// Momentum:=mfi*I*(1-1.0/(Abs(I)/mIsat+1)); + return (MotorParam[SP].mfi * I * (abs(I) / (abs(I) + MotorParam[SP].mIsat) - MotorParam[SP].mfi0)); +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +double TMoverParameters::MomentumF(double I, double Iw, Byte SCP) +{ +//umozliwia dokladne sterowanie wzbudzeniem + + return (MotorParam[SCP].mfi * I * Max0R(abs(Iw) / (abs(Iw) + MotorParam[SCP].mIsat) - MotorParam[SCP].mfi0, 0)); +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::CutOffEngine(void) +{ + bool COE =false; //Ra: wartość domyślna, sprawdzić to trzeba + if ((NPoweredAxles > 0) && (CabNo == 0) && (EngineType == ElectricSeriesMotor)) + { + if (SetFlag(DamageFlag, -dtrain_engine)) + { + NPoweredAxles = NPoweredAxles / 2; // bylo div czyli mod? + COE = true; + } + } + return COE; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::MaxCurrentSwitch(bool State) +{ + bool MCS = false; + if (EngineType == ElectricSeriesMotor) + if (ImaxHi > ImaxLo) + { + if (State && (Imax ==ImaxLo) && (RList[MainCtrlPos].Bn < 2) && !((TrainType == dt_ET42) && (MainCtrlPos > 0)) ) + { + Imax = ImaxHi; + MCS = true; + if (CabNo != 0) + SendCtrlToNext("MaxCurrentSwitch", 1, CabNo); + } + if (!State) + if (Imax == ImaxHi) + if (!((TrainType == dt_ET42) && (MainCtrlPos > 0))) + { + Imax = ImaxLo; + MCS = true; + if (CabNo != 0) + SendCtrlToNext("MaxCurrentSwitch", 0, CabNo); + } + } + return MCS; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::MinCurrentSwitch(bool State) +{ + bool MCS = false; + if (((EngineType == ElectricSeriesMotor) && (IminHi > IminLo)) || (TrainType == dt_EZT)) + { + if (State && (Imin == IminLo)) + { + Imin = IminHi; + MCS = true; + if (CabNo != 0) + SendCtrlToNext("MinCurrentSwitch", 1, CabNo); + } + if ((!State) && (Imin == IminHi)) + { + Imin = IminLo; + MCS = true; + if (CabNo != 0) + SendCtrlToNext("MinCurrentSwitch", 0, CabNo); + } + } + return MCS; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::ResistorsFlagCheck(void) +{ +Byte b; +bool RFC = false; + + if (Power > 0.01) RFC = ResistorsFlag; +//Q: TODO: zakomentowalem bo nie widzi funkcji, do czasu przenesienia TCoupling do mover.h + else //pobor pradu jezeli niema mocy + RFC = false; // po przeniesieniu usunac te linie +//- for (b=0; b<1; b++) + //- if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) + //- if (Couplers[b].Connected->Power > 0.01) +//- RFC = Couplers[b].Connected->ResistorsFlagCheck(); + return RFC; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::AutoRelaySwitch(bool State) +{ + bool ARS; + if ((AutoRelayType == 2) && (AutoRelayFlag != State)) + { + AutoRelayFlag = State; + ARS = true; + SendCtrlToNext("AutoRelaySwitch", int(State), CabNo); + } + else + ARS = false; + + return ARS; +} + + + + +// ************************************************************************************************* +// Q: 20160724 +// ************************************************************************************************* + +bool TMoverParameters::AutoRelayCheck(void) +{ + bool OK; //b:byte; + bool ARFASI, ARFASI2; //sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im 2.1) || (ActiveDir == 0)) //hunter-111211: wylacznik cisnieniowy + { + StLinFlag = false; //yBARC - rozlaczenie stycznikow liniowych + OK = false; + if (!DynamicBrakeFlag) + { + Im = 0; + Itot = 0; + ResistorsFlag = false; + } + } + + + ARFASI2 =((!AutoRelayFlag) || ((MotorParam[ScndCtrlActualPos].AutoSwitch) && (abs(Im) < Imin))); //wszystkie warunki w jednym + ARFASI =((!AutoRelayFlag) || ((RList[MainCtrlActualPos].AutoSwitch) && (abs(Im) < Imin)) || ((!RList[MainCtrlActualPos].AutoSwitch) && (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 + { + if (StLinFlag) + { + if ((RList[MainCtrlActualPos].R == 0) && ((ScndCtrlActualPos > 0) || (ScndCtrlPos > 0)) && (!(CoupledCtrl) || (RList[MainCtrlActualPos].Relay == MainCtrlPos))) + { //zmieniaj scndctrlactualpos + //{ //scnd bez samoczynnego rozruchu + if (ScndCtrlActualPos < ScndCtrlPos) + { + if ((LastRelayTime > CtrlDelay) && (ARFASI2)) + { + ScndCtrlActualPos++; + OK = true; + } + } + else + if (ScndCtrlActualPos > ScndCtrlPos) + { + if ((LastRelayTime > CtrlDownDelay) && (TrainType != dt_EZT)) + { + ScndCtrlActualPos--; + OK = true; + } + } + else OK = false; + // } + } + else + { //zmieniaj mainctrlactualpos + if ((ActiveDir < 0) && (TrainType != dt_PseudoDiesel)) + if (RList[MainCtrlActualPos+1].Bn > 1) + { + OK= false; + //return ARC;// bbylo exit; //Ra: to powoduje, że EN57 nie wyłącza się przy IminLo + } + { //main bez samoczynnego rozruchu + + if ((RList[MainCtrlActualPos].Relay < MainCtrlPos) || (RList[MainCtrlActualPos+1].Relay == MainCtrlPos) || ((TrainType == dt_ET22) && (DelayCtrlFlag))) + { + if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && (!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1)) + { + MainCtrlActualPos++; +// MainCtrlActualPos:=MainCtrlPos; //hunter-111012: szybkie wchodzenie na bezoporowa (303E) + OK = true; + SetFlag(SoundFlag, sound_manyrelay); + SetFlag(SoundFlag, sound_loud); + } + else if ((LastRelayTime > CtrlDelay) && (ARFASI)) + { + //WriteLog("LRT = " + FloatToStr(LastRelayTime) + ", " + FloatToStr(CtrlDelay)); + if ((TrainType == dt_ET22) &&(MainCtrlPos > 1) && ((RList[MainCtrlActualPos].Bn < RList[MainCtrlActualPos+1].Bn) || (DelayCtrlFlag))) //et22 z walem grupowym + if (!DelayCtrlFlag) //najpierw przejscie + { + MainCtrlActualPos++; + DelayCtrlFlag = true; //tryb przejscia + OK = true; + } + else if(LastRelayTime > 4*CtrlDelay) //przejscie + { + + DelayCtrlFlag = false; + OK = true; + } + else; + else //nie ET22 z wałem grupowym + { + MainCtrlActualPos++; + OK = true; + } + //--------- + //hunter-111211: poprawki + if (MainCtrlActualPos>0) + if ((RList[MainCtrlActualPos].R == 0) && (!(MainCtrlActualPos == MainCtrlPosNo))) //wejscie na bezoporowa + { + SetFlag(SoundFlag,sound_manyrelay); + SetFlag(SoundFlag,sound_loud); + } + else if ((RList[MainCtrlActualPos].R > 0) && (RList[MainCtrlActualPos-1].R == 0)) //wejscie na drugi uklad + { + SetFlag(SoundFlag,sound_manyrelay); + } + } + } + else if (RList[MainCtrlActualPos].Relay > MainCtrlPos) + { + if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && (! (MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1)) + { + MainCtrlActualPos--; +// MainCtrlActualPos:=MainCtrlPos; //hunter-111012: szybkie wchodzenie na bezoporowa (303E) + OK = true; + SetFlag(SoundFlag, sound_manyrelay); + } + else if (LastRelayTime > CtrlDownDelay) + { + if (TrainType != dt_EZT) //tutaj powinien być tryb sterowania wałem + { + MainCtrlActualPos--; + OK = true; + } + if (MainCtrlActualPos > 0) //hunter-111211: poprawki + if (RList[MainCtrlActualPos].R == 0) //dzwieki schodzenia z bezoporowej} + { + SetFlag(SoundFlag, sound_manyrelay); + } + } + } + else + if ((RList[MainCtrlActualPos].R > 0) && (ScndCtrlActualPos > 0)) + { + if (LastRelayTime > CtrlDownDelay) + { + ScndCtrlActualPos--; //boczniki nie dzialaja na poz. oporowych + OK =true; + } + } + else + OK =false; + } + } + } + else //not StLinFlag + { + OK = false; + //ybARC - tutaj sa wszystkie warunki, jakie musza byc spelnione, zeby mozna byla zalaczyc styczniki liniowe + if (((MainCtrlPos == 1) || ((TrainType == dt_EZT) && (MainCtrlPos > 0))) && (!FuseFlag) && (Mains) && /*(BrakePress < 1.0) &&*/ (MainCtrlActualPos == 0) && (ActiveDir != 0)) + { //^^ TODO: sprawdzic BUG, prawdopodobnie w CreateBrakeSys() + DelayCtrlFlag = true; + if (LastRelayTime >= InitialCtrlDelay) + { + StLinFlag = true; //ybARC - zalaczenie stycznikow liniowych + MainCtrlActualPos = 1; + DelayCtrlFlag = false; + SetFlag(SoundFlag, sound_relay); + SetFlag(SoundFlag, sound_loud); + OK = true; + } + } + else + DelayCtrlFlag = false; + + if ((!StLinFlag) && ((MainCtrlActualPos > 0) || (ScndCtrlActualPos > 0))) + if ((TrainType == dt_EZT) && (CoupledCtrl)) //EN57 wal jednokierunkowy calosciowy + { + if(MainCtrlActualPos == 1) + { + MainCtrlActualPos = 0; + OK = true; + } + else + if(LastRelayTime > CtrlDownDelay) + { + if(MainCtrlActualPos < RlistSize) + MainCtrlActualPos++; //dojdz do konca + else if(ScndCtrlActualPos < ScndCtrlPosNo) + ScndCtrlActualPos++; //potem boki + else + { //i sie przewroc na koniec + MainCtrlActualPos = 0; + ScndCtrlActualPos = 0; + } + OK = true; + } + } + else if(CoupledCtrl) //wal kulakowy dwukierunkowy + { + if (LastRelayTime > CtrlDownDelay) + { + if (ScndCtrlActualPos > 0) + ScndCtrlActualPos--; + else MainCtrlActualPos--; + OK = true; + } + } + else + { + MainCtrlActualPos = 0; + ScndCtrlActualPos = 0; + OK = true; + } + + } + if (OK) LastRelayTime = 0; + + return OK; + } +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::PantFront(bool State) +{ + double pf1; + bool PF; + +if ((Battery == true)/* and ((TrainType<>dt_ET40)or ((TrainType=dt_ET40) and (EnginePowerSource.CollectorsNo>1)))*/) +{ + PF = true; + if (State == true) pf1 = 1; + else pf1 = 0; + if (PantFrontUp != State) + { + PantFrontUp = State; + if (State == true) + { + PantFrontStart = 0; + SendCtrlToNext("PantFront", 1, CabNo); + } + else + { + PF = false; + PantFrontStart = 1; + SendCtrlToNext("PantFront", 0, CabNo); +//{Ra: nie ma potrzeby opuszczać obydwu na raz, jak mozemy każdy osobno +// if (TrainType == dt_EZT) && (ActiveCab == 1) +// { +// PantRearUp = false; +// PantRearStart = 1; +// SendCtrlToNext("PantRear", 0, CabNo); +// } +//} + } + } + else + SendCtrlToNext("PantFront", pf1, CabNo); + +} + return PF; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::PantRear(bool State) +{ +double pf1; +bool PR; + +if (Battery == true) + { + PR = true; + if (State == true) pf1 = 1; + else pf1 = 0; + if (PantRearUp != State) + { + PantRearUp = State; + if (State == true) + { + PantRearStart = 0; + SendCtrlToNext("PantRear", 1, CabNo); + } + else + { + PR = false; + PantRearStart = 1; + SendCtrlToNext("PantRear", 0, CabNo); + } + } + else + SendCtrlToNext("PantRear", pf1, CabNo); + } + return PR; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +bool TMoverParameters::dizel_EngageSwitch(double state) +{ + if ((EngineType == DieselEngine) && (state <= 1) && (state >= 0) && (state != dizel_engagestate)) + { + dizel_engagestate = state; + return true; + } + else + return false; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +bool TMoverParameters::dizel_EngageChange(double dt) +{ +//zmienia parametr do ktorego dazy sprzeglo + const engagedownspeed = 0.9; + const engageupspeed = 0.5; + double engagespeed; //OK:boolean; + bool DEC; + + DEC = false; + if (dizel_engage - dizel_engagestate > 0) + engagespeed = engagedownspeed; + else + engagespeed = engageupspeed; + if (dt > 0.2) + dt = 0.1; + if (abs(dizel_engage - dizel_engagestate) < 0.11) + { + if (dizel_engage != dizel_engagestate) + { + DEC = true; + dizel_engage = dizel_engagestate; + } + //else OK:=false; //już jest false + } + else + { + dizel_engage = dizel_engage + engagespeed * dt * (dizel_engagestate - dizel_engage); + //OK:=false; + } + //dizel_EngageChange:=OK; + return DEC; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +bool TMoverParameters::dizel_AutoGearCheck(void) +{ +bool OK; + + OK = false; + if (MotorParam[ScndCtrlActualPos].AutoSwitch && Mains) + { + if (RList[MainCtrlPos].Mn == 0) + { + if (dizel_engagestate > 0) + dizel_EngageSwitch(0); + if ((MainCtrlPos == 0) && (ScndCtrlActualPos > 0)) + dizel_automaticgearstatus = -1; + } + else + { + if (MotorParam[ScndCtrlActualPos].AutoSwitch && (dizel_automaticgearstatus == 0)) //sprawdz czy zmienic biegi + { + if ((Vel > MotorParam[ScndCtrlActualPos].mfi) && (ScndCtrlActualPos < ScndCtrlPosNo)) + { + dizel_automaticgearstatus = 1; + OK = true; + } + else + if ((Vel < MotorParam[ScndCtrlActualPos].fi) && (ScndCtrlActualPos > 0)) + { + dizel_automaticgearstatus = -1; + OK = true; + } + } + } + if ((dizel_engage < 0.1) && (dizel_automaticgearstatus != 0)) + { + if (dizel_automaticgearstatus == 1) + ScndCtrlActualPos++; + else + ScndCtrlActualPos--; + dizel_automaticgearstatus = 0; + dizel_EngageSwitch(1.0); + OK = true; + } + } + + if (Mains) + { + if (dizel_automaticgearstatus == 0) //ustaw cisnienie w silowniku sprzegla} + switch (RList[MainCtrlPos].Mn) + { + case 1: dizel_EngageSwitch(0.5); + case 2: dizel_EngageSwitch(1.0); + default: dizel_EngageSwitch(0.0); + } + else + dizel_EngageSwitch(0.0); + if (! (MotorParam[ScndCtrlActualPos].mIsat > 0)) + dizel_EngageSwitch(0.0); //wylacz sprzeglo na pozycjach neutralnych + if (!AutoRelayFlag) + ScndCtrlActualPos = ScndCtrlPos; + } + return OK; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +bool TMoverParameters::dizel_Update(double dt) +{//odświeża informacje o silniku + const fillspeed = 2; + bool DU; + + //dizel_Update:=false; + if (dizel_enginestart && (LastSwitchingTime >= InitialCtrlDelay)) + { + dizel_enginestart = false; + LastSwitchingTime = 0; + enrot = dizel_nmin / 2.0; //TODO: dac zaleznie od temperatury i baterii + } + /*OK=*/dizel_EngageChange(dt); +// if AutoRelayFlag then Poprawka na SM03 + DU = dizel_AutoGearCheck(); +//dizel_fill:=(dizel_fill+dizel_fillcheck(MainCtrlPos))/2; + dizel_fill = dizel_fill+fillspeed*dt*(dizel_fillcheck(MainCtrlPos)-dizel_fill); + //dizel_Update:=OK; + + return DU; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +double TMoverParameters::dizel_fillcheck(Byte mcp) +{// oblicza napelnienie, uzwglednia regulator obrotow + double realfill, nreg; + + realfill = 0; + nreg = 0; + if (Mains && (MainCtrlPosNo > 0)) + { + if (dizel_enginestart && (LastSwitchingTime >= 0.9 * InitialCtrlDelay)) //wzbogacenie przy rozruchu + realfill = 1; + else + realfill = RList[mcp].R; //napelnienie zalezne od MainCtrlPos + if (dizel_nmax_cutoff > 0) + { + switch (RList[MainCtrlPos].Mn) + { + case 0: + case 1: nreg = dizel_nmin; + case 2: if(dizel_automaticgearstatus == 0) + nreg = dizel_nmax; + else + nreg = dizel_nmin; + default: realfill = 0; //sluczaj + } + if (enrot > nreg) + realfill = realfill * (3.9-3.0*abs(enrot)/nreg); + if (enrot > dizel_nmax_cutoff) + realfill = realfill * (9.8-9.0*abs(enrot)/dizel_nmax_cutoff); + if (enrot < dizel_nmin) + realfill = realfill * (1+(dizel_nmin-abs(enrot))/dizel_nmin); + } + } + if (realfill < 0) + realfill = 0; + if (realfill > 1) + realfill = 1; + return realfill; +} + + +// ************************************************************************************************* +// Q: 20160715 +// ************************************************************************************************* +double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) +{//liczy moment sily wytwarzany przez silnik spalinowy} + double Moment, enMoment, eps, newn, friction; + double DM; + +// friction =dizel_engagefriction*(11-2*random)/10; + friction =dizel_engagefriction; + if (enrot > 0) + { //sqr TODO: sqr c++ + Moment = dizel_Mmax*dizel_fill-(dizel_Mmax-dizel_Mnmax*dizel_fill) * sqr(enrot/(dizel_nmax-dizel_nMmax*dizel_fill))-dizel_Mstand; //Q: zamieniam SQR() na sqr() +// Moment:=Moment*(1+sin(eAngle*4))-dizel_Mstand*(1+cos(eAngle*4));} + } + else Moment = -dizel_Mstand; + if (enrot < dizel_nmin / 10.0) + if (eAngle < PI/2.0) Moment = Moment-dizel_Mstand; //wstrzymywanie przy malych obrotach + //!! abs + if (abs(abs(n)-enrot) < 0.1) + { + if ((Moment) > (dizel_engageMaxForce*dizel_engage*dizel_engageDia*friction*2)) //zerwanie przyczepnosci sprzegla + enrot = enrot + dt * Moment / dizel_AIM; + else + { + dizel_engagedeltaomega = 0; + enrot = abs(n); //jest przyczepnosc tarcz + } + } + else + { + if ((enrot==0) && (Moment < 0)) + newn = 0; + else + { + //!! 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) && (eps*enrot<0)) + newn = 0; + } + enrot = newn; + } + DM = Moment; + if ((enrot == 0) && (!dizel_enginestart)) + Mains = false; + + return DM; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::LoadingDone(double LSpeed, AnsiString LoadInit) +{ +//test zakończenia załadunku/rozładunku + long LoadChange; + bool LD; + + + ClearPendingExceptions; //zabezpieczenie dla Trunc() + //LoadingDone:=false; //nie zakończone + if (LoadInit != "") //nazwa ładunku niepusta + { + if (Load > MaxLoad) + LoadChange = abs(int(LSpeed * LastLoadChangeTime / 2.0)); //przeładowanie? // trunc zamieniam na int() + else + LoadChange = abs(int(LSpeed * LastLoadChangeTime)); + if (LSpeed< 0) //gdy rozładunek + { + LoadStatus = 2; //trwa rozładunek (włączenie naliczania czasu) + if (LoadChange != 0) //jeśli coś przeładowano + { + 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) + Load = 0; //ładunek nie może być ujemny + if ((Load == 0) || (CommandIn.Value1 < 0)) //pusto lub rozładowano żądaną ilość + LoadStatus = 4; //skończony rozładunek + if (Load == 0) LoadType = ""; //jak nic nie ma, to nie ma też nazwy + } + } + else if (LSpeed > 0) //gdy załadunek + { + LoadStatus = 1; //trwa załadunek (włączenie naliczania czasu) + if (LoadChange != 0) //jeśli coś przeładowano + { + 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)) || (CommandIn.Value1 < 0)) + LoadStatus = 4; //skończony załadunek + } + } + else LoadStatus = 4; //zerowa prędkość zmiany, to koniec + } + LD = (LoadStatus >= 4); + return LD; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::DoorBlockedFlag(void) +{ + //if (DoorBlocked=true) and (Vel<5.0) then + bool DBF = false; + if ((DoorBlocked == true) && (Vel >= 5.0)) + DBF = true; + + return DBF; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::DoorLeft(bool State) +{ +bool DL; + if ((DoorLeftOpened != State) && (DoorBlockedFlag() == false) && (Battery == true)) + { + DL = true; + DoorLeftOpened = State; + if (State == true) + { + if (CabNo > 0) + SendCtrlToNext("DoorOpen", 1, CabNo); //1=lewe, 2=prawe + else + SendCtrlToNext("DoorOpen", 2, CabNo); //zamiana + CompressedVolume = CompressedVolume - 0.003; + } + else + { + if (CabNo > 0) + SendCtrlToNext("DoorClose", 1, CabNo); + else + SendCtrlToNext("DoorClose", 2, CabNo); + } + } + else + DL = false; + return DL; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::DoorRight(bool State) +{ + bool DR; + if ((DoorRightOpened != State) && (DoorBlockedFlag() == false) && (Battery == true)) + { + DR = true; + DoorRightOpened = State; + if (State == true) + { + if (CabNo > 0) + SendCtrlToNext("DoorOpen", 2, CabNo); //1=lewe, 2=prawe + else + SendCtrlToNext("DoorOpen", 1, CabNo); //zamiana + CompressedVolume = CompressedVolume-0.003; + } + else + { + if (CabNo > 0) + SendCtrlToNext("DoorClose", 2, CabNo); + else + SendCtrlToNext("DoorClose", 1, CabNo); + } + } + else + DR = false; + + return DR; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +bool TMoverParameters::ChangeOffsetH(double DeltaOffset) +{ + bool COH; + if (TestFlag(CategoryFlag, 2) && TestFlag(RunningTrack.CategoryFlag, 2)) + { + OffsetTrackH = OffsetTrackH + DeltaOffset; +// if (abs(OffsetTrackH) > (RunningTrack.Width / 1.95 - TrackW / 2.0)) + if (abs(OffsetTrackH) > (0.5 * (RunningTrack.Width - Dim.W) - 0.05)) //Ra: może pół pojazdu od brzegu? + COH = false; //kola na granicy drogi + else + COH = true; + } + else COH = false; + + return COH; +} + + +// ************************************************************************************************* +// Q: 20160713 +// ************************************************************************************************* +AnsiString TMoverParameters::EngineDescription(int what) +{ +AnsiString outstr; + + outstr = ""; + switch (what) + { + case 0: + { + if (DamageFlag == 255) + outstr = "Totally destroyed!"; + else + { + if (TestFlag(DamageFlag, dtrain_thinwheel)) + if (Power>0.1) + outstr = "Thin wheel,"; + else + outstr = "Load shifted,"; + if (TestFlag(DamageFlag, dtrain_wheelwear)) + outstr = "Wheel wear,"; + if (TestFlag(DamageFlag, dtrain_bearing)) + outstr = "Bearing damaged,"; + if (TestFlag(DamageFlag, dtrain_coupling)) + outstr = "Coupler broken,"; + if (TestFlag(DamageFlag, dtrain_loaddamage)) + if (Power > 0.1) + outstr = "Ventilator damaged,"; + else + outstr = "Load damaged,"; + + if (TestFlag(DamageFlag, dtrain_loaddestroyed)) + if (Power > 0.1) + outstr = "Engine damaged,"; + else + outstr = "Load destroyed!,"; + if (TestFlag(DamageFlag, dtrain_axle)) + outstr = "Axle broken,"; + if (TestFlag(DamageFlag, dtrain_out)) + outstr = "DERAILED!"; + if (outstr == "") + outstr = "OK!"; + } + }; + default: outstr = "Invalid qualifier"; + } + return outstr; +} + + +// ************************************************************************************************* +// Q: 20160709 +// ************************************************************************************************* +double TMoverParameters::GetTrainsetVoltage(void) +{ + double volt; + + volt = 0.0; + if (Couplers[1].Connected != NULL) + if (TestFlag(Couplers[1].CouplingFlag, ctrain_power)) //czy jest sprzęg WN + { //najczęściej silnikowy jest z tyłu + if (Couplers[1].Connected->PantFrontVolt != 0.0) + volt=Couplers[1].Connected->PantFrontVolt; + else + if (Couplers[1].Connected->PantRearVolt != 0.0) + volt =Couplers[1].Connected->PantRearVolt; + } + if (volt == 0.0) + if (Couplers[0].Connected != NULL) + if (TestFlag(Couplers[0].CouplingFlag, ctrain_power)) //czy jest sprzęg WN + { + if (Couplers[0].Connected->PantFrontVolt != 0.0) + volt = Couplers[0].Connected->PantFrontVolt; + else + if (Couplers[0].Connected->PantRearVolt != 0.0) + volt = Couplers[0].Connected->PantRearVolt; + } + // WriteLog("GTV"); + return volt; +} + + +// ************************************************************************************************* +// +// ************************************************************************************************* +bool TMoverParameters::Physic_ReActivation(void) // DO PRZETLUMACZENIA NA KONCU +{ + bool pr; + if (PhysicActivation) + return false; + else + { + PhysicActivation = true; + LastSwitchingTime = 0; + return true; + } + +} + + +// ************************************************************************************************* +// FUNKCJE PARSERA WCZYTYWANIA PLIKU FIZYKI POJAZDU +// ************************************************************************************************* +AnsiString p0, p1, p2, p3, p4, p5, p6, p7; +AnsiString xline, sectionname, lastsectionname; +AnsiString vS; +int vI; +double vD; +bool startBPT; +bool startMPT; +bool startRLIST; +int MPTLINE, RLISTLINE, BPTLINE; +std::vector x; + + + AnsiString aCategory, aType; + double aMass, aMred, aVmax, aPWR, aHeatingP, aLightP; + int aSandCap; + + AnsiString bLoadQ, bLoadAccepted; + double bLoadSpeed, bUnLoadSpeed, bOverLoadFactor, cL, cW, cH, cCx, cFloor; + int bMaxLoad; + + AnsiString dAxle, dBearingType; + double dD, dDl, dDt, dAIM, dTw, dAd, dBd, dRmin; + + AnsiString eBrakeValve, eBM, eCompressorPower; + double eMBF, eTBF, eMaxBP, eMedMaxBP, eTareMaxBP, eMaxLBP, eMaxASBP, eRM, eBCR, eBCD, eBCM, eBCMlo, eBCMhi, eVv, eMinCP, eMaxCP, eBCS, eBSA, eBRE, eHiPP, eLoPP, eCompressorSpeed; + int eNBpA, eBVV, eBCN, eSize; + + AnsiString fCType; + double fkB, fDmaxB, fFmaxB, fkC, fDmaxC, fFmaxC, fbeta; + int fAllowedFlag; + + AnsiString gBrakeSystem, gASB, gLocalBrake, gDynamicBrake, gManualBrake, gScndS, gFSCircuit, gAutoRelay, gBrakeDelays, gBrakeHandle, gLocBrakeHandle, gCoupledCtrl; + float gIniCDelay, gSCDelay, gSCDDelay, gMaxBPMass; + int gBCPN, gBDelay1, gBDelay2, gBDelay3, gBDelay4, gMCPN, gSCPN, gSCIM; + + AnsiString hAwareSystem, hRadioStop; + double hAwareMinSpeed, hAwareDelay, hSoundSignalDelay, hEmergencyBrakeDelay; + + AnsiString iLight, iLGeneratorEngine; + double iLMaxVoltage, iLMaxCurrent; + + AnsiString jEnginePower, jSystemPower; + double jMaxVoltage, jMaxCurrent, jIntR, jMinH, jMaxH, jCSW, jMinV, jMaxV, jMinPress, jMaxPress; + int jCollectorsNo; + + AnsiString kEngineType, kTrans; + double kWindingRes, knmax, kVolt; +// int kVolt; + + double lCircuitRes; + int lImaxLo, lImaxHi, lIminLo, lIminHi; + + AnsiString mRVent; + double mRVentnmax, mRVentCutOff; + int mSize; + + double nMmax, nnMmax, nMnmax, nnmax, nnominalfill, nMstand; + int nSize; + + + +int ti(AnsiString val) +{ + return StrToInt(val); +} + +double td(AnsiString val) +{ + return val.ToDouble(); +} + +AnsiString ts(AnsiString val) +{ +//WriteLog("["+ val + "]"); + + return (AnsiString(val)); +// else return "unknown"; +} + +AnsiString tS(AnsiString val) +{ + return (val.UpperCase()); +} + + +// ************************************************************************************************* +// Q: 20160717 +// ************************************************************************************************* +int Pos(AnsiString find, AnsiString in) +{ + return (in.Pos(find)); +} + + +// ************************************************************************************************* +// Q: 20160717 +// ************************************************************************************************* +bool issection(AnsiString name) +{ + sectionname = name; + if (xline.Pos(name) > 0) + { + lastsectionname = name; + return true; + } + else return false; +} + + +// ************************************************************************************************* +// Q: 20160717 +// ************************************************************************************************* +// Pobieranie wartosci z klucza i przypisanie jej do wlasciwego typu danych 1 - string, 2 - int, 3 - double +AnsiString getkeyval(int rettype, AnsiString key) +{ + AnsiString keyname = key; + key = key + "="; + AnsiString kval, temp; + temp = xline; + int to; + + + if (Pos(key, xline) >0) // jezeli jest klucz w swkcji... + { + int klen = key.Length(); + int kpos = Pos(key, xline)-1; + temp.Delete(1, kpos+klen); + if (temp.Pos(" ") > 0) to = temp.Pos(" "); else to = 255; + kval = temp.SubString(1, to); + if (kval != "") kval = kval.Trim(); // wyciagnieta wartosc + + sectionname = StringReplace(sectionname, ":", "", TReplaceFlags() << rfReplaceAll); + sectionname = StringReplace(sectionname, ".", "", TReplaceFlags() << rfReplaceAll); +//--WriteLog(sectionname + "." + keyname + " val= [" + kval + "]"); + +// if (rettype == 1) vS = kval; +// if (kval != "" && rettype == 2) vI = StrToInt(kval); +// if (kval != "" && rettype == 3) vD = StrToFloat(kval); + } + else kval = "0"; // gdy nie bylo klucza TODO: dodac do funkcji parametr z wartoscia fabryczna + // UWAGA! 0 moze powodowac bledy, przemyslec zwracanie wartosci gdy nie ma klucza!!! + return kval; +} + + +int MARKERROR(int code, AnsiString type, AnsiString msg) +{ + WriteLog(msg); + return code; +} + + +// ************************************************************************************************* +// Q: 20160717 +// ************************************************************************************************* +// parsowanie Motor Param Table +bool TMoverParameters::readMPT(int ln, AnsiString xline) +{ + // bl, mfi, mIsat, mfi0, fi, Isat, fi0 + bool as; + int bl; + startMPT = true; + + if (ln > 0) //0 to nazwa sekcji - MotorParamTable0: + { + //--WriteLog("MPT: " + xline); + x = split(xline.c_str(), ' '); + + p0 = Trim(x[0].c_str()); + p1 = Trim(x[1].c_str()); + p2 = Trim(x[2].c_str()); + p3 = Trim(x[3].c_str()); + p4 = Trim(x[4].c_str()); + p5 = Trim(x[5].c_str()); + p6 = Trim(x[6].c_str()); + + if (AutoRelayType == 0) as = false; + bl = StrToInt(p0); // numer pozycji + + MotorParam[StrToInt(p0)].mfi = StrToFloat(p1); + MotorParam[StrToInt(p0)].mIsat = StrToFloat(p2); + MotorParam[StrToInt(p0)].mfi0 = StrToFloat(p3); + MotorParam[StrToInt(p0)].fi = StrToFloat(p4); + MotorParam[StrToInt(p0)].Isat = StrToFloat(p5); + MotorParam[StrToInt(p0)].fi0 = StrToFloat(p6); + MotorParam[StrToInt(p0)].AutoSwitch = as; + + //--WriteLog(":::: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4 + "," + p5 + "," + p6); + } + MPTLINE++; + return true; +} + + +// ************************************************************************************************* +// Q: 20160718 +// ************************************************************************************************* +// parsowanie RList +bool TMoverParameters::readRLIST(int ln, AnsiString xline) +{ + char *xxx; + startRLIST = true; + + if (ln > 0) //0 to nazwa sekcji - RList: + { + //WriteLog("RLIST: " + xline); + xline = Tab2Sp(xline); // zamieniamy taby na spacje (ile tabow tyle spacji bedzie) + + xxx = trim_and_reduce_spaces( stdstrtochar( xline.c_str() ) ); // konwertujemy na *char i ograniczamy spacje pomiedzy parametrami do jednej + + x = split(xxx, ' '); // split je wskaznik na char jak i std::string + + p0 = Trim(x[0].c_str()); + p1 = Trim(x[1].c_str()); + p2 = Trim(x[2].c_str()); + p3 = Trim(x[3].c_str()); + p4 = Trim(x[4].c_str()); + p5 = Trim(x[5].c_str()); + + int k = ln-1; + + RlistSize = s2b(mSize); + if (RlistSize > ResArraySize) ConversionError = -4 ; + + RList[k].Relay = p0.ToInt(); // byte + RList[k].R = p1.ToDouble(); // double + RList[k].Bn = p2.ToInt(); // byte + RList[k].Mn = p3.ToInt(); // byte + RList[k].AutoSwitch = false; //p4.ToInt(); + + + //--WriteLog("RLIST: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4); + } + RLISTLINE++; + return true; +} + + +// ************************************************************************************************* +// Q: 20160721 +// ************************************************************************************************* +// parsowanie Brake Param Table +bool TMoverParameters::readBPT(int ln, AnsiString xline) +{ + char *xxx; + startBPT = true; + int k; + + if (ln > 0) //0 to nazwa sekcji - Cntrl. - po niej jest tablica hamulcow + { + //WriteLog("BPT: " + xline); + xline = Tab2Sp(xline); + xxx = trim_and_reduce_spaces( stdstrtochar( xline.c_str() ) ); + x = split(xxx, ' '); + + p0 = Trim(x[0].c_str()); + p1 = Trim(x[1].c_str()); + p2 = Trim(x[2].c_str()); + p3 = Trim(x[3].c_str()); + p4 = Trim(x[4].c_str()); + + + k = s2iE(p0); + BrakePressureTable[k].PipePressureVal = p1.ToDouble(); + BrakePressureTable[k].BrakePressureVal= p2.ToDouble(); + BrakePressureTable[k].FlowSpeedVal = p3.ToDouble(); + if (p4 == "Pneumatic") BrakePressureTable[k].BrakeType = Pneumatic; else + if (p4 == "ElectroPneumatic") BrakePressureTable[k].BrakeType = ElectroPneumatic; else + BrakePressureTable[k].BrakeType = Individual; + + //-- WriteLog("BPT: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4); + } + + BPTLINE++; + return true; +} + + +// ************************************************************************************************* +// Q: 20160719 +// ************************************************************************************************* +void TMoverParameters::BrakeValveDecode(AnsiString s) +{ + if (s == "W") + BrakeValve = W; + else if (s == "W_Lu_L") + BrakeValve = W_Lu_L; + else if (s == "W_Lu_XR") + BrakeValve = W_Lu_XR; + else if (s == "W_Lu_VI") + BrakeValve = W_Lu_VI; + else if (s == "K") + BrakeValve = W; + else if (s == "Kkg") + BrakeValve = Kkg; + else if (s == "Kkp") + BrakeValve = Kkp; + else if (s == "Kks") + BrakeValve = Kks; + else if (s == "Hikp1") + BrakeValve = Hikp1; + else if (s == "Hikss") + BrakeValve = Hikss; + else if (s == "Hikg1") + BrakeValve = Hikg1; + else if (s == "KE") + BrakeValve = KE; + else if (s == "EStED") + BrakeValve = EStED; + else if (Pos("ESt", s) > 0 ) + BrakeValve = ESt3; + else if (s == "LSt") + BrakeValve = LSt; + else if (s == "EP2") + BrakeValve = EP2; + else if (s == "EP1") + BrakeValve = EP1; + else if (s == "CV1") + BrakeValve = CV1; + else if (s == "CV1_L_TR") + BrakeValve = CV1_L_TR; + else + BrakeValve = Other; +} + + +// ************************************************************************************************* +// Q: 20160719 +// ************************************************************************************************* +void TMoverParameters::BrakeSubsystemDecode() +{ + BrakeSubsystem = ss_None; + switch ( BrakeValve ) + { + case W,W_Lu_L,W_Lu_VI,W_Lu_XR: BrakeSubsystem = ss_W; break; + case ESt3,ESt3AL2,ESt4,EP2,EP1: BrakeSubsystem = ss_ESt; break; + case KE: BrakeSubsystem = ss_KE; break; + case CV1, CV1_L_TR: BrakeSubsystem = ss_Dako; break; + case LSt, EStED: BrakeSubsystem = ss_LSt; break; + } +} + + +// ************************************************************************************************* +// Q: 20160721 +// ************************************************************************************************* +TEngineTypes TMoverParameters::EngineDecode(AnsiString s) +{ + if (s =="ElectricSeriesMotor") return ElectricSeriesMotor; else + if (s =="DieselEngine") return DieselEngine; else + if (s =="SteamEngine") return SteamEngine; else + if (s =="WheelsDriven") return WheelsDriven; else + if (s =="Dumb") return Dumb; else + if (s =="DieselElectric") return DieselElectric; else //youBy: spal-ele + if (s =="DumbDE") return DieselElectric; else //youBy: spal-ele + if (s =="ElectricInductionMotor") return ElectricInductionMotor; +// else if s='EZT' then {dla kibla} +// EngineDecode:=EZT } + else return None; +} + + +// ************************************************************************************************* +// Q: 20160719 +// ************************************************************************************************* +TPowerSource TMoverParameters::PowerSourceDecode(AnsiString s) +{ + + if (s=="Transducer") return Transducer; else + if (s=="Generator") return Generator; else + if (s=="Accu") return Accumulator; else + if (s=="CurrentCollector") return CurrentCollector; else + if (s=="PowerCable") return PowerCable; else + if (s=="Heater") return Heater; else + if (s=="Internal") return InternalSource; else + return NotDefined; +} + + +// ************************************************************************************************* +// Q: 20160719 +// ************************************************************************************************* +TPowerType TMoverParameters::PowerDecode(AnsiString s) +{ + if (s=="BioPower") return BioPower; else + if (s=="BioPower") return BioPower; else + if (s=="MechPower") return MechPower; else + if (s=="ElectricPower") return ElectricPower; else + if (s=="SteamPower") return SteamPower; else + return NoPower; +} + + +// ************************************************************************************************* +// Q: 20160719 +// ************************************************************************************************* +void TMoverParameters::PowerParamDecode(AnsiString lines, AnsiString prefix, TPowerParameters &PowerParamDecode) +{ +// with PowerParamDecode do + // begin + switch ( PowerParamDecode.SourceType ) + { + //--case NotDefined : PowerType = PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType='))); + //--case InternalSource : PowerType = PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType='))); + //--case Transducer : InputVoltage = s2rE(DUE(ExtractKeyWord(lines,prefix+'TransducerInputV='))); + //--case Generator : GeneratorEngine:=EngineDecode(DUE(ExtractKeyWord(lines,prefix+'GeneratorEngine='))); + //--case Accumulator: + //--{ + //-- RAccumulator.MaxCapacity:=s2r(DUE(ExtractKeyWord(lines,prefix+'Cap='))); + //-- s:=DUE(ExtractKeyWord(lines,prefix+'RS=')); + //-- RAccumulator.RechargeSource:=PowerSourceDecode(s); + //--} + + case CurrentCollector: + { + + PowerParamDecode.CollectorParameters.CollectorsNo = s2lE(jCollectorsNo); + PowerParamDecode.CollectorParameters.MinH = s2rE(jMinH); + PowerParamDecode.CollectorParameters.MaxH = s2rE(jMaxH); + PowerParamDecode.CollectorParameters.CSW = s2rE(jCSW); //szerokość części roboczej + PowerParamDecode.CollectorParameters.MaxV = s2rE(jMaxVoltage); + + // s:=jMinV; //napięcie rozłączające WS + if (jMinV == 0) + PowerParamDecode.CollectorParameters.MinV = 0.5 * PowerParamDecode.CollectorParameters.MaxV; //gdyby parametr nie podany + else + PowerParamDecode.CollectorParameters.MinV = s2rE(jMinV); + + //-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 (jMinPress == 0) + PowerParamDecode.CollectorParameters.MinPress = 2.0; //domyślnie 2 bary do załączenia WS + else + PowerParamDecode.CollectorParameters.MinPress = s2rE(jMinPress); + //s:=ExtractKeyWord(lines,'MaxPress='); //maksymalne ciśnienie za reduktorem + if (jMaxPress == 0) + PowerParamDecode.CollectorParameters.MaxPress = 5.0+ 0.001 * (random(50)-random(50)); + else + PowerParamDecode.CollectorParameters.MaxPress = s2rE(jMaxPress); + + } + //case PowerCable: + //{ + // RPowerCable.PowerTrans:=PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerTrans='))); + // if RPowerCable.PowerTrans=SteamPower then + // RPowerCable.SteamPressure:=s2r(DUE(ExtractKeyWord(lines,prefix+'SteamPress='))); + //} + //case Heater : + //{ + // //jeszcze nie skonczone! + //} + } + + if ((PowerParamDecode.SourceType != Heater) && (PowerParamDecode.SourceType != InternalSource)) + if (! ((PowerParamDecode.SourceType == PowerCable) && (PowerParamDecode.RPowerCable.PowerTrans == SteamPower))) + { + //--MaxVoltage =s2rE(DUE(ExtractKeyWord(lines,prefix+'MaxVoltage='))); + //--MaxCurrent =s2r(DUE(ExtractKeyWord(lines,prefix+'MaxCurrent='))); + //--IntR =s2r(DUE(ExtractKeyWord(lines,prefix+'IntR='))); + } + +} + + +// ************************************************************************************************* +// Q: 20160717 +// Funkcja pelniaca role pierwotnej LoadChkFile wywolywana w dynobj.cpp w double TDynamicObject::Init() +// Po niej wykonywana jest CreateBrakeSys(), ktora jest odpowiednikiem CheckLocomotiveParameters() +// ************************************************************************************************* +bool TMoverParameters::LoadFIZ(AnsiString chkpath) +{ + const param_ok=1; + const wheels_ok=2; + const dimensions_ok=4; + int ishash; + int bl, i, k; + Byte b, OKFlag; + AnsiString lines,s, appdir; + AnsiString APPDIR, filetocheck, line, node, key, file, CERR; + string wers; + bool noexist = false; + bool OK; + + + OKFlag = 0; + LineCount = 0; + ConversionError = 666; + BPTLINE = 0; + MPTLINE = 0; + RLISTLINE = 0; + Mass = 0; + file = chkpath + TypeName + ".fiz"; + + WriteLog("LOAD FIZ FROM " + file); + +// if (!FileExists(file)) WriteLog("E8 - FIZ FILE NOT EXIST."); +// if (!FileExists(file)) return false; + +// appdir = ExtractFilePath(ParamStr(0)); + + ifstream in(file.c_str()); + + bool secBPT, secMotorParamTable0, secPower, secEngine, secParam, secLoad, secDimensions, secWheels, secBrake, secBuffCoupl, secCntrl, secSecurity, secLight, secCircuit, secRList, secDList, secWWList, secffList, secTurboPos; + + ConversionError = 0; + + // Zbieranie danych zawartych w pliku FIZ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + while(getline(in, wers)) + { + //wers.find('#'); + xline = wers.c_str(); + ishash = Pos("#", xline); + //if ((ishash == 1)) WriteLog("zakomentowane " + xline); + if ((ishash == 0)) + { + + if (xline.Length() == 0) startBPT = false; // Tablica parametyrow hamulca nie ma znacznika konca :( + if (issection("END-MPT")) startMPT = false; + if (issection("END-RL")) startRLIST = false; + + if (issection("Param.")) + { + secParam = true; + SetFlag(OKFlag, param_ok); + aCategory = ts(getkeyval(1, "Category")); + aType = tS(getkeyval(1, "Type")); + aMass = td(getkeyval(3, "M")); + aMred = td(getkeyval(3, "Mred")); + aVmax = td(getkeyval(3, "Vmax")); + aPWR = td(getkeyval(3, "PWR")); + aSandCap = ti(getkeyval(2, "SandCap")); + aHeatingP = td(getkeyval(3, "HeatingP")); + aLightP = td(getkeyval(3, "LightP")); + } + + if (issection("Load:")) + { + secLoad = true; + bMaxLoad = ti(getkeyval(2, "MaxLoad")); + bLoadQ = ts(getkeyval(1, "LoadQ")); + bLoadAccepted = ts(getkeyval(1, "LoadAccepted")); + bLoadSpeed = td(getkeyval(3, "LoadSpeed")); + bUnLoadSpeed = td(getkeyval(3, "UnLoadSpeed")); + bOverLoadFactor = td(getkeyval(3, "OverLoadFactor")); + } + + if (issection("Dimensions:")) + { + secDimensions = true; + SetFlag(OKFlag, dimensions_ok); + cL = td(getkeyval(3, "L")); + cH = td(getkeyval(3, "H")); + cW = td(getkeyval(3, "W")); + cCx = td(getkeyval(3, "Cx")); + cFloor = td(getkeyval(3, "Floor")); + } + + if (issection("Wheels:")) + { + secWheels = true; + dD = td(getkeyval(3, "D")); + dDl = td(getkeyval(3, "Dl")); + dDt = td(getkeyval(3, "Dt")); + dAIM = td(getkeyval(3, "AIM")); + dTw = td(getkeyval(3, "Tw")); + dAxle = ts(getkeyval(1, "Axle")); + dAd = td(getkeyval(3, "Ad")); + dBd = td(getkeyval(3, "Bd")); + dRmin = td(getkeyval(3, "Rmin")); + dBearingType = ts(getkeyval(1, "BearingType")); + } + + if (issection("Brake:")) + { + secBrake = true; + eBrakeValve = ts(getkeyval(1, "BrakeValve")); + eNBpA = ti(getkeyval(2, "NBpA")); + eMBF = td(getkeyval(3, "MBF")); + eTBF = td(getkeyval(3, "TBF")); + eSize = ti(getkeyval(3, "Size")); + eMaxBP = td(getkeyval(3, "MaxBP")); + eMedMaxBP = td(getkeyval(3, "MedMaxBP")); + eTareMaxBP = td(getkeyval(3, "TareMaxBP")); + eMaxLBP = td(getkeyval(3, "MaxLBP")); + eMaxASBP = td(getkeyval(3, "MaxASBP")); + eRM = td(getkeyval(3, "RM")); + eBCN = ti(getkeyval(2, "BCN")); + eBCR = td(getkeyval(3, "BCR")); + eBCD = td(getkeyval(3, "BCD")); + eBCM = td(getkeyval(3, "BCM")); + eBCMlo = td(getkeyval(3, "BCMlo")); + eBCMhi = td(getkeyval(3, "BCMhi")); + eVv = td(getkeyval(3, "Vv")); + eMinCP = td(getkeyval(3, "MinCP")); + eMaxCP = td(getkeyval(3, "MaxCP")); + eBCS = td(getkeyval(3, "BCS")); + eBSA = td(getkeyval(3, "BSA")); + eBM = ts(getkeyval(1, "BM")); + eBVV = ti(getkeyval(2, "BVV")); + eBRE = td(getkeyval(3, "BRE")); + eHiPP = td(getkeyval(3, "HiPP")); + eLoPP = td(getkeyval(3, "LoPP")); + eCompressorSpeed = td(getkeyval(3, "CompressorSpeed")); + eCompressorPower = ts(getkeyval(1, "CompressorPower")); + } + + if (issection("BuffCoupl.") || issection("BuffCoupl1.")) + { + secBuffCoupl = true; + fCType = ts(getkeyval(1, "CType")); + fkB = td(getkeyval(3, "kB")); + fDmaxB = td(getkeyval(3, "DmaxB")); + fFmaxB = td(getkeyval(3, "FmaxB")); + fkC = td(getkeyval(3, "kC")); + fDmaxC = td(getkeyval(3, "DmaxC")); + fFmaxC = td(getkeyval(3, "FmaxC")); + fbeta = td(getkeyval(3, "beta")); + fAllowedFlag = ti(getkeyval(2, "AllowedFlag")); + } + + if (issection("Cntrl.")) + { + secCntrl = true; + gBrakeSystem = ts(getkeyval(1, "BrakeSystem")); + gBCPN = ti(getkeyval(2, "BCPN")); + gBDelay1 = ti(getkeyval(2, "BDelay1")); + gBDelay2 = ti(getkeyval(2, "BDelay2")); + gBDelay3 = ti(getkeyval(2, "BDelay3")); + gBDelay4 = ti(getkeyval(2, "BDelay4")); + gASB = ts(getkeyval(1, "ASB")); + gLocalBrake = ts(getkeyval(1, "LocalBrake")); + gDynamicBrake = ts(getkeyval(1, "DynamicBrake")); + // gManualBrake = ts(getkeyval(1, "ManualBrake")); + gFSCircuit = ts(getkeyval(1, "FSCircuit")); + gMCPN = ti(getkeyval(2, "MCPN")); + gSCPN = ti(getkeyval(2, "SCPN")); + gSCIM = ti(getkeyval(2, "SCIM")); + gScndS = ts(getkeyval(1, "ScndS")); + gCoupledCtrl = ts(getkeyval(1, "CoupledCtrl")); + gAutoRelay = ts(getkeyval(1, "AutoRelay")); + gIniCDelay = td(getkeyval(3, "IniCDelay")); + gSCDelay = td(getkeyval(3, "SCDelay")); + gSCDDelay = td(getkeyval(3, "SCDDelay")); + gBrakeDelays = ts(getkeyval(1, "BrakeDelays")); + gBrakeHandle = ts(getkeyval(1, "BrakeHandle")); + gLocBrakeHandle = ts(getkeyval(1, "LocBrakeHandle")); + gMaxBPMass = td(getkeyval(3, "MaxBPMass")); + } + + if (issection("Security:")) + { + secSecurity = true; + hAwareSystem = ts(getkeyval(1, "AwareSystem")); + hAwareMinSpeed = td(getkeyval(3, "AwareMinSpeed")); + hAwareDelay = td(getkeyval(3, "AwareDelay")); + hSoundSignalDelay = td(getkeyval(3, "SoundSignalDelay")); + hEmergencyBrakeDelay = td(getkeyval(3, "EmergencyBrakeDelay")); + hRadioStop = ts(getkeyval(1, "RadioStop")); + } + + if (issection("Light:")) + { + secLight = true; + iLight = ts(getkeyval(1, "Light")); + iLGeneratorEngine = ts(getkeyval(1, "LGeneratorEngine")); + iLMaxVoltage = td(getkeyval(3, "LMaxVoltage")); + iLMaxCurrent = td(getkeyval(3, "LMaxCurrent")); + } + + if (issection("Power:")) + { + secPower = true; + jEnginePower = ts(getkeyval(1, "EnginePower")); + jSystemPower = ts(getkeyval(1, "SystemPower")); + jCollectorsNo = ti(getkeyval(2, "CollectorsNo")); + jMaxVoltage = td(getkeyval(3, "MaxVoltage")); + jMaxCurrent = td(getkeyval(3, "MaxCurrent")); + jIntR = td(getkeyval(3, "IntR")); + jMinH = td(getkeyval(3, "MinH")); + jMaxH = td(getkeyval(3, "MaxH")); + jCSW = td(getkeyval(3, "CSW")); + jMinV = td(getkeyval(3, "MinV")); + jMinPress = td(getkeyval(3, "MinPress")); + jMaxPress = td(getkeyval(3, "MaxPress")); + } + + if (issection("Engine:")) + { + secEngine = true; + kEngineType = ts(getkeyval(1, "EngineType")); + kTrans = ts(getkeyval(1, "Trans")); + kVolt = td(getkeyval(3, "Volt")); + kWindingRes = td(getkeyval(3, "WindingRes")); + knmax = td(getkeyval(3, "nmax")); + } + + if (issection("Circuit:")) + { + secCircuit = true; + lCircuitRes = td(getkeyval(3, "CircuitRes")); + lImaxLo = ti(getkeyval(2, "ImaxLo")); + lImaxHi = ti(getkeyval(2, "ImaxHi")); + lIminLo = ti(getkeyval(2, "IminLo")); + lIminHi = ti(getkeyval(2, "IminHi")); + } + + if (issection("RList:")) + { + secRList = true; + mSize = ti(getkeyval(2, "Size")); + mRVent = ts(getkeyval(1, "RVent")); + mRVentnmax = td(getkeyval(3, "RVentnmax")); + mRVentCutOff = td(getkeyval(3, "RVentCutOff")); + } + + if (issection("DList:")) + { + secDList = true; + nMmax = td(getkeyval(3, "Mmax")); + nnMmax = td(getkeyval(3, "nMmax")); + nMnmax = td(getkeyval(3, "Mnmax")); + nnmax = td(getkeyval(3, "nmax")); + nnominalfill = td(getkeyval(3, "nominalfill")); + nMstand = td(getkeyval(3, "Mstand")); + nSize = ti(getkeyval(2, "Size")); + } + + if (issection("WWList:")) + { + secWWList = true; + getkeyval(2, "Size"); + } + + if (issection("ffList:")) + { + secffList = true; + getkeyval(2, "Size"); + } + + if (issection("TurboPos:")) + { + secTurboPos = true; + getkeyval(2, "TurboPos"); + } + + if (issection("Cntrl.") || startBPT) + { + secBPT = true; + BrakeCtrlPosNo = gBCPN; + if (BrakeCtrlPosNo > 0) readBPT(BPTLINE, xline); // np wagony nie maja BPT + } + + if (issection("MotorParamTable0:") || startMPT) + { + secMotorParamTable0 = true; + readMPT(MPTLINE, xline); + } + + if (issection("RList:") || startRLIST) + { + secRList = true; + readRLIST(RLISTLINE, xline); + } + } // is hash + } // while line + + +// Sprawdzenie poprawnosci wczytanych parametrow +// WriteLog("DATA TEST: " + aCategory + ", " + aType + ", " + bLoadQ + ", " + bLoadAccepted + ", " + dAxle + ", " + dBearingType + ", " + eBrakeValve + ", " + eBM + ", " + jEnginePower + ", " + kEngineType + ", " + mRVent ); +// WriteLog(" "); +// WriteLog(" "); + + +// Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie zaleznosci + + if (aCategory == "train") CategoryFlag = 1; else + if (aCategory == "road") CategoryFlag = 2; else + if (aCategory == "ship") CategoryFlag = 4; else + if (aCategory == "airplane") CategoryFlag = 8; else + if (aCategory == "unimog") CategoryFlag = 3; else + ConversionError = MARKERROR(-7, 1, "Improper vechicle category"); + + + Mass = aMass; + Mred = aMred; + Vmax = aVmax; + Power = aPWR; + HeatingPower = aHeatingP; + LightPower = aLightP; + SandCapacity = aSandCap; + TrainType = dt_Default; + if (aType == "PSEUDODIESEL") aType = "PDIS"; + + if (aType == "EZT") {TrainType = dt_EZT; IminLo = 1; IminHi = 2; Imin = 1; } else//wirtualne wartości dla rozrządczego + if (aType == "ET41") TrainType = dt_ET41; else + if (aType == "ET42") TrainType = dt_ET42; else + if (aType == "ET22") TrainType = dt_ET22; else + if (aType == "ET40") TrainType = dt_ET40; else + if (aType == "EP05") TrainType = dt_EP05; else + if (aType == "SN61") TrainType = dt_SN61; else + if (aType == "PDIS") TrainType = dt_PseudoDiesel; else + if (aType == "181") TrainType = dt_181; else + if (aType == "182") TrainType = dt_181; //na razie tak + + MaxLoad = bMaxLoad; + LoadQuantity = bLoadQ; + OverLoadFactor = bOverLoadFactor; + LoadSpeed = bLoadSpeed; + UnLoadSpeed = bUnLoadSpeed; + Dim.L = cL; + Dim.W = cW; + Dim.H = cH; + Cx = cCx; + + if (Cx == 0) Cx = 0.3; + if (cFloor == -1) + { + if (Dim.H <= 2.0) + Floor = Dim.H; //gdyby nie było parametru, lepsze to niż zero + else + Floor = 0.0; //zgodność wsteczna + } + else Floor = cFloor; + +// Axles ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + WheelDiameter = dD; + WheelDiameterL = dDl; + WheelDiameterT = dDt; + TrackW = dTw; + AxleInertialMoment = dAIM; + AxleArangement = dAxle; + NPoweredAxles = s2NPW(AxleArangement); + NAxles = NPoweredAxles + s2NNW(AxleArangement); + BearingType = 1; + ADist = dAd; + BDist = dBd; + + if (WheelDiameterL == -1) // gdyby nie było parametru... + WheelDiameterL = WheelDiameter; //... lepsze to niż zero + else WheelDiameterL = dDl; + if (WheelDiameterT == -1) // gdyby nie było parametru... + WheelDiameterT = WheelDiameter; //... lepsze to niż zero + else WheelDiameterT = dDt; + + if (AxleInertialMoment <= 0) AxleInertialMoment = 1; + + if (NAxles == 0) ConversionError = MARKERROR(-1, 1, "0 axles, hover cat?"); + + if (dBearingType == "Roll") BearingType = 1; else BearingType = 0; +/* + WriteLog("CompressorPower " + eCompressorPower); + WriteLog("NAxles " + IntToStr(NAxles)); + WriteLog("BearingType " + dBearingType); + WriteLog("params " + BrakeValveParams); + WriteLog("NBpA " + IntToStr(NBpA)); + WriteLog("MaxBrakeForce " + FloatToStr(MaxBrakeForce)); + WriteLog("TrackBrakeForce " + FloatToStr(TrackBrakeForce)); + WriteLog("MaxBrakePress[3] " + FloatToStr(MaxBrakePress[3])); + WriteLog("BrakeCylNo " + IntToStr(BrakeCylNo)); + WriteLog("BCD " + FloatToStr(eBCD)); + WriteLog("BCR " + FloatToStr(eBCR)); + WriteLog("BCS " + FloatToStr(eBCS)); + WriteLog("BrakeHandle " + gBrakeHandle); + WriteLog("BrakeLocHandle " + gLocBrakeHandle); +*/ + +// Brakes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +if (secBrake) +{ + BrakeValveParams = eBrakeValve; + BrakeValveDecode(BrakeValveParams); + BrakeSubsystemDecode(); + NBpA = eNBpA; + MaxBrakeForce = eMBF; + BrakeValveSize = eSize; + TrackBrakeForce = eTBF * 1000; + MaxBrakePress[3] = eMaxBP; + //WriteLog("eMaxBP " + FloatToStr(MaxBrakePress[3])); + if (MaxBrakePress[3] > 0) + { + BrakeCylNo = eBCN; + if (BrakeCylNo > 0) + { + MaxBrakePress[0] = eMaxLBP; + if (MaxBrakePress[0] < 0.01) + MaxBrakePress[0] = MaxBrakePress[3]; + MaxBrakePress[1] = eTareMaxBP; + MaxBrakePress[2] = eMedMaxBP; + MaxBrakePress[4] = eMaxASBP; + if (MaxBrakePress[4] < 0.01) + MaxBrakePress[4] = 0; + BrakeCylRadius = eBCR; + BrakeCylDist = eBCD; + BrakeCylSpring = eBCS; + BrakeSlckAdj = eBSA; + if (eBRE !=0) + BrakeRigEff = eBRE; + else + BrakeRigEff = 1; + BrakeCylMult[0] = eBCM; + BrakeCylMult[1] = eBCMlo; + BrakeCylMult[2] = eBCMhi; + P2FTrans = 100 * PI * sqr(BrakeCylRadius); //w kN/bar Q: zamieniam SQR() na sqr() + if ((BrakeCylMult[1] > 0) || (MaxBrakePress[1] > 0)) LoadFlag = 1; else LoadFlag =0; // Q: zamieniam SQR() na sqr() + BrakeVolume = PI * sqr(BrakeCylRadius) * BrakeCylDist * BrakeCylNo; + BrakeVVolume = eBVV; + if (eBM == "P10-Bg") BrakeMethod = bp_P10Bg; else + if (eBM == "P10-Bgu") BrakeMethod = bp_P10Bgu; else + if (eBM == "FR513") BrakeMethod = bp_FR513; else + if (eBM == "Cosid") BrakeMethod = bp_Cosid; else + if (eBM == "P10yBg") BrakeMethod = bp_P10yBg; else + if (eBM == "P10yBgu") BrakeMethod = bp_P10yBgu; else + if (eBM == "Disk1") BrakeMethod = bp_D1; else + if (eBM == "Disk1+Mg") BrakeMethod = bp_D1+bp_MHS; else + if (eBM == "Disk2") BrakeMethod = bp_D2; else + BrakeMethod = 0; + if (eRM != 0) + RapidMult = eRM; + else + RapidMult = 1; + + } + else ConversionError = MARKERROR(-5, 1, "0 brake cylinder units"); + } + else P2FTrans = 0; + +//WriteLog("eBM=" + eBM + ", " + IntToStr(0)); + + + if (eHiPP != 0) CntrlPipePress = eHiPP; + else CntrlPipePress = 5 + 0.001*(random(10) - random(10)); //Ra 2014-07: trochę niedokładności + HighPipePress = CntrlPipePress; + + if (eHiPP != 0) LowPipePress = eLoPP; + else LowPipePress = Min0R(HighPipePress, 3.5); + + DeltaPipePress = HighPipePress-LowPipePress; + + VeselVolume = eVv; + if (VeselVolume == 0) + VeselVolume = 0.01; + + MinCompressor = eMinCP; + MaxCompressor = eMaxCP; + CompressorSpeed = eCompressorSpeed; + + if (eCompressorPower == "Converter") CompressorPower = 2; else + if (eCompressorPower == "Engine") CompressorPower = 3; else + if (eCompressorPower == "Coupler1") CompressorPower = 4; else // włączana w silnikowym EZT z przodu + if (eCompressorPower == "Coupler2") CompressorPower = 5; else // włączana w silnikowym EZT z tyłu + if (eCompressorPower == "Main") CompressorPower = 0; + +// WriteLog("params " + BrakeValveParams); +// WriteLog("NBpA " + IntToStr(NBpA)); +// WriteLog("MaxBrakeForce " + FloatToStr(MaxBrakeForce)); +// WriteLog("TrackBrakeForce " + FloatToStr(TrackBrakeForce)); +// WriteLog("MaxBrakePress[3] " + FloatToStr(MaxBrakePress[3])); +// WriteLog("BrakeCylNo " + IntToStr(BrakeCylNo)); +} + + + // Couplers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + if (fCType == "Automatic") Couplers[0].CouplerType = Automatic; else + if (fCType == "Screw") Couplers[0].CouplerType = Screw; else + if (fCType == "Chain") Couplers[0].CouplerType = Chain; else + if (fCType == "Bare") Couplers[0].CouplerType = Bare; else + if (fCType == "Articulated") Couplers[0].CouplerType = Articulated; else + Couplers[0].CouplerType = NoCoupler; + + if (fAllowedFlag > 0) Couplers[0].AllowedFlag = fAllowedFlag; + if (Couplers[0].AllowedFlag < 0) Couplers[0].AllowedFlag = ((-Couplers[0].AllowedFlag) || ctrain_depot); + if ((Couplers[0].CouplerType != NoCoupler) && (Couplers[0].CouplerType != Bare) && (Couplers[0].CouplerType != Articulated)) + { + + Couplers[0].SpringKC = fkC * 1000; + Couplers[0].DmaxC = fDmaxC; + Couplers[0].FmaxC = fFmaxC * 1000; + Couplers[0].SpringKB = fkB * 1000; + Couplers[0].DmaxB = fDmaxB; + Couplers[0].FmaxB = fFmaxB * 1000; + Couplers[0].beta = fbeta; + } + else if (Couplers[0].CouplerType == Bare) + { + Couplers[0].SpringKC = 50 * Mass + Ftmax / 0.05; + Couplers[0].DmaxC = 0.05; + Couplers[0].FmaxC = 100 * Mass + 2 * Ftmax; + Couplers[0].SpringKB = 60 * Mass + Ftmax / 0.05; + Couplers[0].DmaxB = 0.05; + Couplers[0].FmaxB = 50 * Mass + 2 * Ftmax; + Couplers[0].beta = 0.3; + } + else if (Couplers[0].CouplerType == Articulated) + { + Couplers[0].SpringKC = 60 * Mass + 1000; + Couplers[0].DmaxC = 0.05; + Couplers[0].FmaxC = 20000000 + 2 * Ftmax; + Couplers[0].SpringKB = 70 * Mass + 1000; + Couplers[0].DmaxB = 0.05; + Couplers[0].FmaxB = 4000000 + 2 * Ftmax; + Couplers[0].beta = 0.55; + } + 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; + + +// Controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +if (secCntrl) +{ + if (gBrakeSystem == "Pneumatic") BrakeSystem = Pneumatic; else + if (gBrakeSystem == "ElectroPneumatic") BrakeSystem = ElectroPneumatic; else + BrakeSystem = Individual; + + + if (BrakeSystem != Individual) + { + + BrakeCtrlPosNo = gBCPN; + BrakeDelay[1] = gBDelay1; + //BrakeDelay[2] = gBDelay2; + //BrakeDelay[3] = gBDelay3; + //BrakeDelay[4] = gBDelay4; + + if (gBrakeDelays == "GPR") BrakeDelays = bdelay_G + bdelay_P + bdelay_R; else + if (gBrakeDelays == "PR") BrakeDelays = bdelay_P + bdelay_R; else + if (gBrakeDelays == "GP") BrakeDelays = bdelay_G + bdelay_P; else + if (gBrakeDelays == "R") { BrakeDelays = bdelay_R; BrakeDelayFlag = bdelay_R; } else + if (gBrakeDelays == "P") { BrakeDelays = bdelay_P; BrakeDelayFlag = bdelay_P; } else + if (gBrakeDelays == "G") { BrakeDelays = bdelay_G; BrakeDelayFlag = bdelay_G; } else + if (gBrakeDelays == "GPR+Mg") BrakeDelays = bdelay_G + bdelay_P + bdelay_R + bdelay_M; else + if (gBrakeDelays == "PR+Mg") BrakeDelays = bdelay_P + bdelay_R + bdelay_M; + + + if (gBrakeHandle == "FV4a") BrakeHandle = FV4a; else + if (gBrakeHandle == "test") BrakeHandle = testH; else + if (gBrakeHandle == "D2") BrakeHandle = D2; else + if (gBrakeHandle == "M394") BrakeHandle = M394; else + if (gBrakeHandle == "Knorr") BrakeHandle = Knorr; else + if (gBrakeHandle == "Westinghouse") BrakeHandle = West; else + if (gBrakeHandle == "FVel6") BrakeHandle = FVel6; else + if (gBrakeHandle == "St113") BrakeHandle = St113; + + if (gLocBrakeHandle == "FD1") BrakeLocHandle = FD1; else + if (gLocBrakeHandle == "Knorr") BrakeLocHandle = Knorr; else + if (gLocBrakeHandle == "Westinghouse") BrakeLocHandle = West; + + if (gMaxBPMass != 0) MBPM = gMaxBPMass * 1000; + + if (BrakeCtrlPosNo>0) + { + if (gASB == "Manual") ASBType = 1; else + if (gASB == "Automatic") ASBType = 2; + } + else + { + if (gASB == "Yes") ASBType = 128; + } + } // BrakeSystem != individual + +// WriteLog("gLocalBrake " + gLocalBrake); +// WriteLog("gManualBrake " + gManualBrake); +// WriteLog("gManualBrake " + gManualBrake); + + if (gLocalBrake == "ManualBrake") LocalBrake = ManualBrake; else + if (gLocalBrake == "PneumaticBrake") LocalBrake = PneumaticBrake; else + if (gLocalBrake == "HydraulicBrake") LocalBrake = HydraulicBrake; else + LocalBrake = NoBrake; + + if (gManualBrake == "Yes") MBrake = true; else + MBrake = false; + + if (gDynamicBrake == "Passive") DynamicBrakeType =dbrake_passive; else + if (gDynamicBrake == "Switch") DynamicBrakeType =dbrake_switch; else + if (gDynamicBrake == "Reversal") DynamicBrakeType =dbrake_reversal; else + if (gDynamicBrake == "Automatic") DynamicBrakeType =dbrake_automatic; else + DynamicBrakeType = dbrake_none; + + MainCtrlPosNo = gMCPN; + + ScndCtrlPosNo = gSCPN; + + ScndInMain = bool(gSCIM); + + if (gAutoRelay == "Optional") AutoRelayType = 2; else + if (gAutoRelay == "Yes") AutoRelayType = 1; else + AutoRelayType = 0; + + + if (gCoupledCtrl == "Yes") CoupledCtrl = true; else //wspolny wal + CoupledCtrl = false; + + if (gScndS == "Yes") + ScndS = true; //brak pozycji rownoleglej przy niskiej nastawie PSR} + else ScndS = false; + + InitialCtrlDelay = gIniCDelay; + CtrlDelay = gSCDelay; + + + if (gSCDDelay > 0 ) CtrlDownDelay = gSCDDelay; else + CtrlDownDelay = CtrlDelay; //hunter-101012: jesli nie ma SCDDelay; + + if (gFSCircuit == "Yes") FastSerialCircuit = 1; else + FastSerialCircuit = 0; +} + + +// Security System ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +if (secSecurity) +{ + if (Pos("Active", hAwareSystem) > 0) SetFlag(SecuritySystem.SystemType, 1); + if (Pos("CabSignal", hAwareSystem) > 0) SetFlag(SecuritySystem.SystemType, 2); + if (hAwareDelay > 0) SecuritySystem.AwareDelay = hAwareDelay; + if (hAwareMinSpeed > 0) SecuritySystem.AwareMinSpeed = hAwareMinSpeed; else + SecuritySystem.AwareMinSpeed = 0.1 * Vmax; //domyślnie 10% Vmax + if (hSoundSignalDelay > 0) SecuritySystem.SoundSignalDelay = hSoundSignalDelay; + if (hEmergencyBrakeDelay > 0) SecuritySystem.EmergencyBrakeDelay = hEmergencyBrakeDelay; + if (Pos("Yes", hRadioStop) > 0) SecuritySystem.RadioStop = true; +} + + +// Power ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +if (secPower) + { + // WriteLog("EnginePower " + jEnginePower); + + if (jEnginePower != "") + { + // s:=DUE(ExtractKeyWord(lines,'EnginePower=')); + if (jEnginePower != "") + { + EnginePowerSource.SourceType = PowerSourceDecode(jEnginePower); + PowerParamDecode(xline, "", EnginePowerSource); + + if ((EnginePowerSource.SourceType == Generator) && (EnginePowerSource.GeneratorEngine == WheelsDriven)) + ConversionError = -666; //perpetuum mobile?} + if (Power == 0) //jeśli nie ma mocy, np. rozrządcze EZT + EnginePowerSource.SourceType = NotDefined; //to silnik nie ma zasilania + } + else EnginePowerSource.SourceType = NotDefined; + + + if (jSystemPower != "") + { + SystemPowerSource.SourceType = PowerSourceDecode(jSystemPower); + PowerParamDecode(xline, "", SystemPowerSource); + } + else SystemPowerSource.SourceType = NotDefined; + + } + jEnginePower = ""; // zeby nastepny pojad mial zresetowane na poczatku wczytywania + } + + +// Engine ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +if (secEngine) + { + if (kEngineType != "") + { + EngineType = EngineDecode(kEngineType); + + switch (EngineType) + { + + case ElectricSeriesMotor: + { + NominalVoltage = kVolt; + + x = split(kTrans.c_str(), ':'); // 18:79 + + p0 = Trim(x[0].c_str()); + p1 = Trim(x[1].c_str()); + + Transmision.NToothW = s2b(p1); + Transmision.NToothM = s2b(p0); + + // ToothW to drugi parametr czyli 79 + // ToothM to pierwszy czyli 18 + + //WriteLog("trans " + IntToStr(Transmision.NToothW ) + "/" + IntToStr(Transmision.NToothM )); + //if (kTrans != "") + if (Transmision.NToothM > 0) + Transmision.Ratio = Transmision.NToothW / Transmision.NToothM; + else Transmision.Ratio = 1; + + + WindingRes = kWindingRes; + if (WindingRes == 0) WindingRes = 0.01; + //WriteLog("WindingRes " + FloatToStr(WindingRes)); + + nmax = knmax / 60.0; + //WriteLog("nmax " + FloatToStr(nmax )); + + + } + + break; + } // switch + + } + kTrans = ""; + } + + +// Circuit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +if (secCircuit) + { + // s := DUE(ExtractKeyWord(lines, 'CircuitRes=')); writepaslog('CircuitRes', s); + CircuitRes = s2r(lCircuitRes); + + //s := DUE(ExtractKeyWord(lines, 'IminLo=')); writepaslog('IminLo', s); + IminLo = s2iE(lIminLo); + + //s := DUE(ExtractKeyWord(lines, 'IminHi=')); writepaslog('IminHi', s); + IminHi = s2i(lIminHi); + + //s := DUE(ExtractKeyWord(lines, 'ImaxLo=')); writepaslog('ImaxLo', s); + ImaxLo = s2iE(lImaxLo); + + //s := DUE(ExtractKeyWord(lines, 'ImaxHi=')); writepaslog('ImaxHi', s); + ImaxHi = s2i(lImaxHi); + Imin = IminLo; + Imax = ImaxLo; + } + + +// RList ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +if (secRList) + { + RlistSize = s2b(mSize); + + if (mRVent == "Automatic") RVentType = 2; else + if (mRVent == "Yes") RVentType = 1; else + RVentType = 0; + + if (RVentType > 0) + { + RVentnmax = s2rE(mRVentnmax) / 60.0; + + RVentCutOff = s2r(mRVentCutOff); + } + } + + if (ConversionError == 0) OK = true; + else OK = false; + +// WriteLog(""); +// WriteLog("----------------------------------------------------------------------------------------"); + WriteLog("CERROR: " + IntToStr(ConversionError) + ", SUCCES: " + AS(BoolToYN(OK))); +// WriteLogSS(); + WriteLog(""); + return OK; +} // LoadFIZ() + + + +// ************************************************************************************************* +// Q: 20160717 +// ************************************************************************************************* + +bool TMoverParameters::CheckLocomotiveParametersQ(bool ReadyFlag, int Dir) +{ + bool OK; + Byte b; + Byte DefBrakeTable[8] = {15,4,25,25,13,3,12,2}; + + OK = true; + + AutoRelayFlag = (AutoRelayType == 1); + Sand = SandCapacity; + + //WriteLog("aa = " + AxleArangement + " " + AnsiString( Pos("o", AxleArangement)) ); + + //if ((Pos("o", AxleArangement) > 0) && (EngineType == ElectricSeriesMotor)) + // OK = (RList[1].Bn * RList[1].Mn == NPoweredAxles); //test poprawnosci ilosci osi indywidualnie napedzanych + + + + //if ((Pos(LoadType, LoadAccepted) == 0) && (LoadType != "")) + // { + // WriteLog("Load Accepted fail"); + // Load = 0; + // OK = false; + // } + + //if (BrakeSystem == Individual) + // if (BrakeSubsystem != ss_None) + // { + // WriteLog("BrakeSubsystem fail"); + // OK = false; //! + // } + + +// if ((BrakeVVolume == 0) && (MaxBrakePress[3] > 0) && (BrakeSystem != Individual)) +// BrakeVVolume = MaxBrakePress[3] / (5 - MaxBrakePress[3]) * (BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * PI) * 1000; +// if (BrakeVVolume == 0) BrakeVVolume = 0.01; + BrakeVVolume = 0.01; //q + + switch (BrakeValve) + { + case W: + case K: + { + Hamulec = new TWest(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + //if(MBPM<2) //jesli przystawka wazaca + // (dynamic_cast(Hamulec))->SetLP(0,MaxBrakePress[3],0); + //else + // (dynamic_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case KE: + { + Hamulec = new TKE(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + // (dynamic_cast(Hamulec))->SetRM(RapidMult); + //if(MBPM<2) //jesli przystawka wazaca + // (dynamic_cast(Hamulec))->SetLP(0, MaxBrakePress[3], 0); + //else + // (dynamic_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case NESt3: + case ESt3: + case ESt3AL2: + case ESt4: + { + Hamulec = new TNESt3(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + // (dynamic_cast(Hamulec))->SetSize(BrakeValveSize,BrakeValveParams); + //if(MBPM<2) //jesli przystawka wazaca + // (dynamic_cast(Hamulec))->SetLP(0, MaxBrakePress[3], 0); + //else + // (dynamic_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + + case LSt: + { + Hamulec = new TLSt(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + //(dynamic_cast(Hamulec))->SetRM(RapidMult); + break; + } + case EStED: + { + Hamulec = new TEStED(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + //(dynamic_cast(Hamulec))->SetRM(RapidMult); + break; + } + case EP2: + { + Hamulec = new TEStEP2(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + //(dynamic_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + + case CV1: + { + Hamulec = new TCV1(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + case CV1_L_TR: + { + Hamulec = new TCV1L_TR(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + + default : Hamulec = new TBrake(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); +} + +//Hamulec->SetASBP(MaxBrakePress[4]); + + +switch (BrakeHandle) + { + case FV4a: Handle = new TFV4aM(); break; + case FVel6: Handle = new TFVel6();break; + case testH: Handle = new Ttest(); break; + case M394: Handle = new TM394(); break; + case Knorr: Handle = new TH14K1();break; + case St113: Handle = new TSt113();break; + default: Handle = new TBHandle(); + } + + +switch (BrakeLocHandle) + { + case FD1: + { + LocHandle = new TFD1(); + LocHandle->Init(MaxBrakePress[0]); + break; + } + case Knorr: + { + LocHandle = new TH1405(); + LocHandle->Init(MaxBrakePress[0]); + break; + } + default: + LocHandle = new TBHandle(); +} + + + +//ustalanie srednicy przewodu glownego (lokomotywa lub napędowy + if ((TestFlag(BrakeDelays,bdelay_G)) && ((!TestFlag(BrakeDelays,bdelay_R)) || (Power > 1))) + Spg = 0.792; + else + Spg = 0.507; + + + Pipe = new TReservoir(); + Pipe2 = new TReservoir(); //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) LightsPos = LightsDefPos; + + //to dac potem do init + + if (ReadyFlag) //gotowy do drogi + { + WriteLog("Ready to depart"); + CompressedVolume = VeselVolume * MinCompressor * (9.8 ) / 10; + ScndPipePress = CompressedVolume / VeselVolume; + PipePress = CntrlPipePress; + BrakePress = 0; + LocalBrakePos = 0; + + if (CabNo == 0) + BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor + else + BrakeCtrlPos = floor(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; + } + else + { //zahamowany} + WriteLog("Bracked"); + //Volume = BrakeVVolume * MaxBrakePress[3]; + //CompressedVolume = VeselVolume * MinCompressor * 0.55; + //ScndPipePress = 5.1; + //PipePress = LowPipePress; + //PipeBrakePress = MaxBrakePress[3]; + //BrakePress = MaxBrakePress[3]; + //LocalBrakePos = 0; + //BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor + //LimPipePress = LowPipePress; + } + + //ActFlowSpeed = 0; + //BrakeCtrlPosR = BrakeCtrlPos; + + //if (BrakeLocHandle == Knorr) + // LocalBrakePos = 5; + + //Pipe->CreatePress(PipePress); + //Pipe2->CreatePress(ScndPipePress); + //Pipe->Act(); + //Pipe2->Act(); + + //EqvtPipePress = PipePress; + + //Handle->Init(PipePress); + + //--ComputeConstans(); // TODO: przeinesiono do mover.cpp + + + if (LoadFlag > 0) + { + if (Load < MaxLoad * 0.45) + { + IncBrakeMult();IncBrakeMult();DecBrakeMult(); // TODO: przeinesiono do mover.cpp + if(Load= MaxLoad * 0.45) + { + IncBrakeMult(); // TODO: przeinesiono do mover.cpp + if(Load>=MaxLoad * 0.55) + IncBrakeMult(); + } + } + +//taki mini automat - powinno byc ladnie dobrze :) +// BrakeDelayFlag = bdelay_P; +// if ((TestFlag(BrakeDelays, bdelay_G)) && !(TestFlag(BrakeDelays, bdelay_R))) +// BrakeDelayFlag = bdelay_G; +// if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G))) +// BrakeDelayFlag = bdelay_R; + +//yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)% +// for ( b=1; b<4; b++) +// { +// if (BrakeDelay[b] == 0) +// BrakeDelay[b] = DefBrakeTable[b]; +// BrakeDelay[b] = BrakeDelay[b] * (2.5 + random(0.0, 0.2)) / 3.0; +// } + + //if(TrainType == dt_ET22) + // CompressorPower = 0; + + //Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag); + + //ScndPipePress = Compressor; + WriteLogSS("OK=", BoolTo10(OK)); + + return OK; +} + + +// ************************************************************************************************* +// Q: 20160717 +// Funkcja pelniaca role pierwotnej CheckLocomotiveParameters(bool ReadyFlag, int Dir) +// wywolywana w dynobj.cpp w double TDynamicObject::Init() +// ************************************************************************************************* +bool TMoverParameters::CreateBrakeSys() +{ + WriteLog("check locomotive parameters..."); + Byte b; + bool OK = true; + + AutoRelayFlag = (AutoRelayType == 1); + + Sand = SandCapacity; + + //WriteLog("aa = " + AxleArangement + " " + AnsiString( Pos("o", AxleArangement)) ); + + if ((Pos("o", AxleArangement) > 0) && (EngineType == ElectricSeriesMotor)) + OK = (RList[1].Bn * RList[1].Mn == NPoweredAxles); //test poprawnosci ilosci osi indywidualnie napedzanych + //WriteLogSS("aa ok", BoolToYN(OK)); + + if (BrakeSystem == Individual) + if (BrakeSubsystem != ss_None) + OK = false; //! + + + if((BrakeVVolume == 0) && (MaxBrakePress[3] > 0 ) && (BrakeSystem != Individual)) + BrakeVVolume = MaxBrakePress[3] / (5-MaxBrakePress[3]) * (BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * PI) * 1000; + if (BrakeVVolume == 0) BrakeVVolume = 0.01; + + //WriteLog("BVV = " + FloatToStr(BrakeVVolume)); + + + if ((TestFlag(BrakeDelays,bdelay_G)) && ((!TestFlag(BrakeDelays,bdelay_R)) || (Power>1))) //ustalanie srednicy przewodu glownego (lokomotywa lub napędowy + Spg = 0.792; + else + Spg = 0.507; + + //WriteLog("SPG = " + FloatToStr(Spg)); + + + switch (BrakeValve) + { + case W: + case K: + { + WriteLog("XBT W, K"); + Hamulec = new TWest(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + if(MBPM<2) //jesli przystawka wazaca + (static_cast(Hamulec))->SetLP(0,MaxBrakePress[3],0); + else + (static_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case KE: + { + WriteLog("XBT WKE"); + Hamulec = new TKE(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + (static_cast(Hamulec))->SetRM(RapidMult); + if(MBPM<2) //jesli przystawka wazaca + (static_cast(Hamulec))->SetLP(0, MaxBrakePress[3], 0); + else + (static_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case NESt3: + case ESt3: + case ESt3AL2: + case ESt4: + { + WriteLog("XBT NESt3, ESt3, ESt3AL2, ESt4"); + Hamulec = new TNESt3(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + (static_cast(Hamulec))->SetSize(BrakeValveSize,BrakeValveParams); + if(MBPM<2) //jesli przystawka wazaca + (static_cast(Hamulec))->SetLP(0, MaxBrakePress[3], 0); + else + (static_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + + case LSt: + { + WriteLog("XBT LSt"); + Hamulec = new TLSt(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + (static_cast(Hamulec))->SetRM(RapidMult); + break; + } + case EStED : + { + WriteLog("XBT EStED"); + Hamulec = new TEStED(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + (static_cast(Hamulec))->SetRM(RapidMult); + break; + } + case EP2: + { + WriteLog("XBT EP2"); + Hamulec = new TEStEP2(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + (static_cast(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + + case CV1: + { + WriteLog("XBT CV1"); + Hamulec = new TCV1(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + case CV1_L_TR: + { + WriteLog("XBT CV1_L_T"); + Hamulec = new TCV1L_TR(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + + default : Hamulec = new TBrake(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + } + + Hamulec->SetASBP(MaxBrakePress[4]); + + + switch (BrakeHandle) + { + case FV4a: Handle = new TFV4aM(); break; + case FVel6: Handle = new TFVel6();break; + case testH: Handle = new Ttest(); break; + case M394: Handle = new TM394(); break; + case Knorr: Handle = new TH14K1();break; + case St113: Handle = new TSt113();break; + default: Handle = new TBHandle(); + } + + + switch (BrakeLocHandle) + { + case FD1: + { + LocHandle = new TFD1(); + LocHandle->Init(MaxBrakePress[0]); + break; + } + case Knorr: + { + LocHandle = new TH1405(); + LocHandle->Init(MaxBrakePress[0]); + break; + } + default: + LocHandle = new TBHandle(); + } + + Pipe = new TReservoir(); + Pipe2 = new TReservoir(); //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) LightsPos = LightsDefPos; + + // checking ready flag + //to dac potem do init + bool ReadyFlag = true; + if (ReadyFlag) //gotowy do drogi + { + //WriteLog("Ready to depart"); + CompressedVolume = VeselVolume * MinCompressor * (9.8 ) / 10; + ScndPipePress = CompressedVolume / VeselVolume; + PipePress = CntrlPipePress; + BrakePress = 0; + LocalBrakePos = 0; + + if (CabNo == 0) + BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor + else + BrakeCtrlPos = floor(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; + } + else + { //zahamowany} + //WriteLog("Bracked"); + //Volume = BrakeVVolume * MaxBrakePress[3]; + //CompressedVolume = VeselVolume * MinCompressor * 0.55; + //ScndPipePress = 5.1; + //PipePress = LowPipePress; + //PipeBrakePress = MaxBrakePress[3]; + //BrakePress = MaxBrakePress[3]; + //LocalBrakePos = 0; + //BrakeCtrlPos = Trunc(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor + //LimPipePress = LowPipePress; + } + + + ActFlowSpeed =0; + BrakeCtrlPosR =BrakeCtrlPos; + +// if(BrakeLocHandle==Knorr) +// LocalBrakePos =5; + + Pipe->CreatePress(PipePress); + Pipe2->CreatePress(ScndPipePress); + Pipe->Act(); + Pipe2->Act(); + + EqvtPipePress =PipePress; + + Handle->Init(PipePress); + +//taki mini automat - powinno byc ladnie dobrze :) + BrakeDelayFlag = bdelay_P; + if ((TestFlag(BrakeDelays, bdelay_G)) && !(TestFlag(BrakeDelays, bdelay_R))) + BrakeDelayFlag = bdelay_G; + if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G))) + BrakeDelayFlag = bdelay_R; + + Byte DefBrakeTable[8] = {15,4,25,25,13,3,12,2}; + +//yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)% +// for ( b=1; b<4; b++) +// { +// if (BrakeDelay[b] == 0) +// BrakeDelay[b] = DefBrakeTable[b]; +// BrakeDelay[b] = BrakeDelay[b] * (2.5 + random(0.0, 0.2)) / 3.0; +// } + +// if(TrainType == dt_ET22) +// CompressorPower = 0; + + Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag); + + ScndPipePress = Compressor; + + //WriteLogSS("OK=", BoolTo10(OK)); + WriteLog(""); + + return OK; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +void TMoverParameters::PutCommand(AnsiString NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation) +{ + CommandLast = NewCommand; //zapamiętanie komendy + CommandIn.Command = NewCommand; + CommandIn.Value1 = NewValue1; + CommandIn.Value2 = NewValue2; + CommandIn.Location = NewLocation; + //czy uruchomic tu RunInternalCommand? nie wiem +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +double TMoverParameters::GetExternalCommand(AnsiString &Command) +{ + Command = CommandOut; + return ValueOut; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +bool TMoverParameters::SendCtrlBroadcast(AnsiString CtrlCommand, double ctrlvalue) +{ + Byte b; + bool OK; + + OK = ((CtrlCommand != CommandIn.Command) && (ctrlvalue != CommandIn.Value1)); +// if (OK) +// for (b=0; b<1; b++ ) +// if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll)) +// if (Couplers[b].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, DirF(b))) +// OK = (Couplers[b].Connected->RunInternalCommand() || OK); + + return OK; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +bool TMoverParameters::SetInternalCommand(AnsiString NewCommand, double NewValue1, double NewValue2) +{ + bool SIC; + if ((CommandIn.Command == NewCommand) && (CommandIn.Value1 == NewValue1) && (CommandIn.Value2 == NewValue2)) + SIC = false; + else + { + CommandIn.Command = NewCommand; + CommandIn.Value1 = NewValue1; + CommandIn.Value2 = NewValue2; + SIC = true; + LastLoadChangeTime = 0; //zerowanie czasu (roz)ładowania + } + + return SIC; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +bool TMoverParameters::SendCtrlToNext(AnsiString CtrlCommand, double ctrlvalue, double dir) +{ + bool OK; + int d; //numer sprzęgu w kierunku którego wysyłamy + +//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)) / 2; //dir=-1=>d=0, dir=1=>d=1 - wysyłanie tylko w tył +//- if (OK) //musi być wybrana niezerowa kabina +//with Couplers[d] do //własny sprzęg od strony (d) +//- if (TestFlag(Couplers[d].CouplingFlag, ctrain_controll)) +//- if (Couplers[d].ConnectedNr != d) //jeśli ten nastpęny jest zgodny z aktualnym +//- { +//- if (Couplers[d].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, dir)) +//- OK = (Couplers[d].Connected->RunInternalCommand() && OK); //tu jest rekurencja +//- } +//- else //jeśli następny jest ustawiony przeciwnie, zmieniamy kierunek +//- if (Couplers[d].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, -dir)) +//- OK = (Couplers[d].Connected->RunInternalCommand() && OK); //tu jest rekurencja + return OK; +} + + +// ************************************************************************************************* +// Q: 20160723 +// ************************************************************************************************* +//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ę. +bool TMoverParameters::RunCommand(AnsiString command, double CValue1, double CValue2) +{ + bool OK; + AnsiString testload; + 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 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 // TODO: funkcja przeniesiona do mover.cpp + //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 // moe ma w pas TODO: + //-- 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 (Load0 then //nazwa jest obecna w CHK + //- OK:=LoadingDone(Min0R(CValue2,LoadSpeed),testload); //zmienia LoadStatus // przeniesione do mover.cpp + //- 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); // przeniesione do mover.cpp + //- end; + //if OK then LoadStatus:=0; + end; + RunCommand:=OK; //dla true komenda będzie usunięta, dla false wykonana ponownie + + */ + return OK; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +bool TMoverParameters::RunInternalCommand(void) +{ + bool OK; + + if (CommandIn.Command != "") + { + OK = RunCommand(CommandIn.Command,CommandIn.Value1,CommandIn.Value2); + if (OK) + + { + CommandIn.Command = ""; //kasowanie bo rozkaz wykonany + CommandIn.Value1 = 0; + CommandIn.Value2 = 0; + CommandIn.Location.X = 0; + CommandIn.Location.Y = 0; + CommandIn.Location.Z = 0; + if (!PhysicActivation) + Physic_ReActivation(); + } + } + else + OK = false; + return OK; +} + + +// ************************************************************************************************* +// Q: 20160714 +// ************************************************************************************************* +int TMoverParameters::ShowCurrentP(Byte AmpN) +{ + Byte b,Bn; + bool Grupowy; + + //ClearPendingExceptions; + Grupowy = ((DelayCtrlFlag) && (TrainType == dt_ET22)); //przerzucanie walu grupowego w ET22; + Bn = RList[MainCtrlActualPos].Bn; //ile równoległych gałęzi silników + + if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) + Bn = 2; + if (Power > 0.01) + { + if (AmpN > 0) //podać prąd w gałęzi + { + if ((BnPower > 0.01) + return Couplers[b].Connected->ShowCurrent(AmpN); + +} + + + + + + + + + + + + +