From 3e000eae29e1180a51e67c9e774930bf001dcb85 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Fri, 28 Apr 2017 02:59:51 +0200 Subject: [PATCH] build 170427. improved multi-unit simulation accuracy, high voltage couplers modification --- DynObj.cpp | 98 +++++++----- McZapkie/MOVER.h | 58 +++++-- McZapkie/Mover.cpp | 365 ++++++++++++++++++++++++++++++--------------- Train.cpp | 256 +++++++++++++------------------ World.cpp | 44 ++++-- 5 files changed, 490 insertions(+), 331 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 36b09abb..f63f6c0e 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -798,7 +798,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) btnOn = true; } // else btCPass2.TurnOff(); - if (MoverParameters->Battery) + if (MoverParameters->Battery || MoverParameters->ConverterFlag) { // sygnaly konca pociagu if (btEndSignals1.Active()) { @@ -900,7 +900,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) // Ra: przechyłkę załatwiamy na etapie przesuwania modelu // if (ObjSqrDist<80000) ABuModelRoll(); //przechyłki od 400m } - if (MoverParameters->Battery) + if( MoverParameters->Battery || MoverParameters->ConverterFlag ) { // sygnały czoła pociagu //Ra: wyświetlamy bez // ograniczeń odległości, by były widoczne z // daleka @@ -1778,9 +1778,9 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" MoverParameters->PipePress = 0.0; MoverParameters->Pipe2->CreatePress(0.0); MoverParameters->ScndPipePress = 0.0; - MoverParameters->PantVolume = 1; - MoverParameters->PantPress = 0; - MoverParameters->CompressedVolume = 0; + MoverParameters->PantVolume = 0.1; + MoverParameters->PantPress = 0.0; + MoverParameters->CompressedVolume = 0.0; } if (ActPar.find('1') != std::string::npos) // wylaczanie 10% @@ -2456,30 +2456,41 @@ bool TDynamicObject::Update(double dt, double dt1) // McZapkie-260202 if ((MoverParameters->EnginePowerSource.SourceType == CurrentCollector) && (MoverParameters->Power > 1.0)) // aby rozrządczy nie opuszczał silnikowemu +/* if ((MechInside) || (MoverParameters->TrainType == dt_EZT)) { +*/ // if // ((!MoverParameters->PantCompFlag)&&(MoverParameters->CompressedVolume>=2.8)) // MoverParameters->PantVolume=MoverParameters->CompressedVolume; - if (MoverParameters->PantPress < (MoverParameters->TrainType == dt_EZT ? 2.4 : 3.5)) - { // 3.5 wg - // http://www.transportszynowy.pl/eu06-07pneumat.php - //"Wyłączniki ciśnieniowe odbieraków prądu wyłączają sterowanie - // wyłącznika szybkiego - // oraz uniemożliwiają podniesienie odbieraków prądu, gdy w instalacji - // rozrządu - // ciśnienie spadnie poniżej wartości 3,5 bara." + if( MoverParameters->PantPress < ( MoverParameters->TrainType == dt_EZT ? 2.5 : 3.5 ) ) { + // 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php // Ra 2013-12: Niebugocław mówi, że w EZT podnoszą się przy 2.5 - // if (!MoverParameters->PantCompFlag) - // MoverParameters->PantVolume=MoverParameters->CompressedVolume; - MoverParameters->PantFront(false); // opuszczenie pantografów przy niskim ciśnieniu - MoverParameters->PantRear(false); // to idzie w ukrotnieniu, a nie powinno... + if( true == MoverParameters->PantPressSwitchActive ) { + // opuszczenie pantografów przy niskim ciśnieniu + MoverParameters->PantFront( false, MoverParameters->TrainType == dt_EZT ); + MoverParameters->PantRear( false, MoverParameters->TrainType == dt_EZT ); + // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage + if( MoverParameters->GetTrainsetVoltage() == 0.0 ) { + MoverParameters->MainSwitch( false, false ); + } + // mark the pressure switch as spent + MoverParameters->PantPressSwitchActive = false; + } } - // Winger - automatyczne wylaczanie malej sprezarki - else if (MoverParameters->PantPress >= 4.8) - MoverParameters->PantCompFlag = false; - } // Ra: do Mover to trzeba przenieść, żeby AI też mogło sobie podpompować + else { + // prime the pressure switch + // TODO: check what decides whether the pressure switch is active, prototypically + MoverParameters->PantPressSwitchActive = true; + if( MoverParameters->PantPress >= 4.8 ) { + // Winger - automatyczne wylaczanie malej sprezarki + MoverParameters->PantCompFlag = false; + } + } +/* + } // Ra: do Mover to trzeba przenieść, żeby AI też mogło sobie podpompować +*/ double dDOMoveLen; TLocation l; @@ -2911,14 +2922,25 @@ bool TDynamicObject::Update(double dt, double dt1) // fragment "z EXE Kursa" if (MoverParameters->Mains) // nie wchodzić w funkcję bez potrzeby - if ( ( false == MoverParameters->Battery) + if ( ( false == MoverParameters->Battery ) && ( false == MoverParameters->ConverterFlag ) // added alternative power source. TODO: more generic power check - && ( Controller == Humandriver) +/* + // NOTE: disabled on account of multi-unit setups, where the unmanned unit wouldn't be affected + && ( Controller == Humandriver ) +*/ && ( MoverParameters->EngineType != DieselEngine ) && ( MoverParameters->EngineType != WheelsDriven ) ) { // jeśli bateria wyłączona, a nie diesel ani drezyna reczna - if (MoverParameters->MainSwitch(false)) // wyłączyć zasilanie + if( MoverParameters->MainSwitch( false, MoverParameters->TrainType == dt_EZT ) ) { + // wyłączyć zasilanie + // NOTE: we turn off entire EMU, but only the affected unit for other multi-unit consists MoverParameters->EventFlag = true; + // drop pantographs + // NOTE: this isn't universal behaviour + // TODO: have this dependant on .fiz-driven flag + MoverParameters->PantFront( false, MoverParameters->TrainType == dt_EZT ); + MoverParameters->PantRear( false, MoverParameters->TrainType == dt_EZT ); + } } if (MoverParameters->TrainType == dt_ET42) { // powinny być wszystkie dwuczłony oraz EZT @@ -3210,21 +3232,23 @@ bool TDynamicObject::Update(double dt, double dt1) MoverParameters->PantRearVolt = 0.0; break; } // pozostałe na razie nie obsługiwane - if (MoverParameters->PantPress > - (MoverParameters->TrainType == dt_EZT ? 2.5 : 3.3)) // Ra 2013-12: - // Niebugocław - // mówi, że w EZT - // podnoszą się - // przy 2.5 - pantspeedfactor = 0.015 * (MoverParameters->PantPress) * - dt1; // z EXE Kursa //Ra: wysokość zależy od ciśnienia !!! - else + if( MoverParameters->PantPress > ( + MoverParameters->TrainType == dt_EZT ? + 2.45 : // Ra 2013-12: Niebugocław mówi, że w EZT podnoszą się przy 2.5 + 3.45 ) ) { + // z EXE Kursa + // Ra: wysokość zależy od ciśnienia !!! + pantspeedfactor = 0.015 * ( MoverParameters->PantPress ) * dt1; + } + else { pantspeedfactor = 0.0; - if (pantspeedfactor < 0) - pantspeedfactor = 0; + } + pantspeedfactor = std::max( 0.0, pantspeedfactor ); k = p->fAngleL; - if (i ? MoverParameters->PantRearUp : - MoverParameters->PantFrontUp) // jeśli ma być podniesiony + if( ( pantspeedfactor > 0.0 ) + && ( i ? + MoverParameters->PantRearUp : + MoverParameters->PantFrontUp ) )// jeśli ma być podniesiony { if (PantDiff > 0.001) // jeśli nie dolega do drutu { // jeśli poprzednia wysokość jest mniejsza niż pożądana, zwiększyć kąt diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index c2c53086..9a390ae7 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -139,7 +139,17 @@ 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 - +enum coupling { + faux = 0x0, + coupler = 0x1, + brakehose = 0x2, + control = 0x4, + highvoltage = 0x8, + gangway = 0x10, + mainhose = 0x20, + heating = 0x40, + permanent = 0x80 +}; /*typ hamulca elektrodynamicznego*/ static int const dbrake_none = 0; static int const dbrake_passive = 1; @@ -360,14 +370,14 @@ struct TBoilerType { }; /*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 + long CollectorsNo{ 0.0 }; //musi być tu, bo inaczej się kopie + double MinH{ 0.0 }; double MaxH{ 0.0 }; //zakres ruchu pantografu, nigdzie nie używany + double CSW{ 0.0 }; //szerokość części roboczej (styku) ślizgacza + double MinV{ 0.0 }; double MaxV{ 0.0 }; //minimalne i maksymalne akceptowane napięcie + double OVP{ 0.0 }; //czy jest przekaznik nadnapieciowy + double InsetV{ 0.0 }; //minimalne napięcie wymagane do załączenia + double MinPress{ 0.0 }; //minimalne ciśnienie do załączenia WS + double MaxPress{ 0.0 }; //maksymalne ciśnienie za reduktorem //inline TCurrentCollector() { // CollectorsNo = 0; // MinH, MaxH, CSW, MinV, MaxV = 0.0; @@ -536,6 +546,11 @@ struct TTransmision enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic }; +struct power_coupling { + double outgoing{ 0.0 }; // power generated by coupling owner + double incoming{ 0.0 }; // power supplied from outside source +}; + struct TCoupling { /*parametry*/ double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */ @@ -556,6 +571,9 @@ struct TCoupling { double CForce = 0.0; /*sila z jaka dzialal*/ double Dist = 0.0; /*strzalka ugiecia zderzaków*/ bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/ + + power_coupling power_high; + power_coupling power_low; // TODO: implement this }; class TMoverParameters @@ -768,7 +786,17 @@ public: TRotation Rot; std::string Name; /*nazwa wlasna*/ TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami - double HVCouplers[2][2]; //przewod WN + enum side { + front = 0, + rear + }; +#ifdef EU07_USE_OLD_HVCOUPLERS + double HVCouplers[ 2 ][ 2 ]; //przewod WN + enum hvcoupler { + incoming = 0, + outgoing + }; +#endif int ScanCounter = 0; /*pomocnicze do skanowania sprzegow*/ bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/ int SoundFlag = 0; /*!o patrz stale sound_ */ @@ -804,6 +832,7 @@ public: bool CompressorFlag = false; /*!o czy wlaczona sprezarka*/ bool PantCompFlag = false; /*!o czy wlaczona sprezarka pantografow*/ bool CompressorAllow = false; /*! zezwolenie na uruchomienie sprezarki NBMX*/ + bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure bool ConverterFlag = false ; /*! czy wlaczona przetwornica NBMX*/ bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/ int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/ @@ -886,7 +915,8 @@ public: double RventRot = 0.0; /*!s obroty wentylatorow rozruchowych*/ bool UnBrake = false; /*w EZT - nacisniete odhamowywanie*/ double PantPress = 0.0; /*Cisnienie w zbiornikach pantografow*/ - bool s_CAtestebrake = false; //hunter-091012: zmienna dla testu ca + bool PantPressSwitchActive{ false }; // state of the pantograph pressure switch. gets primed when the pantograph is up + bool s_CAtestebrake = false; //hunter-091012: zmienna dla testu ca /*-zmienne dla lokomotywy spalinowej z przekladnia mechaniczna*/ double dizel_fill = 0.0; /*napelnienie*/ @@ -1058,7 +1088,7 @@ public: /*--funkcje dla lokomotyw*/ bool DirectionBackward(void);/*! kierunek ruchu*/ - bool MainSwitch(bool State);/*! wylacznik glowny*/ + bool MainSwitch( bool const State, bool const Multiunitcontrol = true );/*! wylacznik glowny*/ bool ConverterSwitch(bool State);/*! wl/wyl przetwornicy*/ bool CompressorSwitch(bool State);/*! wl/wyl sprezarki*/ @@ -1086,8 +1116,8 @@ public: bool AutoRelayCheck(void);//symulacja automatycznego rozruchu bool ResistorsFlagCheck(void); //sprawdzenie kontrolki oporow rozruchowych NBMX - bool PantFront(bool State); //obsluga pantografou przedniego - bool PantRear(bool State); //obsluga pantografu tylnego + bool PantFront(bool const State, bool const Multiunitcontrol = true ); //obsluga pantografou przedniego + bool PantRear(bool const State, bool const Multiunitcontrol = true ); //obsluga pantografu tylnego /*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/ bool dizel_EngageSwitch(double state); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index a5a10dd5..cd4ebad1 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -337,11 +337,12 @@ Name( NameInit ) Couplers[b].DmaxC = 0.1; Couplers[b].FmaxC = 1000.0; } - for(int b = 0; b < 2; ++b ) { +#ifdef EU07_USE_OLD_HVCOUPLERS + for( int b = 0; b < 2; ++b ) { HVCouplers[ b ][ 0 ] = 0.0; HVCouplers[ b ][ 1 ] = 0.0; } - +#endif for( int b = 0; b < 3; ++b ) { BrakeCylMult[ b ] = 0.0; } @@ -709,21 +710,19 @@ void TMoverParameters::UpdatePantVolume(double dt) // 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: 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ę + // NOTE: custom variant for EMU disabled because it pretty much doesn't work 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 + { // 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 + PantPress = ScndPipePress; + // ograniczenie ciśnienia do MaxPress (tylko w pantografach!) + PantPress = std::min( PantPress, EnginePowerSource.CollectorParameters.MaxPress ); + PantPress = std::max( PantPress, 0.0 ); PantVolume = (PantPress + 1.0) * 0.1; // objętość, na wypadek odcięcia kurkiem } else @@ -733,19 +732,34 @@ void TMoverParameters::UpdatePantVolume(double dt) (2.0 * 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 + PantPress = std::min( (10.0 * PantVolume) - 1.0, EnginePowerSource.CollectorParameters.MaxPress ); // tu by się przydała objętość zbiornika + PantPress = std::max( PantPress, 0.0 ); } 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( Mains ) { + // nie wchodzić w funkcję bez potrzeby + if( EngineType == ElectricSeriesMotor ) { + // nie dotyczy... czego właściwie? + if( ( true == PantPressSwitchActive ) + && ( PantPress < EnginePowerSource.CollectorParameters.MinPress ) ) { + // wywalenie szybkiego z powodu niskiego ciśnienia + if( GetTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV ) { + // to jest trochę proteza; zasilanie członu może być przez sprzęg WN + if( MainSwitch( false, TrainType == dt_EZT ) ) { + EventFlag = true; + } + } +/* + // NOTE: disabled, the flag gets set in dynobj.update() when the pantograph actually drops + // mark the pressure switch as spent, regardless whether line breaker actually opened + PantPressSwitchActive = false; +*/ + } + } + } +/* + // NOTE: pantograph tank pressure sharing experimentally disabled for more accurate simulation 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) @@ -757,6 +771,7 @@ void TMoverParameters::UpdatePantVolume(double dt) // 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 @@ -1059,57 +1074,99 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap { const double Vepsilon = 1e-5; const double Aepsilon = 1e-3; // ASBSpeed=0.8; - int b; - double Vprev, AccSprev, d, hvc; + double Vprev, AccSprev, d; // T_MoverParameters::ComputeMovement(dt, dt1, Shape, Track, ElectricTraction, NewLoc, NewRot); // // najpierw kawalek z funkcji w pliku mover.pas TotalCurrent = 0; - hvc = Max0R(Max0R(PantFrontVolt, PantRearVolt), ElectricTraction.TractionVoltage * 0.9); - for (b = 0; b < 2; b++) // przekazywanie napiec - if (((Couplers[b].CouplingFlag & ctrain_power) == ctrain_power) || - (((Couplers[b].CouplingFlag & ctrain_heating) == ctrain_heating) && (Heating))) - { - HVCouplers[1 - b][1] = - Max0R(abs(hvc), Couplers[b].Connected->HVCouplers[Couplers[b].ConnectedNr][1] - - HVCouplers[b][0] * 0.02); + double hvc = + std::max( + std::max( + PantFrontVolt, + PantRearVolt ), + ElectricTraction.TractionVoltage * 0.9 ); + + for( int side = 0; side < 2; ++side ) { + // przekazywanie napiec + auto const oppositeside = ( side == side::front ? side::rear : side::front ); + + if( ( Couplers[ side ].CouplingFlag & ctrain_power ) + || ( ( Heating ) + && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { +#ifdef EU07_USE_OLD_HVCOUPLERS + HVCouplers[ oppositeside ][ hvcoupler::outgoing ] = + std::max( + std::abs( hvc ), + Couplers[ side ].Connected->HVCouplers[ Couplers[ side ].ConnectedNr ][ hvcoupler::outgoing ] - HVCouplers[ side ][ hvcoupler::incoming ] * 0.02 ); +#else + auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ]; + Couplers[ oppositeside ].power_high.outgoing = + std::max( + std::abs( hvc ), + connectedcoupler.power_high.outgoing - Couplers[ side ].power_high.incoming * 0.02 ); +#endif } - else - HVCouplers[1 - b][1] = abs(hvc) - HVCouplers[b][0] * 0.02; - // Max0R(Abs(Voltage),0); - // end; + else { +#ifdef EU07_USE_OLD_HVCOUPLERS + HVCouplers[ oppositeside ][ hvcoupler::outgoing ] = abs( hvc ) - HVCouplers[ side ][ hvcoupler::incoming ] * 0.02; +#else + Couplers[ oppositeside ].power_high.outgoing = std::abs( hvc ) - Couplers[ side ].power_high.incoming * 0.02; +#endif + } + } - hvc = HVCouplers[0][1] + HVCouplers[1][1]; +#ifdef EU07_USE_OLD_HVCOUPLERS + hvc = HVCouplers[ side::front ][ hvcoupler::outgoing ] + HVCouplers[ side::rear ][ hvcoupler::outgoing ]; +#else + hvc = Couplers[ side::front ].power_high.outgoing + Couplers[ side::rear ].power_high.outgoing; +#endif - if ((abs(PantFrontVolt) + abs(PantRearVolt) < 1) && - (hvc > 1)) // bez napiecia, ale jest cos na sprzegach: - { - for (b = 0; b < 2; ++b) // przekazywanie pradow - if (((Couplers[b].CouplingFlag & ctrain_power) == ctrain_power) || - (((Couplers[b].CouplingFlag & ctrain_heating) == ctrain_heating) && - (Heating))) // jesli spiety - { - HVCouplers[b][0] = - Couplers[b].Connected->HVCouplers[1 - Couplers[b].ConnectedNr][0] + - Itot * HVCouplers[b][1] / hvc; // obciążenie rozkladane stosownie do napiec - } - else // pierwszy pojazd - { - HVCouplers[b][0] = Itot * HVCouplers[b][1] / hvc; - } + if( ( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) < 1.0 ) + && ( hvc > 1.0 ) ) { + // bez napiecia, ale jest cos na sprzegach: + // przekazywanie pradow + for( int side = 0; side < 2; ++side ) { + + if( ( Couplers[ side ].CouplingFlag & ctrain_power ) + || ( ( Heating ) + && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { +#ifdef EU07_USE_OLD_HVCOUPLERS + HVCouplers[ side ][ hvcoupler::incoming ] = + Couplers[side].Connected->HVCouplers[Couplers[side].ConnectedNr][hvcoupler::outgoing] + + Itot * HVCouplers[side][hvcoupler::outgoing] / hvc; // obciążenie rozkladane stosownie do napiec +#else + auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ]; + Couplers[ side ].power_high.incoming = + connectedcoupler.power_high.outgoing + + Itot * Couplers[ side ].power_high.outgoing / hvc; // obciążenie rozkladane stosownie do napiec +#endif + } + else { +#ifdef EU07_USE_OLD_HVCOUPLERS + // pierwszy pojazd + HVCouplers[side][hvcoupler::incoming] = Itot * HVCouplers[side][hvcoupler::outgoing] / hvc; +#else + Couplers[ side ].power_high.incoming = Itot * Couplers[ side ].power_high.outgoing / hvc; +#endif + } + } } else { - if (((Couplers[0].CouplingFlag & ctrain_power) == ctrain_power) || - (((Couplers[0].CouplingFlag & ctrain_heating) == ctrain_heating) && (Heating))) - TotalCurrent += - Couplers[0].Connected->HVCouplers[1 - Couplers[0].ConnectedNr][0]; - if (((Couplers[1].CouplingFlag & ctrain_power) == ctrain_power) || - (((Couplers[1].CouplingFlag & ctrain_heating) == ctrain_heating) && (Heating))) - TotalCurrent += - Couplers[1].Connected->HVCouplers[1 - Couplers[1].ConnectedNr][0]; - HVCouplers[0][0] = 0; - HVCouplers[1][0] = 0; + for( int side = 0; side < 2; ++side ) { + if( ( Couplers[ side ].CouplingFlag & ctrain_power ) + || ( ( Heating ) + && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { +#ifdef EU07_USE_OLD_HVCOUPLERS + TotalCurrent += Couplers[ side ].Connected->HVCouplers[ Couplers[ side ].ConnectedNr ][ hvcoupler::incoming ]; + HVCouplers[ side ][ hvcoupler::incoming ] = 0.0; +#else + auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ]; + TotalCurrent += connectedcoupler.power_high.incoming; + Couplers[ side ].power_high.incoming = 0.0; +#endif + } + } } if (!TestFlag(DamageFlag, dtrain_out)) @@ -1225,7 +1282,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap // przesuniecie dL = (3.0 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha} // ale jesli jest kolizja (zas. zach. pedu) to...} - for (b = 0; b < 2; b++) + for (int b = 0; b < 2; b++) if (Couplers[b].CheckCollision) CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! @@ -1463,10 +1520,14 @@ double TMoverParameters::ShowEngineRotation(int VehN) void TMoverParameters::ConverterCheck() { // sprawdzanie przetwornicy - if (ConverterAllow && Mains) + if( ( ConverterAllow ) + && ( ( Mains ) + || ( GetTrainsetVoltage() > 0.5 * EnginePowerSource.MaxVoltage ) ) ) { ConverterFlag = true; - else + } + else { ConverterFlag = false; + } }; double TMoverParameters::ShowCurrent(int AmpN) @@ -2210,7 +2271,7 @@ bool TMoverParameters::AntiSlippingButton(void) // Q: 20160713 // włączenie / wyłączenie obwodu głownego // ************************************************************************************************* -bool TMoverParameters::MainSwitch(bool State) +bool TMoverParameters::MainSwitch( bool const State, bool const Multiunitcontrol ) { bool MS; @@ -2222,13 +2283,21 @@ bool TMoverParameters::MainSwitch(bool State) (LastSwitchingTime > CtrlDelay) && !TestFlag(DamageFlag, dtrain_out) && !TestFlag(EngDmgFlag, 1))) { - if (Mains) // jeśli był załączony - SendCtrlToNext("MainSwitch", int(State), - CabNo); // wysłanie wyłączenia do pozostałych? + if( Mains ) { + // jeśli był załączony + if( true == Multiunitcontrol ) { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext( "MainSwitch", int( State ), CabNo ); + } + } Mains = State; - if (Mains) // jeśli został załączony - SendCtrlToNext("MainSwitch", int(State), - CabNo); // wyslanie po wlaczeniu albo przed wylaczeniem + if( Mains ) { + // jeśli został załączony + if( true == Multiunitcontrol ) { + // wyslanie po wlaczeniu albo przed wylaczeniem + SendCtrlToNext( "MainSwitch", int( State ), CabNo ); + } + } MS = true; // wartość zwrotna LastSwitchingTime = 0; if ((EngineType == DieselEngine) && Mains) @@ -2898,15 +2967,21 @@ void TMoverParameters::CompressorCheck(double dt) else CompressorFlag = (CompressorAllow) && ((ConverterFlag) || (CompressorPower == 0)) && (Mains); - if (Compressor > - MaxCompressor) // wyłącznik ciśnieniowy jest niezależny od sposobu zasilania + if( Compressor > MaxCompressor ) { + // wyłącznik ciśnieniowy jest niezależny od sposobu zasilania CompressorFlag = false; + CompressorGovernorLock = true; // prevent manual activation until the pressure goes below cut-in level + } } 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 + if( ( ( Compressor < MinCompressor ) + || ( ( Compressor < MaxCompressor ) + && ( false == CompressorGovernorLock ) ) ) + && (LastSwitchingTime > CtrlDelay) ) { + // załączenie przy małym ciśnieniu + // jeśli nie załączona, a ciśnienie za małe + // or if the switch is on and the pressure isn't maxed + 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 = @@ -2927,8 +3002,14 @@ void TMoverParameters::CompressorCheck(double dt) else CompressorFlag = (CompressorAllow) && ((ConverterFlag) || (CompressorPower == 0)) && (Mains); - if (CompressorFlag) // jeśli została załączona + if( CompressorFlag ) { + // jeśli została załączona LastSwitchingTime = 0; // to trzeba ograniczyć ponowne włączenie + if( Compressor < MinCompressor ) { + // if the activation took place at pressure below the cut-in level, we can reset compressor governor + CompressorGovernorLock = false; + } + } } // for b:=0 to 1 do //z Megapacka // with Couplers[b] do @@ -3231,14 +3312,17 @@ void TMoverParameters::UpdateScndPipePressure(double dt) } Pipe2->Flow(Hamulec->GetHPFlow(ScndPipePress, dt)); - +/* + // NOTE: condition disabled to allow the air flow from the main hose to the main tank as well if (((Compressor > ScndPipePress) && (CompressorSpeed > 0.0001)) || (TrainType == dt_EZT)) { +*/ dV = PF(Compressor, ScndPipePress, Spz) * dt; CompressedVolume += dV / 1000.0; Pipe2->Flow(-dV); +/* } - +*/ Pipe2->Flow(dv1 + dv2); Pipe2->Act(); ScndPipePress = Pipe2->P(); @@ -3407,21 +3491,27 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) LastSwitchingTime += dt1; if (EngineType == ElectricSeriesMotor) LastRelayTime += dt1; - if (Mains && /*(abs(CabNo) < 2) &&*/ (EngineType == - ElectricSeriesMotor)) // potem ulepszyc! pantogtrafy! + 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) + // zdefiniowany nawrotnik + if( CabNo == 0 ) Voltage = RunningTraction.TractionVoltage * ActiveDir; else Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo; } // bo nie dzialalo - else if ((EngineType == ElectricInductionMotor) || - (((Couplers[0].CouplingFlag & ctrain_power) == ctrain_power) || - ((Couplers[1].CouplingFlag & ctrain_power) == - ctrain_power))) // potem ulepszyc! pantogtrafy! - Voltage = - Max0R(Max0R(RunningTraction.TractionVoltage, HVCouplers[0][1]), HVCouplers[1][1]); + else if( ( EngineType == ElectricInductionMotor ) || + ( ( ( Couplers[ 0 ].CouplingFlag & ctrain_power ) == ctrain_power ) || + ( ( Couplers[ 1 ].CouplingFlag & ctrain_power ) == + ctrain_power ) ) ) // potem ulepszyc! pantogtrafy! + Voltage = + std::max( + RunningTraction.TractionVoltage, +#ifdef EU07_USE_OLD_HVCOUPLERS + std::max( HVCouplers[side::front][hvcoupler::incoming], HVCouplers[side::rear][hvcoupler::incoming] ) ); +#else + std::max( Couplers[ side::front ].power_high.incoming, Couplers[ side::rear ].power_high.incoming ) ); +#endif else Voltage = 0; //if (Mains && /*(abs(CabNo) < 2) &&*/ ( @@ -3975,10 +4065,10 @@ double TMoverParameters::TractionForce(double dt) FuseOff(); // wywalanie bezpiecznika z powodu przetezenia silnikow if ((Mains)) // nie wchodzić w funkcję bez potrzeby - if ((abs(Voltage) < EnginePowerSource.CollectorParameters.MinV) || - (abs(Voltage) * EnginePowerSource.CollectorParameters.OVP > + if ( (std::max(GetTrainsetVoltage(), std::abs(Voltage)) < EnginePowerSource.CollectorParameters.MinV) || + (std::max(GetTrainsetVoltage(), std::abs(Voltage)) * EnginePowerSource.CollectorParameters.OVP > EnginePowerSource.CollectorParameters.MaxV)) - if (MainSwitch(false)) + if (MainSwitch(false, TrainType == dt_EZT)) // TODO: check whether we need to send this EMU-wide EventFlag = true; // wywalanie szybkiego z powodu niewłaściwego napięcia if (((DynamicBrakeType == dbrake_automatic) || (DynamicBrakeType == dbrake_switch)) && @@ -4263,11 +4353,11 @@ double TMoverParameters::TractionForce(double dt) { if( ( Mains ) ) { // nie wchodzić w funkcję bez potrzeby - if( ( abs( Voltage ) < EnginePowerSource.CollectorParameters.MinV ) - || ( abs( Voltage ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) { - MainSwitch( false ); - } + if( ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) < EnginePowerSource.CollectorParameters.MinV ) + || ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) { + MainSwitch( false, TrainType == dt_EZT ); // TODO: check whether we need to send this EMU-wide } + } tmpV = abs(nrot) * (PI * WheelDiameter) * 3.6; //*DirAbsolute*eimc[eimc_s_p]; - do przemyslenia dzialanie pp if ((Mains)) { @@ -4979,23 +5069,29 @@ bool TMoverParameters::AutoRelayCheck(void) // Q: 20160713 // Podnosi / opuszcza przedni pantograf. Returns: state of the pantograph after the operation // ************************************************************************************************* -bool TMoverParameters::PantFront(bool State) +bool TMoverParameters::PantFront(bool const State, bool const Multiunitcontrol) { +/* if( ( true == Battery ) || ( true == ConverterFlag ) ) { - +*/ if( PantFrontUp != State ) { PantFrontUp = State; if( State == true ) { PantFrontStart = 0; - SendCtrlToNext( "PantFront", 1, CabNo ); + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantFront", 1, CabNo ); + } } else { PantFrontStart = 1; - SendCtrlToNext( "PantFront", 0, CabNo ); - } + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantFront", 0, CabNo ); + } } } +/* + } else { // no power, drop the pantograph // NOTE: this is a simplification as it should just drop on its own with loss of pressure without resupply from (dead) compressor @@ -5004,9 +5100,11 @@ bool TMoverParameters::PantFront(bool State) 1 : 0 ); PantFrontUp = false; - SendCtrlToNext( "PantFront", 0, CabNo ); + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantFront", 0, CabNo ); + } } - +*/ return PantFrontUp; } @@ -5014,23 +5112,29 @@ bool TMoverParameters::PantFront(bool State) // Q: 20160713 // Podnoszenie / opuszczanie pantografu tylnego // ************************************************************************************************* -bool TMoverParameters::PantRear(bool State) +bool TMoverParameters::PantRear(bool const State, bool const Multiunitcontrol) { +/* if( ( true == Battery ) || ( true == ConverterFlag ) ) { - +*/ if( PantRearUp != State ) { PantRearUp = State; if( State == true ) { PantRearStart = 0; - SendCtrlToNext( "PantRear", 1, CabNo ); + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantRear", 1, CabNo ); + } } else { PantRearStart = 1; - SendCtrlToNext( "PantRear", 0, CabNo ); - } + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantRear", 0, CabNo ); + } } } +/* + } else { // no power, drop the pantograph // NOTE: this is a simplification as it should just drop on its own with loss of pressure without resupply from (dead) compressor @@ -5039,9 +5143,11 @@ bool TMoverParameters::PantRear(bool State) 1 : 0 ); PantRearUp = false; - SendCtrlToNext( "PantRear", 0, CabNo ); + if( true == Multiunitcontrol ) { + SendCtrlToNext( "PantRear", 0, CabNo ); + } } - +*/ return PantRearUp; } @@ -5476,7 +5582,7 @@ std::string TMoverParameters::EngineDescription(int what) case 0: { if (DamageFlag == 255) - outstr = "Totally destroyed!"; + outstr = "WRECKED"; else { if (TestFlag(DamageFlag, dtrain_thinwheel)) @@ -5500,13 +5606,13 @@ std::string TMoverParameters::EngineDescription(int what) if (Power > 0.1) outstr = "Engine damaged,"; else - outstr = "Load destroyed!,"; + outstr = "LOAD DESTROYED,"; if (TestFlag(DamageFlag, dtrain_axle)) outstr = "Axle broken,"; if (TestFlag(DamageFlag, dtrain_out)) - outstr = "DERAILED!"; + outstr = "DERAILED"; if (outstr == "") - outstr = "OK!"; + outstr = "OK"; } break; } @@ -5523,7 +5629,30 @@ std::string TMoverParameters::EngineDescription(int what) // ************************************************************************************************* double TMoverParameters::GetTrainsetVoltage(void) {//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT - return Max0R(HVCouplers[1][1], HVCouplers[0][1]); +/* + return std::min( + std::max( HVCouplers[ 1 ][ 1 ], HVCouplers[ 0 ][ 1 ] ), // local + std::max( HVCouplers[ 1 ][ 0 ], HVCouplers[ 0 ][ 0 ] ) ); // remote +*/ + // TODO: investigate what exactly is reported on these couplers, does it include heating? +#ifdef EU07_USE_OLD_HVCOUPLERS + // TODO: if we ever revert to this version, match the expanded alternative below + return std::max( HVCouplers[ 1 ][ 0 ], HVCouplers[ 0 ][ 0 ] ); // incoming, external power +#else + return std::max( + ( ( ( Couplers[side::front].Connected ) + && ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) + || ( ( Heating ) + && ( Couplers[ side::front ].CouplingFlag & ctrain_heating ) ) ) ) ? + Couplers[side::front].Connected->Couplers[ Couplers[side::front].ConnectedNr ].power_high.outgoing : + 0.0 ), + ( ( ( Couplers[side::rear].Connected ) + && ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) + || ( ( Heating ) + && ( Couplers[ side::rear ].CouplingFlag & ctrain_heating ) ) ) ) ? + Couplers[ side::rear ].Connected->Couplers[ Couplers[ side::rear ].ConnectedNr ].power_high.outgoing : + 0.0 ) ); +#endif } // ************************************************************************************************* diff --git a/Train.cpp b/Train.cpp index 81d72c95..4664648c 100644 --- a/Train.cpp +++ b/Train.cpp @@ -1533,6 +1533,10 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com // press or hold... if( Train->m_linebreakerstate == 0 ) { // ...to close the circuit + if( Command.action == GLFW_PRESS ) { + // fresh press, start fresh closing delay calculation + Train->fMainRelayTimer = 0.0f; + } if( Train->ggMainOnButton.SubModel != nullptr ) { // two separate switches to close and break the circuit // audio feedback @@ -1552,8 +1556,9 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com Train->ggMainButton.UpdateValue( 1.0 ); } // keep track of period the button is held down, to determine when/if circuit closes - if( ( false == ( Train->mvControlled->EnginePowerSource.PowerType == ElectricSeriesMotor ) || ( Train->mvControlled->EngineType == ElectricInductionMotor ) ) - || ( Train->fHVoltage > 0.0f ) ) { + if( ( false == ( ( Train->mvControlled->EngineType == ElectricSeriesMotor ) + || ( Train->mvControlled->EngineType == ElectricInductionMotor ) ) ) + || ( Train->fHVoltage > 0.5 * Train->mvControlled->EnginePowerSource.MaxVoltage ) ) { // prevent the switch from working if there's no power // TODO: consider whether it makes sense for diesel engines and such Train->fMainRelayTimer += 0.33f; // Command.time_delta * 5.0; @@ -1695,6 +1700,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com // finalize the state of the line breaker Train->m_linebreakerstate = 1; } + // on button release reset the closing timer, just in case something elsewhere tries to read it + Train->fMainRelayTimer = 0.0f; } } @@ -1705,15 +1712,17 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma if( ( false == Train->mvControlled->ConverterAllow ) && ( Train->ggConverterButton.GetValue() < 0.5 ) ) { // turn on + // sound feedback + if( Train->ggConverterButton.GetValue() < 0.5 ) { + Train->play_sound( Train->dsbSwitch ); + } + // visual feedback + Train->ggConverterButton.UpdateValue( 1.0 ); +/* if( ( Train->mvControlled->EnginePowerSource.SourceType != CurrentCollector ) || ( Train->mvControlled->PantRearVolt != 0.0 ) || ( Train->mvControlled->PantFrontVolt != 0.0 ) ) { - // visual feedback - Train->ggConverterButton.UpdateValue( 1.0 ); - // sound feedback - if( Train->ggConverterButton.GetValue() < 0.5 ) { - Train->play_sound( Train->dsbSwitch ); - } +*/ // impulse type switch has no effect if there's no power // NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway if( ( Train->mvOccupied->ConvSwitchType != "impulse" ) @@ -1728,7 +1737,9 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma } } } +/* } +*/ } else { //turn off @@ -3141,11 +3152,13 @@ if if (DynamicObject->Mechanik) // na wszelki wypadek DynamicObject->Mechanik->CheckVehicles(Connect); // aktualizacja flag kierunku w składzie play_sound( dsbCouplerAttach ); + // one coupling type per key press + return; } else WriteLog("Mechanical coupling failed."); } - else if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_pneumatic)) // pneumatyka + if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_pneumatic)) // pneumatyka { if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag & tmp->MoverParameters->Couplers[CouplNr].AllowedFlag @@ -3155,12 +3168,16 @@ if tmp->MoverParameters->Couplers[CouplNr].Connected, (tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_pneumatic))) { - rsHiss.Play(1, DSBPLAY_LOOPING, true, tmp->GetPosition()); + // TODO: dedicated 'click' sound for connecting cable-type connections + play_sound( dsbCouplerDetach ); +// rsHiss.Play( 1, DSBPLAY_LOOPING, true, tmp->GetPosition() ); DynamicObject->SetPneumatic(CouplNr != 0, true); // Ra: to mi się nie podoba !!!! tmp->SetPneumatic(CouplNr != 0, true); + // one coupling type per key press + return; } } - else if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_scndpneumatic)) // zasilajacy + if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_scndpneumatic)) // zasilajacy { if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag & tmp->MoverParameters->Couplers[CouplNr].AllowedFlag @@ -3170,17 +3187,18 @@ if tmp->MoverParameters->Couplers[CouplNr].Connected, (tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_scndpneumatic))) { - // rsHiss.Play(1,DSBPLAY_LOOPING,true,tmp->GetPosition()); + // TODO: dedicated 'click' sound for connecting cable-type connections play_sound( dsbCouplerDetach ); - DynamicObject->SetPneumatic(CouplNr != 0, false); // Ra: to mi się nie podoba !!!! +// rsHiss.Play( 1, DSBPLAY_LOOPING, true, tmp->GetPosition() ); + DynamicObject->SetPneumatic( CouplNr != 0, false ); // Ra: to mi się nie podoba !!!! tmp->SetPneumatic(CouplNr != 0, false); + // one coupling type per key press + return; } } - else if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_controll)) // ukrotnionko + if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_controll)) // ukrotnionko { - if ((tmp->MoverParameters->Couplers[CouplNr] - .Connected->Couplers[CouplNr] - .AllowedFlag & + if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag & tmp->MoverParameters->Couplers[CouplNr].AllowedFlag & ctrain_controll) == ctrain_controll) if (tmp->MoverParameters->Attach( @@ -3188,14 +3206,15 @@ if tmp->MoverParameters->Couplers[CouplNr].Connected, (tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_controll))) { + // TODO: dedicated 'click' sound for connecting cable-type connections play_sound( dsbCouplerAttach ); + // one coupling type per key press + return; } } - else if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_passenger)) // mostek + if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_passenger)) // mostek { - if ((tmp->MoverParameters->Couplers[CouplNr] - .Connected->Couplers[CouplNr] - .AllowedFlag & + if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag & tmp->MoverParameters->Couplers[CouplNr].AllowedFlag & ctrain_passenger) == ctrain_passenger) if (tmp->MoverParameters->Attach( @@ -3203,10 +3222,29 @@ if tmp->MoverParameters->Couplers[CouplNr].Connected, (tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_passenger))) { - // rsHiss.Play(1,DSBPLAY_LOOPING,true,tmp->GetPosition()); - play_sound( dsbCouplerDetach ); + play_sound( dsbCouplerAttach ); +/* DynamicObject->SetPneumatic(CouplNr != 0, false); tmp->SetPneumatic(CouplNr != 0, false); +*/ + // one coupling type per key press + return; + } + } + if( false == TestFlag( tmp->MoverParameters->Couplers[ CouplNr ].CouplingFlag, ctrain_heating ) ) { + // heating + if( ( tmp->MoverParameters->Couplers[ CouplNr ].Connected->Couplers[ CouplNr ].AllowedFlag + & tmp->MoverParameters->Couplers[ CouplNr ].AllowedFlag + & ctrain_heating ) == ctrain_heating ) + if( tmp->MoverParameters->Attach( + CouplNr, 2, + tmp->MoverParameters->Couplers[ CouplNr ].Connected, + ( tmp->MoverParameters->Couplers[ CouplNr ].CouplingFlag | ctrain_heating ) ) ) { + + // TODO: dedicated 'click' sound for connecting cable-type connections + play_sound( dsbCouplerAttach ); + // one coupling type per key press + return; } } } @@ -3478,6 +3516,19 @@ bool TTrain::Update( double const Deltatime ) m_linebreakerstate = 0; } + // NOTE: crude way to have the pantographs go back up if they're dropped due to insufficient pressure etc + // TODO: rework it into something more elegant, when redoing the whole consist/unit/cab etc arrangement + if( ( mvControlled->Battery ) + || ( mvControlled->ConverterFlag ) ) { + if( ( false == mvControlled->PantFrontUp ) + && ( ggPantFrontButton.GetValue() > 0.95 ) ) { + mvControlled->PantFront( true ); + } + if( ( false == mvControlled->PantRearUp ) + && ( ggPantRearButton.GetValue() > 0.95 ) ) { + mvControlled->PantRear( true ); + } + } /* // NOTE: disabled while switch state isn't preserved while moving between compartments // check whether we should raise the pantographs, based on volume in pantograph tank @@ -3502,15 +3553,14 @@ bool TTrain::Update( double const Deltatime ) tor = DynamicObject->GetTrack(); // McZapkie-180203 // McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol float maxtacho = 3; - fTachoVelocity = Min0R(fabs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot), - mvControlled->Vmax * 1.05); + fTachoVelocity = static_cast( std::min( std::abs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot), mvControlled->Vmax * 1.05) ); { // skacze osobna zmienna float ff = simulation::Time.data().wSecond; // skacze co sekunde - pol sekundy // pomiar, pol sekundy ustawienie if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial { if (fTachoVelocity > 1) // jedzie - fTachoVelocityJump = fTachoVelocity + (2 - Random(3) + Random(3)) * 0.5; + fTachoVelocityJump = fTachoVelocity + (2.0 - Random(3) + Random(3)) * 0.5; else fTachoVelocityJump = 0; // stoi fTachoTimer = ff; // juz zmienil @@ -3725,12 +3775,14 @@ bool TTrain::Update( double const Deltatime ) // przy dowolnym ustawieniu kierunkowego // Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od // kierunku - if (mvControlled->EngineType == ElectricSeriesMotor) - if (fabs(mvControlled->RunningTraction.TractionVoltage) < - 0.5 * - mvControlled->EnginePowerSource - .MaxVoltage) // minimalne napięcie pobierać z FIZ? - mvControlled->MainSwitch(false); + if( mvControlled->EngineType == ElectricSeriesMotor ) { + if( std::max( mvControlled->GetTrainsetVoltage(), std::fabs( mvControlled->RunningTraction.TractionVoltage ) ) < 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) { + // TODO: check whether it should affect entire consist for EMU + // TODO: check whether it should happen if there's power supplied alternatively through hvcouplers + // TODO: potentially move this to the mover module, as there isn't much reason to have this dependent on the operator presence + mvControlled->MainSwitch( false, false ); + } + } // hunter-091012: swiatlo if (bCabLight == true) @@ -3759,7 +3811,7 @@ bool TTrain::Update( double const Deltatime ) { mvControlled->ConvOvldFlag = true; if (mvControlled->TrainType != dt_EZT) - mvControlled->MainSwitch(false); + mvControlled->MainSwitch(false, mvControlled->TrainType == dt_EZT); } else if( fConverterTimer >= fConverterPrzekaznik ) { // changed switch from always true to take into account state of the compressor switch @@ -4702,74 +4754,20 @@ bool TTrain::Update( double const Deltatime ) ggManualBrake.UpdateValue(double(mvOccupied->ManualBrakePos)); ggManualBrake.Update(); } - if (ggBrakeProfileCtrl.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggBrakeProfileCtrl.UpdateValue( - double(mvOccupied->BrakeDelayFlag == 4 ? 2 : mvOccupied->BrakeDelayFlag - 1)); -#endif - ggBrakeProfileCtrl.Update(); - } - if (ggBrakeProfileG.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggBrakeProfileG.UpdateValue( double( mvOccupied->BrakeDelayFlag == bdelay_G ? 1 : 0 ) ); -#endif - ggBrakeProfileG.Update(); - } - if (ggBrakeProfileR.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggBrakeProfileR.UpdateValue( double( mvOccupied->BrakeDelayFlag == bdelay_R ? 1 : 0 ) ); -#endif - ggBrakeProfileR.Update(); - } - - if (ggMaxCurrentCtrl.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggMaxCurrentCtrl.UpdateValue( double( mvControlled->Imax == mvControlled->ImaxHi ) ); -#endif - ggMaxCurrentCtrl.Update(); - } - + ggBrakeProfileCtrl.Update(); + ggBrakeProfileG.Update(); + ggBrakeProfileR.Update(); + ggMaxCurrentCtrl.Update(); // NBMX wrzesien 2003 - drzwi - if (ggDoorLeftButton.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1 : 0 ); -#endif - ggDoorLeftButton.Update(); - } - if (ggDoorRightButton.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggDoorRightButton.PutValue( mvOccupied->DoorRightOpened ? 1 : 0 ); -#endif - ggDoorRightButton.Update(); - } - if (ggDepartureSignalButton.SubModel) - { - // ggDepartureSignalButton.UpdateValue(double()); - ggDepartureSignalButton.Update(); - } - + ggDoorLeftButton.Update(); + ggDoorRightButton.Update(); + ggDepartureSignalButton.Update(); // NBMX dzwignia sprezarki - if (ggCompressorButton.SubModel) // hunter-261211: poprawka - ggCompressorButton.Update(); - if (ggMainButton.SubModel) - ggMainButton.Update(); - if (ggRadioButton.SubModel) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggRadioButton.PutValue( mvOccupied->Radio ? 1 : 0 ); -#endif - ggRadioButton.Update(); - } - if (ggConverterButton.SubModel) - ggConverterButton.Update(); - if (ggConverterOffButton.SubModel) - ggConverterOffButton.Update(); + ggCompressorButton.Update(); + ggMainButton.Update(); + ggRadioButton.Update(); + ggConverterButton.Update(); + ggConverterOffButton.Update(); #ifdef EU07_USE_OLD_COMMAND_SYSTEM if( ( ( DynamicObject->iLights[ 0 ] ) == 0 ) && ( ( DynamicObject->iLights[ 1 ] ) == 0 ) ) @@ -4918,64 +4916,18 @@ bool TTrain::Update( double const Deltatime ) ggLightsButton.PutValue(mvOccupied->LightsPos - 1); ggLightsButton.Update(); } - if( ggDimHeadlightsButton.SubModel ) { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggDimHeadlightsButton.PutValue( DynamicObject->DimHeadlights ? 1.0 : 0.0 ); -#endif - ggDimHeadlightsButton.Update(); - } - + ggDimHeadlightsButton.Update(); //--------- // Winger 010304 - pantografy // NOTE: shouldn't the pantograph updates check whether it's front or rear cabin? - if (ggPantFrontButton.SubModel ) { - ggPantFrontButton.Update(); - } - if (ggPantRearButton.SubModel) { - ggPantRearButton.Update(); - } - if (ggPantFrontButtonOff.SubModel) { - ggPantFrontButtonOff.Update(); - } + ggPantFrontButton.Update(); + ggPantRearButton.Update(); + ggPantFrontButtonOff.Update(); + ggTrainHeatingButton.Update(); + ggSignallingButton.Update(); + ggDoorSignallingButton.Update(); // Winger 020304 - ogrzewanie - //---------- // hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy - if( ggTrainHeatingButton.SubModel ) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - if( mvControlled->Heating ) - { - ggTrainHeatingButton.PutValue(1); - // if (mvControlled->ConverterFlag==true) - // btLampkaOgrzewanieSkladu.TurnOn(); - } - else - { - ggTrainHeatingButton.PutValue(0); - // btLampkaOgrzewanieSkladu.TurnOff(); - } -#endif - ggTrainHeatingButton.Update(); - } - if (ggSignallingButton.SubModel != nullptr) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggSignallingButton.PutValue( mvControlled->Signalling ? 1 : 0 ); -#endif - ggSignallingButton.Update(); - } - if (ggDoorSignallingButton.SubModel != nullptr) - { -#ifdef EU07_USE_OLD_COMMAND_SYSTEM - ggDoorSignallingButton.PutValue( mvControlled->DoorSignalling ? 1 : 0 ); -#endif - ggDoorSignallingButton.Update(); - } - // if (ggDistCounter.SubModel) - //{//Ra 2014-07: licznik kilometrów - // ggDistCounter.PutValue(mvControlled->DistCounter); - // ggDistCounter.Update(); - //} if ((((mvControlled->EngineType == ElectricSeriesMotor) && (mvControlled->Mains == true) && (mvControlled->ConvOvldFlag == false)) || (mvControlled->ConverterFlag)) && diff --git a/World.cpp b/World.cpp index aaf67aa7..28555df2 100644 --- a/World.cpp +++ b/World.cpp @@ -1820,24 +1820,48 @@ TWorld::Update_UI() { uitextline2 += "; TC:" + to_string( tmp->MoverParameters->TotalCurrent, 0 ); +#ifdef EU07_USE_OLD_HVCOUPLERS uitextline2 += - ", HV0:" - + to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 1 ], 0 ) - + "@" - + to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 0 ], 0 ); + ", HV0: (" + + to_string( tmp->MoverParameters->HVCouplers[ TMoverParameters::side::front ][ TMoverParameters::hvcoupler::outgoing ], 0 ) + + ")<-" + + to_string( tmp->MoverParameters->HVCouplers[ TMoverParameters::side::front ][ TMoverParameters::hvcoupler::incoming ], 0 ); uitextline2 += - ", HV1:" - + to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 1 ], 0 ) - + "@" - + to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 0 ], 0 ); + ", HV1: (" + + to_string( tmp->MoverParameters->HVCouplers[ TMoverParameters::side::rear ][ TMoverParameters::hvcoupler::outgoing ], 0 ) + + ")<-" + + to_string( tmp->MoverParameters->HVCouplers[ TMoverParameters::side::rear ][ TMoverParameters::hvcoupler::incoming ], 0 ); +#else + uitextline2 += + ", HV: " + + to_string( tmp->MoverParameters->Couplers[ TMoverParameters::side::front ].power_high.incoming, 0 ) + + "->(" + + to_string( tmp->MoverParameters->Couplers[ TMoverParameters::side::front ].power_high.outgoing, 0 ) + + ")F" + (tmp->DirectionGet() ? "<<" : ">>") + "R(" + + to_string( tmp->MoverParameters->Couplers[ TMoverParameters::side::rear ].power_high.outgoing, 0 ) + + ")<-" + + to_string( tmp->MoverParameters->Couplers[ TMoverParameters::side::rear ].power_high.incoming, 0 ); +#endif + // equipment flags + uitextline3 = ""; + uitextline3 += ( tmp->MoverParameters->Battery ? "B" : "b" ); + uitextline3 += ( tmp->MoverParameters->Mains ? "M" : "m" ); + uitextline3 += ( tmp->MoverParameters->PantRearUp ? ( tmp->MoverParameters->PantPressSwitchActive ? "O" : "o" ) : "." );; + uitextline3 += ( tmp->MoverParameters->PantFrontUp ? ( tmp->MoverParameters->PantPressSwitchActive ? "P" : "p" ) : "." );; + uitextline3 += ( tmp->MoverParameters->PantPressSwitchActive ? "!" : "." ); + uitextline3 += ( tmp->MoverParameters->ConverterAllow ? ( tmp->MoverParameters->ConverterFlag ? "X" : "x" ) : "." ); + uitextline3 += ( tmp->MoverParameters->ConvOvldFlag ? "!" : "." ); + uitextline3 += ( tmp->MoverParameters->CompressorAllow ? ( tmp->MoverParameters->CompressorFlag ? "C" : "c" ) : "." ); + uitextline3 += ( tmp->MoverParameters->CompressorGovernorLock ? "!" : "." ); - uitextline3 = - "BP: " + to_string( tmp->MoverParameters->BrakePress, 2 ) + uitextline3 += + " BP: " + to_string( tmp->MoverParameters->BrakePress, 2 ) + " (" + to_string( tmp->MoverParameters->BrakeStatus, 0 ) + "), LBP: " + to_string( tmp->MoverParameters->LocBrakePress, 2 ) + ", PP: " + to_string( tmp->MoverParameters->PipePress, 2 ) + "/" + to_string( tmp->MoverParameters->ScndPipePress, 2 ) + "/" + to_string( tmp->MoverParameters->EqvtPipePress, 2 ) + + ", MT: " + to_string( tmp->MoverParameters->CompressedVolume, 3 ) + ", BVP: " + to_string( tmp->MoverParameters->Volume, 3 ) + ", " + to_string( tmp->MoverParameters->CntrlPipePress, 3 ) + ", " + to_string( tmp->MoverParameters->Hamulec->GetCRP(), 3 )