From bda879bdcac26fc7b24d9faebd257d5f6a432156 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sat, 7 Sep 2019 14:54:57 +0200 Subject: [PATCH 01/15] build 190906. alternative vehicle takeover mode, collision system tweaks, security system activation tweaks, gfx card selection exports, potential render crash fixe for amd gfx cards --- Driver.cpp | 81 +++++++++++++++++++++-------------- Driver.h | 13 ++++-- DynObj.cpp | 8 ++-- Event.cpp | 4 +- McZapkie/MOVER.h | 1 + McZapkie/Mover.cpp | 30 ++++++++----- Train.cpp | 11 +++-- TrkFoll.cpp | 6 +-- application.cpp | 3 ++ drivermode.cpp | 32 ++++++++++---- driveruipanels.cpp | 8 ++-- messaging.cpp | 2 +- renderer.cpp | 20 +++++---- simulationstateserializer.cpp | 2 +- version.h | 2 +- 15 files changed, 141 insertions(+), 82 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 72b76b03..20de084e 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2110,12 +2110,18 @@ bool TController::CheckVehicles(TOrders user) { // sprawdzanie, czy jest głównym sterującym, żeby nie było konfliktu if (p->Mechanik) // jeśli ma obsadę if (p->Mechanik != this) // ale chodzi o inny pojazd, niż aktualnie sprawdzający - if (p->Mechanik->iDrivigFlags & movePrimary) // a tamten ma priorytet - if ((iDrivigFlags & movePrimary) && (mvOccupied->DirAbsolute) && - (mvOccupied->BrakeCtrlPos >= -1)) // jeśli rządzi i ma kierunek - p->Mechanik->iDrivigFlags &= ~movePrimary; // dezaktywuje tamtego - else + if( p->Mechanik->iDrivigFlags & movePrimary ) { + // a tamten ma priorytet + if( ( iDrivigFlags & movePrimary ) + && ( mvOccupied->DirAbsolute ) + && ( mvOccupied->BrakeCtrlPos >= -1 ) ) { + // jeśli rządzi i ma kierunek + p->Mechanik->primary( false ); // dezaktywuje tamtego + } + else { main = false; // nici z rządzenia + } + } ++iVehicles; // jest jeden pojazd więcej pVehicles[1] = p; // zapamiętanie ostatniego fLength += p->MoverParameters->Dim.L; // dodanie długości pojazdu @@ -4763,7 +4769,7 @@ TController::UpdateSituation(double dt) { // rozpoznaj komende bo lokomotywa jej nie rozpoznaje RecognizeCommand(); // samo czyta komendę wstawioną do pojazdu? } - if( mvOccupied->SecuritySystem.Status > 1 ) { + if( mvOccupied->SecuritySystem.Status != s_off ) { // jak zadziałało CA/SHP if( !mvOccupied->SecuritySystemReset() ) { // to skasuj if( ( /*mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == 0 ) @@ -6759,43 +6765,56 @@ void TController::UpdateDelayFlag() { //-----------koniec skanowania semaforow -void TController::TakeControl(bool yes) +void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck ) { // przejęcie kontroli przez AI albo oddanie - if (AIControllFlag == yes) + if (AIControllFlag == Aidriver) return; // już jest jak ma być - if (yes) //żeby nie wykonywać dwa razy + if (Aidriver) //żeby nie wykonywać dwa razy { // teraz AI prowadzi AIControllFlag = AIdriver; pVehicle->Controller = AIdriver; iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć - // gdy zgaszone światła, flaga podjeżdżania pod semafory pozostaje bez zmiany - // conditional below disabled to get around the situation where the AI train does nothing ever - // because it is waiting for orders which don't come until the engine is engaged, i.e. effectively never - if (OrderCurrentGet()) // jeśli coś robi - PrepareEngine(); // niech sprawdzi stan silnika - else // jeśli nic nie robi - if (pVehicle->iLights[ ( mvOccupied->CabNo < 0 ? - end::rear : - end::front ) ] - & (light::headlight_left | light::headlight_right | light::headlight_upper)) // któreś ze świateł zapalone? - { // od wersji 357 oczekujemy podania komend dla AI przez scenerię - OrderNext(Prepare_engine); - if (pVehicle->iLights[mvOccupied->CabNo < 0 ? end::rear : end::front] & light::headlight_upper) // górne światło zapalone - OrderNext(Obey_train); // jazda pociągowa - else - OrderNext(Shunt); // jazda manewrowa - if (mvOccupied->Vel >= 1.0) // jeśli jedzie (dla 0.1 ma stać) - iDrivigFlags &= ~moveStopHere; // to ma nie czekać na sygnał, tylko jechać - else - iDrivigFlags |= moveStopHere; // a jak stoi, to niech czeka - } - CheckVehicles(); // ustawienie świateł TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z sygnałami + if( action() != TAction::actSleep ) { + // gdy zgaszone światła, flaga podjeżdżania pod semafory pozostaje bez zmiany + // conditional below disabled to get around the situation where the AI train does nothing ever + // because it is waiting for orders which don't come until the engine is engaged, i.e. effectively never + if( OrderCurrentGet() ) { + // jeśli coś robi + PrepareEngine(); // niech sprawdzi stan silnika + } + else { + // jeśli nic nie robi + if( pVehicle->iLights[ ( mvOccupied->CabNo < 0 ? + end::rear : + end::front ) ] + & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) // któreś ze świateł zapalone? + { // od wersji 357 oczekujemy podania komend dla AI przez scenerię + OrderNext( Prepare_engine ); + if( pVehicle->iLights[ mvOccupied->CabNo < 0 ? end::rear : end::front ] & light::headlight_upper ) // górne światło zapalone + OrderNext( Obey_train ); // jazda pociągowa + else + OrderNext( Shunt ); // jazda manewrowa + if( mvOccupied->Vel >= 1.0 ) // jeśli jedzie (dla 0.1 ma stać) + iDrivigFlags &= ~moveStopHere; // to ma nie czekać na sygnał, tylko jechać + else + iDrivigFlags |= moveStopHere; // a jak stoi, to niech czeka + } + } + CheckVehicles(); // ustawienie świateł + } } else { // a teraz użytkownik AIControllFlag = Humandriver; pVehicle->Controller = Humandriver; + if( eAction == TAction::actSleep ) { + eAction = TAction::actUnknown; + } + if( Forcevehiclecheck ) { + // update consist ownership and other consist data + CheckVehicles(); + } } }; diff --git a/Driver.h b/Driver.h index 85177dbe..062691af 100644 --- a/Driver.h +++ b/Driver.h @@ -194,9 +194,13 @@ public: public: void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę void MoveTo(TDynamicObject *to); - void TakeControl(bool yes); + void TakeControl(bool const Aidriver, bool const Forcevehiclecheck = false); inline - bool Primary() const { + bool primary( bool const Primary ) { + SetFlag( iDrivigFlags, ( Primary ? movePrimary : -movePrimary ) ); + return primary(); } + inline + bool primary() const { return ( ( iDrivigFlags & movePrimary ) != 0 ); }; inline TMoverParameters const *Controlling() const { @@ -210,8 +214,11 @@ public: inline int Direction() const { return iDirection; } + inline + TAction & action() { + return eAction; } inline - TAction GetAction() { + TAction const & action() const { return eAction; } private: void Activation(); // umieszczenie obsady w odpowiednim członie diff --git a/DynObj.cpp b/DynObj.cpp index ba0f1b44..a0568347 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -980,8 +980,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) if( ( false == bDisplayCab ) // edge case, lowpoly may act as a stand-in for the hi-fi cab, so make sure not to show the driver when inside && ( Mechanik != nullptr ) - && ( ( Mechanik->GetAction() != TAction::actSleep ) - || ( MoverParameters->Battery ) ) ) { + && ( ( Mechanik->action() != TAction::actSleep ) + /* || ( MoverParameters->Battery ) */ ) ) { // rysowanie figurki mechanika btMechanik1.Turn( MoverParameters->ActiveCab > 0 ); btMechanik2.Turn( MoverParameters->ActiveCab < 0 ); @@ -2762,14 +2762,14 @@ bool TDynamicObject::Update(double dt, double dt1) if (Mechanik) { // Ra 2F3F: do Driver.cpp to przenieść? MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG - if ((Mechanik->Primary()) + if ((Mechanik->primary()) && (MoverParameters->EngineType == TEngineType::DieselEngine) && (MoverParameters->EIMCtrlType > 0)) { MoverParameters->CheckEIMIC(dt1); MoverParameters->eimic_real = MoverParameters->eimic; MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic, MoverParameters->CabNo); } - if( ( Mechanik->Primary() ) + if( ( Mechanik->primary() ) && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { // jesli glowny i z asynchronami, to niech steruje hamulcem i napedem lacznie dla calego pociagu/ezt auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0); diff --git a/Event.cpp b/Event.cpp index 2e7ff1ca..fdcf7e93 100644 --- a/Event.cpp +++ b/Event.cpp @@ -897,7 +897,7 @@ whois_event::run_() { // jeśli typ pojazdu // TODO: define and recognize individual request types auto const owner { ( - ( ( m_activator->Mechanik != nullptr ) && ( m_activator->Mechanik->Primary() ) ) ? + ( ( m_activator->Mechanik != nullptr ) && ( m_activator->Mechanik->primary() ) ) ? m_activator->Mechanik : m_activator->ctOwner ) }; auto const consistbrakelevel { ( @@ -952,7 +952,7 @@ whois_event::run_() { } // +0 else if( m_activator->Mechanik ) { - if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! + if( m_activator->Mechanik->primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! targetcell->UpdateValues( m_activator->Mechanik->TrainName(), m_activator->Mechanik->StationCount() - m_activator->Mechanik->StationIndex(), // ile przystanków do końca diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 3c4bc493..65df7e6f 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -204,6 +204,7 @@ static int const dbrake_automatic = 8; /*status czuwaka/SHP*/ //hunter-091012: rozdzielenie alarmow, dodanie testu czuwaka +static int const s_off = 0; //disabled static int const s_waiting = 1; //działa static int const s_aware = 2; //czuwak miga static int const s_active = 4; //SHP świeci diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index e25494cd..db55491f 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1051,7 +1051,10 @@ void TMoverParameters::CollisionDetect(int const End, double const dt) if( velocitydifference > safevelocitylimit ) { // HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio - WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); + if( ( false == TestFlag( DamageFlag, dtrain_out ) ) + || ( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) { + WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); + } if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) { derail( 5 ); @@ -1084,12 +1087,14 @@ void TMoverParameters::CollisionDetect(int const End, double const dt) void TMoverParameters::damage_coupler( int const End ) { + auto &coupler{ Couplers[ End ] }; + + if( coupler.CouplerType == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what + if( SetFlag( DamageFlag, dtrain_coupling ) ) EventFlag = true; - auto &coupler { Couplers[ End ] }; - - if( ( coupler.CouplingFlag & ctrain_pneumatic ) == ctrain_pneumatic ) { + if( ( coupler.CouplingFlag & coupling::brakehose ) == coupling::brakehose ) { // hamowanie nagle - zerwanie przewodow hamulcowych AlarmChainFlag = true; } @@ -1100,11 +1105,11 @@ TMoverParameters::damage_coupler( int const End ) { switch( End ) { // break connection with other vehicle, if there's any case 0: { - coupler.Connected->Couplers[ end::rear ].CouplingFlag = 0; + coupler.Connected->Couplers[ end::rear ].CouplingFlag = coupling::faux; break; } case 1: { - coupler.Connected->Couplers[ end::front ].CouplingFlag = 0; + coupler.Connected->Couplers[ end::front ].CouplingFlag = coupling::faux; break; } default: { @@ -2301,7 +2306,7 @@ bool TMoverParameters::CabDeactivisation(void) CabNo = 0; DirAbsolute = ActiveDir * CabNo; DepartureSignal = false; // nie buczeć z nieaktywnej kabiny - SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection + SecuritySystem.Status = s_off; // deactivate alerter TODO: make it part of control based cab selection SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0! } @@ -2446,7 +2451,7 @@ void TMoverParameters::SecuritySystemCheck(double dt) RadiostopSwitch(false); if ((SecuritySystem.SystemType > 0) - && (SecuritySystem.Status > 0) + && (SecuritySystem.Status != s_off) && (Battery)) // Ra: EZT ma teraz czuwak w rozrządczym { // CA @@ -2537,8 +2542,8 @@ bool TMoverParameters::BatterySwitch(bool State) SendCtrlToNext("BatterySwitch", 0, CabNo); BS = true; - if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/ - SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka + if ((Battery) && (ActiveCab != 0)) + SecuritySystem.Status |= s_waiting; // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka @@ -10397,10 +10402,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C Battery = true; else if ((CValue1 == 0)) Battery = false; - if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/) + /* + // TBD: makes no sense to activate alerters in entire consist + if ((Battery) && (ActiveCab != 0) ) SecuritySystem.Status = SecuritySystem.Status | s_waiting; // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka + */ OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } // else if command='EpFuseSwitch' then {NBMX} diff --git a/Train.cpp b/Train.cpp index 73095609..f670d74e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5667,7 +5667,7 @@ bool TTrain::Update( double const Deltatime ) } } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if( mvOccupied->SecuritySystem.Status > 0 ) { + if( mvOccupied->SecuritySystem.Status != s_off ) { if( fBlinkTimer > fCzuwakBlink ) fBlinkTimer = -fCzuwakBlink; else @@ -5695,7 +5695,7 @@ bool TTrain::Update( double const Deltatime ) false ) ); btLampkaWylSzybkiOff.Turn( ( ( ( mvControlled->MainsInitTimeCountdown > 0.0 ) - || ( fHVoltage == 0.0 ) +// || ( fHVoltage == 0.0 ) || ( m_linebreakerstate == 2 ) || ( true == mvControlled->Mains ) ) ? false : @@ -5928,7 +5928,10 @@ bool TTrain::Update( double const Deltatime ) auto const *mover { tmp->MoverParameters }; btLampkaWylSzybkiB.Turn( mover->Mains ); - btLampkaWylSzybkiBOff.Turn( ( false == mover->Mains ) && ( mover->MainsInitTimeCountdown <= 0.0 ) && ( fHVoltage != 0.0 ) ); + btLampkaWylSzybkiBOff.Turn( + ( false == mover->Mains ) + && ( mover->MainsInitTimeCountdown <= 0.0 ) + /*&& ( fHVoltage != 0.0 )*/ ); btLampkaOporyB.Turn(mover->ResistorsFlagCheck()); btLampkaBezoporowaB.Turn( @@ -6528,7 +6531,7 @@ TTrain::update_sounds( double const Deltatime ) { } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if (mvOccupied->SecuritySystem.Status > 0) { + if (mvOccupied->SecuritySystem.Status != s_off ) { // hunter-091012: rozdzielenie alarmow if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) { diff --git a/TrkFoll.cpp b/TrkFoll.cpp index dc462a78..d7f2aebe 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -116,7 +116,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( false == ismoving ) { //McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu pCurrentTrack->QueueEvents( pCurrentTrack->m_events0, Owner ); } @@ -127,7 +127,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( SetFlag( iEventFlag, -1 ) ) { // zawsze zeruje flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu // McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner ); @@ -143,7 +143,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( SetFlag( iEventFlag, -2 ) ) { // zawsze ustawia flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner ); } diff --git a/application.cpp b/application.cpp index 791ccbcd..c825d12b 100644 --- a/application.cpp +++ b/application.cpp @@ -43,6 +43,9 @@ http://mozilla.org/MPL/2.0/. #pragma comment (lib, "dbghelp.lib") #pragma comment (lib, "version.lib") +extern "C" { _declspec( dllexport ) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; } +extern "C" { _declspec( dllexport ) DWORD NvOptimusEnablement = 0x00000001; } + eu07_application Application; ui_layer uilayerstaticinitializer; diff --git a/drivermode.cpp b/drivermode.cpp index 0f152e61..17273b94 100644 --- a/drivermode.cpp +++ b/drivermode.cpp @@ -723,20 +723,36 @@ driver_mode::OnKeyDown(int cKey) { if( tmp != nullptr ) { - if( simulation::Train ) {// jeśli mielismy pojazd - if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć - simulation::Train->Dynamic()->Mechanik->TakeControl( true ); // oddajemy dotychczasowy AI - } - } - if( ( true == DebugModeFlag ) || ( tmp->MoverParameters->Vel <= 5.0 ) ) { // works always in debug mode, or for stopped/slow moving vehicles otherwise + if( simulation::Train ) { // jeśli mielismy pojazd + if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć + if( ( tmp->ctOwner == simulation::Train->Dynamic()->Mechanik ) + && ( true == Global.ctrlState ) ) { + // if the vehicle we left to the ai controlled the vehicle we're about to take over + // put the ai we left in charge of our old vehicle to sleep + // TODO: remove ctrl key mode once manual cab (de)activation is in place + simulation::Train->Dynamic()->Mechanik->primary( false ); + simulation::Train->Dynamic()->Mechanik->action() = TAction::actSleep; + simulation::Train->Dynamic()->MoverParameters->CabDeactivisation(); + } + simulation::Train->Dynamic()->Mechanik->TakeControl( true ); // oddajemy dotychczasowy AI + } + } + if( simulation::Train == nullptr ) { simulation::Train = new TTrain(); // jeśli niczym jeszcze nie jeździlismy } - if( simulation::Train->Init( tmp ) ) { // przejmujemy sterowanie - simulation::Train->Dynamic()->Mechanik->TakeControl( false ); + if( simulation::Train->Init( tmp ) ) { + // przejmujemy sterowanie + if( true == Global.ctrlState ) { + // make sure we can take over the consist + // TODO: remove ctrl key mode once manual cab (de)activation is in place + simulation::Train->Dynamic()->Mechanik->primary( true ); + simulation::Train->Dynamic()->MoverParameters->CabActivisation(); + } + simulation::Train->Dynamic()->Mechanik->TakeControl( false, true ); } else { SafeDelete( simulation::Train ); // i nie ma czym sterować diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 96ef1b98..34267430 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -170,7 +170,7 @@ scenario_panel::update() { std::get( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) ); // w trybie latania lokalizujemy wg mapy if( m_nearest == nullptr ) { return; } auto const *owner { ( - ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->Primary() ) ) ? + ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->primary() ) ) ? m_nearest->Mechanik : m_nearest->ctOwner ) }; if( owner == nullptr ) { return; } @@ -208,7 +208,7 @@ scenario_panel::render() { if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) { // potential assignment section auto const *owner { ( - ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->Primary() ) ) ? + ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->primary() ) ) ? m_nearest->Mechanik : m_nearest->ctOwner ) }; if( owner != nullptr ) { @@ -261,7 +261,7 @@ timetable_panel::update() { if( vehicle == nullptr ) { return; } // if the nearest located vehicle doesn't have a direct driver, try to query its owner auto const *owner = ( - ( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->Primary() ) ) ? + ( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->primary() ) ) ? vehicle->Mechanik : vehicle->ctOwner ); if( owner == nullptr ) { return; } @@ -553,7 +553,7 @@ debug_panel::update_section_vehicle( std::vector &Output ) { auto const &vehicle { *m_input.vehicle }; auto const &mover { *m_input.mover }; - auto const isowned { ( vehicle.Mechanik == nullptr ) && ( vehicle.ctOwner != nullptr ) }; + auto const isowned { /* ( vehicle.Mechanik == nullptr ) && */ ( vehicle.ctOwner != nullptr ) && ( vehicle.ctOwner->Vehicle() != m_input.vehicle ) }; auto const isplayervehicle { ( m_input.train != nullptr ) && ( m_input.train->Dynamic() == m_input.vehicle ) }; auto const isdieselenginepowered { ( mover.EngineType == TEngineType::DieselElectric ) || ( mover.EngineType == TEngineType::DieselEngine ) }; auto const isdieselinshuntmode { mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric }; diff --git a/messaging.cpp b/messaging.cpp index cae047ff..95712c0c 100644 --- a/messaging.cpp +++ b/messaging.cpp @@ -370,7 +370,7 @@ WyslijObsadzone() r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x; r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y; r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z; - r.iPar[ 16 * i + 7 ] = static_cast( vehicle->Mechanik->GetAction() ); + r.iPar[ 16 * i + 7 ] = static_cast( vehicle->Mechanik->action() ); strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->IsolatedName().c_str() ); strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->TrainName().c_str() ); i++; diff --git a/renderer.cpp b/renderer.cpp index 58de9245..e1c23d04 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -179,16 +179,17 @@ opengl_particles::update( opengl_camera const &Camera ) { if( m_buffercapacity < m_particlevertices.size() ) { // allocate gpu side buffer big enough to hold the data m_buffercapacity = 0; - if( m_buffer != -1 ) { + if( m_buffer != (GLuint)-1 ) { // get rid of the old buffer ::glDeleteBuffers( 1, &m_buffer ); + m_buffer = (GLuint)-1; } ::glGenBuffers( 1, &m_buffer ); - ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); - if( m_buffer > 0 ) { + if( ( m_buffer > 0 ) && ( m_buffer != (GLuint)-1 ) ) { // if we didn't get a buffer we'll try again during the next draw call // NOTE: we match capacity instead of current size to reduce number of re-allocations auto const particlecount { m_particlevertices.capacity() }; + ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); ::glBufferData( GL_ARRAY_BUFFER, particlecount * sizeof( particle_vertex ), @@ -198,7 +199,7 @@ opengl_particles::update( opengl_camera const &Camera ) { // TBD: throw a bad_alloc? ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" ); ::glDeleteBuffers( 1, &m_buffer ); - m_buffer = -1; + m_buffer = (GLuint)-1; } else { m_buffercapacity = particlecount; @@ -206,7 +207,7 @@ opengl_particles::update( opengl_camera const &Camera ) { } } // ...send the data... - if( m_buffer > 0 ) { + if( ( m_buffer > 0 ) && ( m_buffer != (GLuint)-1 ) ) { // if the buffer exists at this point it's guaranteed to be big enough to hold our data ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); ::glBufferSubData( @@ -225,6 +226,7 @@ opengl_particles::render( int const Textureunit ) { if( false == Global.Smoke ) { return; } if( m_buffercapacity == 0 ) { return; } if( m_particlevertices.empty() ) { return; } + if( ( m_buffer == 0 ) || ( m_buffer == (GLuint)-1 ) ) { return; } // setup... ::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); @@ -239,6 +241,10 @@ opengl_particles::render( int const Textureunit ) { // ...draw... ::glDrawArrays( GL_QUADS, 0, m_particlevertices.size() ); // ...and cleanup + ::glBindBuffer( GL_ARRAY_BUFFER, 0 ); + if( Global.bUseVBO ) { + gfx::opengl_vbogeometrybank::reset(); + } ::glPopClientAttrib(); } @@ -3163,10 +3169,6 @@ opengl_renderer::Render_particles() { Bind_Texture( m_smoketexture ); m_particlerenderer.render( m_diffusetextureunit ); - if( Global.bUseVBO ) { - // shouldn't be strictly necessary but, eh - gfx::opengl_vbogeometrybank::reset(); - } ::glDepthMask( GL_TRUE ); ::glEnable( GL_LIGHTING ); diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index a58e16d1..5d686521 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -672,7 +672,7 @@ state_serializer::deserialize_endtrainset( cParser &Input, scene::scratch_data & for( auto *vehicle : Scratchpad.trainset.vehicles ) { // go through list of vehicles in the trainset, coupling them together and checking for potential driver if( ( vehicle->Mechanik != nullptr ) - && ( vehicle->Mechanik->Primary() ) ) { + && ( vehicle->Mechanik->primary() ) ) { // primary driver will receive the timetable for this trainset Scratchpad.trainset.driver = vehicle; // they'll also receive assignment data if there's any diff --git a/version.h b/version.h index f159e50b..e4cf28bb 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 902 +#define VERSION_MINOR 906 #define VERSION_REVISION 0 From bb229bbac910ddd273ed66db0b7175983cc312f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Fri, 6 Sep 2019 18:02:00 +0200 Subject: [PATCH 02/15] Disintegration of brakes from UniCtrl --- McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 65df7e6f..382948dc 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -979,6 +979,8 @@ public: TSecuritySystem SecuritySystem; TUniversalCtrlTable UniCtrlList; /*lista pozycji uniwersalnego nastawnika*/ int UniCtrlListSize = 0; /*wielkosc listy pozycji uniwersalnego nastawnika*/ + bool UniCtrlIntegratedBrakePNCtrl = false; /*zintegrowany nastawnik JH obsluguje hamulec PN*/ + bool UniCtrlIntegratedBrakeCtrl = false; /*zintegrowany nastawnik JH obsluguje hamowanie*/ /*-sekcja parametrow dla lokomotywy elektrycznej*/ TSchemeTable RList; /*lista rezystorow rozruchowych i polaczen silnikow, dla dizla: napelnienia*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index db55491f..2e2bf60e 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6336,17 +6336,20 @@ void TMoverParameters::CheckEIMIC(double dt) } break; case 3: - if ((UniCtrlList[MainCtrlPos].mode != BrakeCtrlPos) && (MainCtrlActualPos == MainCtrlPos)) //there was no move of controller, but brake only + if (UniCtrlIntegratedBrakePNCtrl) { - if (BrakeCtrlPos < UniCtrlList[MainCtrlPosNo].mode) - BrakeLevelSet(UniCtrlList[MainCtrlPosNo].mode); //bottom clamping - if (BrakeCtrlPos > UniCtrlList[0].mode) - BrakeLevelSet(UniCtrlList[0].mode); //top clamping - while (BrakeCtrlPos > UniCtrlList[MainCtrlPos].mode) DecMainCtrl(1); //find nearest position - while (BrakeCtrlPos < UniCtrlList[MainCtrlPos].mode) IncMainCtrl(1); //find nearest position + if ((UniCtrlList[MainCtrlPos].mode != BrakeCtrlPos) && (MainCtrlActualPos == MainCtrlPos)) //there was no move of controller, but brake only + { + if (BrakeCtrlPos < UniCtrlList[MainCtrlPosNo].mode) + BrakeLevelSet(UniCtrlList[MainCtrlPosNo].mode); //bottom clamping + if (BrakeCtrlPos > UniCtrlList[0].mode) + BrakeLevelSet(UniCtrlList[0].mode); //top clamping + while (BrakeCtrlPos > UniCtrlList[MainCtrlPos].mode) DecMainCtrl(1); //find nearest position + while (BrakeCtrlPos < UniCtrlList[MainCtrlPos].mode) IncMainCtrl(1); //find nearest position + } + else //controller was moved + BrakeLevelSet(UniCtrlList[MainCtrlPos].mode); } - else //controller was moved - BrakeLevelSet(UniCtrlList[MainCtrlPos].mode); if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) { @@ -6363,6 +6366,10 @@ void TMoverParameters::CheckEIMIC(double dt) } if (Hamulec->GetEDBCP() > 0.3 && eimic < 0) //when braking with pneumatic brake eimic = 0; //shut off retarder + if (UniCtrlIntegratedBrakeCtrl == false) + { + eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : eimic); + } } auto const eimicpowerenabled { @@ -9533,6 +9540,8 @@ void TMoverParameters::LoadFIZ_RList( std::string const &Input ) { void TMoverParameters::LoadFIZ_UCList(std::string const &Input) { extract_value(UniCtrlListSize, "Size", Input, ""); + UniCtrlIntegratedBrakeCtrl = (extract_value("IntegratedBrake", Input) == "Yes"); + UniCtrlIntegratedBrakePNCtrl = (extract_value("IntegratedBrakePN", Input) == "Yes"); } From 414ef2e3623ada0cfaf5f9ce3db43fa9f17a9300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Fri, 6 Sep 2019 23:25:17 +0200 Subject: [PATCH 03/15] Added spring parking brake --- McZapkie/MOVER.h | 30 ++++++++++ McZapkie/Mover.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++- Train.cpp | 76 ++++++++++++++++++++++++- Train.h | 7 +++ command.cpp | 9 ++- command.h | 7 +++ 6 files changed, 260 insertions(+), 4 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 382948dc..4c8fa8e7 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -861,6 +861,30 @@ private: float temperatura2 { 40.0 }; }; + struct spring_brake { + std::shared_ptr Cylinder; + bool Activate { false }; //Input: switching brake on/off in exploitation - main valve/switch + bool ShuttOff { true }; //Input: shutting brake off during failure - valve in pneumatic container + bool Release { false }; //Input: emergency releasing rod + + bool IsReady{ false }; //Output: readyness to braking - cylinder is armed, spring is tentioned + bool IsActive{ false }; //Output: brake is working + + bool PNBrakeConnection{ false }; //Conf: connection to pneumatic brake cylinders + double MaxSetPressure { 0.0 }; //Conf: Maximal pressure for switched off brake + double ResetPressure{ 0.0 }; //Conf: Pressure for arming brake cylinder + double MinForcePressure{ 0.1 }; //Conf: Minimal pressure for zero force + double MaxBrakeForce{ 0.0 }; //Conf: Maximal tension for brake pads/shoes + double PressureOn{ -2.0 }; //Conf: Pressure changing ActiveFlag to "On" + double PressureOff{ -1.0 }; //Conf: Pressure changing ActiveFlag to "Off" + double ValveOffArea{ 0.0 }; //Conf: Area of filling valve + double ValveOnArea{ 0.0 }; //Conf: Area of dumping valve + double ValvePNBrakeArea{ 0.0 }; //Conf: Area of bypass to brake cylinders + + int MultiTractionCoupler{ 127 }; //Conf: Coupling flag necessary for transmitting the command + + }; + public: double dMoveLen = 0.0; @@ -920,6 +944,7 @@ public: std::shared_ptr LocHandle; std::shared_ptr Pipe; std::shared_ptr Pipe2; + spring_brake SpringBrake; TLocalBrake LocalBrake = TLocalBrake::NoBrake; /*rodzaj hamulca indywidualnego*/ TBrakePressureTable BrakePressureTable; /*wyszczegolnienie cisnien w rurze*/ @@ -1471,6 +1496,9 @@ public: bool BatterySwitch(bool State); bool EpFuseSwitch(bool State); + bool SpringBrakeActivate(bool State); + bool SpringBrakeShutOff(bool State); + bool SpringBrakeRelease(); /*! stopnie hamowania - hamulec zasadniczy*/ bool IncBrakeLevelOld(void); @@ -1500,6 +1528,7 @@ public: void CompressorCheck(double dt);/*wlacza, wylacza kompresor, laduje zbiornik*/ void UpdatePantVolume(double dt); //Ra void UpdateScndPipePressure(double dt); + void UpdateSpringBrake(double dt); double GetDVc(double dt); /*funkcje obliczajace sily*/ @@ -1617,6 +1646,7 @@ private: void LoadFIZ_Cntrl( std::string const &line ); void LoadFIZ_Blending(std::string const &line); void LoadFIZ_DCEMUED(std::string const &line); + void LoadFIZ_SpringBrake(std::string const &line); void LoadFIZ_Light( std::string const &line ); void LoadFIZ_Security( std::string const &line ); void LoadFIZ_Clima( std::string const &line ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 2e2bf60e..0c7ccbc5 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2567,6 +2567,57 @@ bool TMoverParameters::EpFuseSwitch(bool State) // else SendCtrlToNext("EpFuseSwitch", 0, CabNo); } +// ************************************************************************************************* +// yB: 20190906 +// włączenie / wyłączenie hamulca sprezynowego +// ************************************************************************************************* +bool TMoverParameters::SpringBrakeActivate(bool State) +{ + if (Battery) + { + SendCtrlToNext("SpringBrakeActivate", int(State), CabNo, SpringBrake.MultiTractionCoupler); + + if (SpringBrake.Activate != State) + { + SpringBrake.Activate = State; + return true; + } + } + return false; +} + +// ************************************************************************************************* +// yB: 20190906 +// włączenie / wyłączenie odciecia hamulca sprezynowego +// ************************************************************************************************* +bool TMoverParameters::SpringBrakeShutOff(bool State) +{ + if (SpringBrake.ShuttOff != State) + { + SpringBrake.ShuttOff = State; + return true; + } + else + return false; + +} + +// ************************************************************************************************* +// yB: 20190906 +// wyluzowanie hamulca sprezynowego +// ************************************************************************************************* +bool TMoverParameters::SpringBrakeRelease() +{ + if (SpringBrake.IsReady && SpringBrake.Cylinder->P() < SpringBrake.MinForcePressure) + { + SpringBrake.IsReady = false; + return true; + } + else + return false; + +} + // ************************************************************************************************* // Q: 20160710 // kierunek do tyłu @@ -3980,6 +4031,8 @@ void TMoverParameters::UpdateScndPipePressure(double dt) TMoverParameters *c; double dv1, dv2, dV; + UpdateSpringBrake(dt); + dv1 = 0; dv2 = 0; @@ -4032,6 +4085,34 @@ void TMoverParameters::UpdateScndPipePressure(double dt) } } + +// ************************************************************************************************* +// yB: 20190906 +// Aktualizacja ciśnienia w hamulcu sprezynowym +// ************************************************************************************************* +void TMoverParameters::UpdateSpringBrake(double dt) +{ + double SBP = SpringBrake.Cylinder->P(); + double BP = SpringBrake.PNBrakeConnection ? BrakePress : 0; + double MSP = SpringBrake.ShuttOff ? 0 : SpringBrake.MaxSetPressure; + if (!SpringBrake.Activate) + { + double desired_press = std::min(std::max(MSP, BP), Pipe2->P()); + double dv = PF(desired_press, SBP, SpringBrake.ValveOffArea); + SpringBrake.Cylinder->Flow(-dv); + Pipe2->Flow(std::max(dv,0.0)); + } + else + { + double dv = PF(BP, SBP, SpringBrake.ValveOnArea); + SpringBrake.Cylinder->Flow(-dv); + } + if (SBP > SpringBrake.ResetPressure) + SpringBrake.IsReady = true; + SpringBrake.Release = false; + SpringBrake.Cylinder->Act(); +} + // ************************************************************************************************* // Q: 20160715 // oblicza i zwraca przepływ powietrza pomiędzy pojazdami @@ -4373,6 +4454,9 @@ double TMoverParameters::BrakeForce( TTrackParam const &Track ) { K = MaxBrakeForce * ManualBrakeRatio(); } + if (SpringBrake.IsReady) + K += std::max(0.0, SpringBrake.MinForcePressure - SpringBrake.Cylinder->P()) * SpringBrake.MaxBrakeForce; + u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj; if (u * BrakeRigEff > Ntotal) // histereza na nacisku klockow Ntotal = u * BrakeRigEff; @@ -8314,7 +8398,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) if (issection("Blending:", inputline)) { - startBPT = true; LISTLINE = 0; + startBPT = false; LISTLINE = 0; fizlines.emplace( "Blending", inputline); LoadFIZ_Blending( inputline ); continue; @@ -8322,12 +8406,20 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) if (issection("DCEMUED:", inputline)) { - startBPT = true; LISTLINE = 0; + startBPT = false; LISTLINE = 0; fizlines.emplace("DCEMUED", inputline); LoadFIZ_DCEMUED(inputline); continue; } + if (issection("SpringBrake:", inputline)) { + + startBPT = false; LISTLINE = 0; + fizlines.emplace("SpringBrake", inputline); + LoadFIZ_SpringBrake(inputline); + continue; + } + if( issection( "Light:", inputline ) ) { startBPT = false; @@ -9195,6 +9287,30 @@ void TMoverParameters::LoadFIZ_DCEMUED(std::string const &line) { } + +void TMoverParameters::LoadFIZ_SpringBrake(std::string const &line) { + + double vol; + extract_value(vol, "Volume", line, "1"); + if (!SpringBrake.Cylinder) + SpringBrake.Cylinder = std::make_shared(); + SpringBrake.Cylinder->CreateCap(vol); + extract_value(SpringBrake.MaxBrakeForce, "MBF", line, ""); + extract_value(SpringBrake.MaxSetPressure, "MaxSP", line, ""); + extract_value(SpringBrake.ResetPressure, "ResetP", line, ""); + extract_value(SpringBrake.MinForcePressure, "MinFP", line, ""); + extract_value(SpringBrake.PressureOff, "PressOff", line, ""); + extract_value(SpringBrake.PressureOn, "PressOn", line, ""); + extract_value(SpringBrake.ValveOffArea, "ValveOnArea", line, ""); + extract_value(SpringBrake.ValveOnArea, "ValveOffArea", line, ""); + extract_value(SpringBrake.ValvePNBrakeArea, "ValvePNBArea", line, ""); + SpringBrake.PNBrakeConnection = SpringBrake.ValvePNBrakeArea > 0; + extract_value(SpringBrake.MultiTractionCoupler, "MTC", line, ""); + SpringBrake.ShuttOff = false; + SpringBrake.Activate = false; + SpringBrake.IsReady = true; +} + void TMoverParameters::LoadFIZ_Light( std::string const &line ) { LightPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Light", line ) ); @@ -9929,6 +10045,11 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Pipe2 = std::make_shared(); // zabezpieczenie, bo sie PG wywala... :( Pipe->CreateCap( ( std::max( Dim.L, 14.0 ) + 0.5 ) * Spg * 1 ); // dlugosc x przekroj x odejscia i takie tam Pipe2->CreateCap( ( std::max( Dim.L, 14.0 ) + 0.5 ) * Spg * 1 ); + if (!SpringBrake.Cylinder) + { + SpringBrake.Cylinder = std::make_shared(); + SpringBrake.Cylinder->CreateCap(1); + } if( LightsPosNo > 0 ) LightsPos = LightsDefPos; @@ -10700,6 +10821,16 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C ScndCtrlActualPos = static_cast(round(CValue1)); OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } + else if (Command == "SpringBrakeActivate") + { + if (Battery) + { + SpringBrake.Activate = CValue1 > 0; + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else + OK = true; + } return OK; // dla true komenda będzie usunięta, dla false wykonana ponownie } diff --git a/Train.cpp b/Train.cpp index f670d74e..fb938be1 100644 --- a/Train.cpp +++ b/Train.cpp @@ -352,7 +352,14 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::generictoggle6, &TTrain::OnCommand_generictoggle }, { user_command::generictoggle7, &TTrain::OnCommand_generictoggle }, { user_command::generictoggle8, &TTrain::OnCommand_generictoggle }, - { user_command::generictoggle9, &TTrain::OnCommand_generictoggle } + { user_command::generictoggle9, &TTrain::OnCommand_generictoggle }, + { user_command::springbraketoggle, &TTrain::OnCommand_springbraketoggle }, + { user_command::springbrakeenable, &TTrain::OnCommand_springbrakeenable }, + { user_command::springbrakedisable, &TTrain::OnCommand_springbrakedisable }, + { user_command::springbrakeshutofftoggle, &TTrain::OnCommand_springbrakeshutofftoggle }, + { user_command::springbrakeshutoffenable, &TTrain::OnCommand_springbrakeshutoffenable }, + { user_command::springbrakeshutoffdisable, &TTrain::OnCommand_springbrakeshutoffdisable }, + { user_command::springbrakerelease, &TTrain::OnCommand_springbrakerelease } }; std::vector const TTrain::fPress_labels = { @@ -4224,6 +4231,73 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command } } +void TTrain::OnCommand_springbraketoggle(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + if (false == Train->mvOccupied->SpringBrake.Activate) { + // turn on + OnCommand_springbrakeenable(Train, Command); + } + else { + //turn off + OnCommand_springbrakedisable(Train, Command); + } + } +}; + +void TTrain::OnCommand_springbrakeenable(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SpringBrakeActivate(true); + } +}; + +void TTrain::OnCommand_springbrakedisable(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SpringBrakeActivate(false); + } +}; +void TTrain::OnCommand_springbrakeshutofftoggle(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + if (false == Train->mvOccupied->SpringBrake.ShuttOff) { + // turn on + OnCommand_springbrakeshutoffenable(Train, Command); + } + else { + //turn off + OnCommand_springbrakeshutoffdisable(Train, Command); + } + } +}; + +void TTrain::OnCommand_springbrakeshutoffenable(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SpringBrakeShutOff(true); + } +}; + +void TTrain::OnCommand_springbrakeshutoffdisable(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SpringBrakeShutOff(false); + } +}; + +void TTrain::OnCommand_springbrakerelease(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + + auto *vehicle{ Train->find_nearest_consist_vehicle() }; + if (vehicle == nullptr) { return; } + Train->mvOccupied->SpringBrakeRelease(); + } +}; + void TTrain::OnCommand_doorlocktoggle( TTrain *Train, command_data const &Command ) { if( Train->ggDoorSignallingButton.SubModel == nullptr ) { diff --git a/Train.h b/Train.h index 62a44097..842af209 100644 --- a/Train.h +++ b/Train.h @@ -349,6 +349,13 @@ class TTrain { static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command ); static void OnCommand_generictoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_springbraketoggle(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakeenable(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakedisable(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakeshutofftoggle(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakeshutoffenable(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakeshutoffdisable(TTrain *Train, command_data const &Command); + static void OnCommand_springbrakerelease(TTrain *Train, command_data const &Command); // members diff --git a/command.cpp b/command.cpp index 5b27f32f..9d7bdc6e 100644 --- a/command.cpp +++ b/command.cpp @@ -228,7 +228,14 @@ commanddescription_sequence Commands_descriptions = { { "motorblowerstogglerear", command_target::vehicle }, { "motorblowersdisableall", command_target::vehicle }, { "coolingfanstoggle", command_target::vehicle }, - { "tempomattoggle", command_target::vehicle } + { "tempomattoggle", command_target::vehicle }, + { "springbraketoggle", command_target::vehicle }, + { "springbrakeenable", command_target::vehicle }, + { "springbrakedisable", command_target::vehicle }, + { "springbrakeshutofftoggle", command_target::vehicle }, + { "springbrakeshutoffenable", command_target::vehicle }, + { "springbrakeshutoffdisable", command_target::vehicle }, + { "springbrakerelease", command_target::vehicle } }; diff --git a/command.h b/command.h index 9a06cd14..89904862 100644 --- a/command.h +++ b/command.h @@ -222,6 +222,13 @@ enum class user_command { motorblowersdisableall, coolingfanstoggle, tempomattoggle, + springbraketoggle, + springbrakeenable, + springbrakedisable, + springbrakeshutofftoggle, + springbrakeshutoffenable, + springbrakeshutoffdisable, + springbrakerelease, none = -1 }; From 2b1fe26265c24c60847909b7ef1a47da8e3dddba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 7 Sep 2019 15:03:33 +0200 Subject: [PATCH 04/15] Springbrake manometer and indicators --- McZapkie/MOVER.h | 1 + McZapkie/Mover.cpp | 11 +++++++---- Train.cpp | 15 +++++++++++++++ Train.h | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 4c8fa8e7..5575c5d9 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -869,6 +869,7 @@ private: bool IsReady{ false }; //Output: readyness to braking - cylinder is armed, spring is tentioned bool IsActive{ false }; //Output: brake is working + double SBP{ 0.0 }; //Output: pressure in spring brake cylinder bool PNBrakeConnection{ false }; //Conf: connection to pneumatic brake cylinders double MaxSetPressure { 0.0 }; //Conf: Maximal pressure for switched off brake diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 0c7ccbc5..1e5d59aa 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -4092,25 +4092,28 @@ void TMoverParameters::UpdateScndPipePressure(double dt) // ************************************************************************************************* void TMoverParameters::UpdateSpringBrake(double dt) { - double SBP = SpringBrake.Cylinder->P(); double BP = SpringBrake.PNBrakeConnection ? BrakePress : 0; double MSP = SpringBrake.ShuttOff ? 0 : SpringBrake.MaxSetPressure; if (!SpringBrake.Activate) { double desired_press = std::min(std::max(MSP, BP), Pipe2->P()); - double dv = PF(desired_press, SBP, SpringBrake.ValveOffArea); + double dv = PF(desired_press, SpringBrake.SBP, SpringBrake.ValveOffArea); SpringBrake.Cylinder->Flow(-dv); Pipe2->Flow(std::max(dv,0.0)); } else { - double dv = PF(BP, SBP, SpringBrake.ValveOnArea); + double dv = PF(BP, SpringBrake.SBP, SpringBrake.ValveOnArea); SpringBrake.Cylinder->Flow(-dv); } - if (SBP > SpringBrake.ResetPressure) + if (SpringBrake.SBP > SpringBrake.ResetPressure) SpringBrake.IsReady = true; + + SpringBrake.IsActive = SpringBrake.SBP < (SpringBrake.IsActive ? SpringBrake.PressureOff : SpringBrake.PressureOn); + SpringBrake.Release = false; SpringBrake.Cylinder->Act(); + SpringBrake.SBP = SpringBrake.Cylinder->P(); } // ************************************************************************************************* diff --git a/Train.cpp b/Train.cpp index fb938be1..d0b96ee1 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5899,6 +5899,8 @@ bool TTrain::Update( double const Deltatime ) btLampkaBrakeProfileG.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_G ) ); btLampkaBrakeProfileP.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_P ) ); btLampkaBrakeProfileR.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_R ) ); + btLampkaSpringBrakeActive.Turn( mvOccupied->SpringBrake.IsActive ); + btLampkaSpringBrakeInactive.Turn( !mvOccupied->SpringBrake.IsActive ); // light indicators // NOTE: sides are hardcoded to deal with setups where single cab is equipped with all indicators btLampkaUpperLight.Turn( ( mvOccupied->iLights[ end::front ] & light::headlight_upper ) != 0 ); @@ -5947,6 +5949,8 @@ bool TTrain::Update( double const Deltatime ) btLampkaBrakeProfileG.Turn( false ); btLampkaBrakeProfileP.Turn( false ); btLampkaBrakeProfileR.Turn( false ); + btLampkaSpringBrakeActive.Turn( false ); + btLampkaSpringBrakeInactive.Turn( false ); btLampkaMaxSila.Turn( false ); btLampkaPrzekrMaxSila.Turn( false ); btLampkaRadio.Turn( false ); @@ -7572,6 +7576,8 @@ void TTrain::clear_cab_controls() btLampkaBrakeProfileG.Clear(); btLampkaBrakeProfileP.Clear(); btLampkaBrakeProfileR.Clear(); + btLampkaSpringBrakeActive.Clear(); + btLampkaSpringBrakeInactive.Clear(); btLampkaSprezarka.Clear(); btLampkaSprezarkaB.Clear(); btLampkaSprezarkaOff.Clear(); @@ -7979,6 +7985,8 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co { "i-brakeprofileg:", btLampkaBrakeProfileG }, { "i-brakeprofilep:", btLampkaBrakeProfileP }, { "i-brakeprofiler:", btLampkaBrakeProfileR }, + { "i-springbrakeactive:", btLampkaSpringBrakeActive }, + { "i-springbrakeinactive:", btLampkaSpringBrakeInactive }, { "i-braking-ezt:", btLampkaHamowanie1zes }, { "i-braking-ezt2:", btLampkaHamowanie2zes }, { "i-compressor:", btLampkaSprezarka }, @@ -8334,6 +8342,13 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con gauge.Load(Parser, DynamicObject, 0.1); gauge.AssignDouble(&mvControlled->PantPress); } + else if (Label == "springbrakepress:") + { + // manometr cylindra hamulca sprężynowego + auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka + gauge.Load(Parser, DynamicObject, 0.1); + gauge.AssignDouble(&mvOccupied->SpringBrake.SBP); + } else if ((Label == "compressor:") || (Label == "compressorb:")) { // manometr sprezarki/zbiornika glownego diff --git a/Train.h b/Train.h index 842af209..7ca13749 100644 --- a/Train.h +++ b/Train.h @@ -568,6 +568,8 @@ public: // reszta może by?publiczna TButton btLampkaBrakeProfileG; // cargo train brake acting speed TButton btLampkaBrakeProfileP; // passenger train brake acting speed TButton btLampkaBrakeProfileR; // rapid brake acting speed + TButton btLampkaSpringBrakeActive; + TButton btLampkaSpringBrakeInactive; // KURS90 TButton btLampkaBoczniki; TButton btLampkaMaxSila; From dc688f08c323e4c4f44a747fe2cd3c602a8d7c65 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 10 Sep 2019 23:38:13 +0200 Subject: [PATCH 05/15] maintenance: minor code tweaks --- Train.cpp | 3 ++- TrkFoll.cpp | 2 +- driverkeyboardinput.cpp | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Train.cpp b/Train.cpp index d0b96ee1..eae41be2 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5157,6 +5157,7 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com 1 : -1 ) }; if( false == Train->CabChange( movedirection ) ) { + // current vehicle doesn't extend any farther in this direction, check if we there's one connected we can move to auto const exitdirection { ( movedirection > 0 ? end::front : @@ -8035,7 +8036,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co } } // TODO: move viable dedicated lights to the automatic light array - std::unordered_map const autolights = { + std::unordered_map const autolights = { { "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit }, { "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit }, { "i-doorstep:", &mvOccupied->Doors.step_enabled } diff --git a/TrkFoll.cpp b/TrkFoll.cpp index d7f2aebe..d1dba363 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -244,7 +244,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) { // gdy zostaje na tym samym torze (przesuwanie już nie zmienia toru) if (bPrimary) { // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki - if (Owner->MoverParameters->ActiveCab != 0) { + if (Owner->MoverParameters->CabNo != 0) { pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 ); pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 ); diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 01883f12..6ee2c2a9 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -231,6 +231,13 @@ driverkeyboard_input::default_bindings() { { user_command::motorblowersdisableall, GLFW_KEY_M | keymodifier::control } // coolingfanstoggle // tempomattoggle + // springbraketoggle + // springbrakeenable + // springbrakedisable + // springbrakeshutofftoggle + // springbrakeshutoffenable + // springbrakeshutoffdisable + // springbrakerelease }; } From 3153ffc499bb6d675489523c34a416c14237068e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Mon, 9 Sep 2019 21:11:13 +0200 Subject: [PATCH 06/15] Added spring brake parameters to python dictionary --- Train.cpp | 18 +++++++++++++++--- Train.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Train.cpp b/Train.cpp index eae41be2..36b276d8 100644 --- a/Train.cpp +++ b/Train.cpp @@ -404,9 +404,12 @@ TTrain::TTrain() { fDieselParams[i][j] = 0.0; } - for( int i = 0; i < 20; ++i ) - for( int j = 0; j < 3; ++j ) - fPress[ i ][ j ] = 0.0; + for ( int i = 0; i < 20; ++i ) + { + for ( int j = 0; j < 3; ++j ) + fPress[i][j] = 0.0; + bBrakes[i][0] = bBrakes[i][1] = 0.0; + } } bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) @@ -509,6 +512,7 @@ dictionary_source *TTrain::GetTrainState() { char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" }; char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "engine_temp", "res1" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; + char const *TXTB[ 2 ] = { "spring_active", "spring_shutoff" }; for( int j = 0; j < 10; ++j ) dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); for( int i = 0; i < 8; ++i ) { @@ -534,6 +538,9 @@ dictionary_source *TTrain::GetTrainState() { for( int j = 0; j < 3; ++j ) { dict->insert( ( "eimp_pn" + std::to_string( i + 1 ) + "_" + TXTP[ j ] ), fPress[ i ][ j ] ); } + for ( int j = 0; j < 2; ++j) { + dict->insert( ( "brakes_" + std::to_string( i + 1 ) + "_" + TXTB[ j ] ), bBrakes[ i ][ j ] ); + } } // multi-unit state data dict->insert( "car_no", iCarNo ); @@ -5410,6 +5417,8 @@ bool TTrain::Update( double const Deltatime ) fPress[i][0] = p->MoverParameters->BrakePress; fPress[i][1] = p->MoverParameters->PipePress; fPress[i][2] = p->MoverParameters->ScndPipePress; + bBrakes[i][0] = p->MoverParameters->SpringBrake.IsActive; + bBrakes[i][1] = p->MoverParameters->SpringBrake.ShuttOff; bDoors[i][1] = ( p->MoverParameters->Doors.instances[ side::left ].position > 0.f ); bDoors[i][2] = ( p->MoverParameters->Doors.instances[ side::right ].position > 0.f ); bDoors[i][3] = ( p->MoverParameters->Doors.instances[ side::left ].step_position > 0.f ); @@ -5493,6 +5502,9 @@ bool TTrain::Update( double const Deltatime ) = bDoors[i][3] = bDoors[i][4] = false; + bBrakes[i][0] + = bBrakes[i][1] + = false; bSlip[i] = false; iUnits[i] = 0; cCode[i] = 0; //'0'; diff --git a/Train.h b/Train.h index 7ca13749..591495a3 100644 --- a/Train.h +++ b/Train.h @@ -688,6 +688,7 @@ private: public: float fPress[20][3]; // cisnienia dla wszystkich czlonow + float bBrakes[20][2]; // zalaczenie i dzialanie hamulcow static std::vector const fPress_labels; float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych float fDieselParams[9][10]; // parametry dla silnikow asynchronicznych From b6ca21d2803a15a4e3d31af6dd247d1d5a469545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Mon, 9 Sep 2019 22:39:45 +0200 Subject: [PATCH 07/15] Manual and automatic sanding working independently in EIM vehicles --- McZapkie/MOVER.h | 5 ++++ McZapkie/Mover.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++-- Train.cpp | 4 +-- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 5575c5d9..944d917c 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1197,6 +1197,9 @@ public: double UnitBrakeForce = 0.0; /*!s siła hamowania przypadająca na jeden element*/ double Ntotal = 0.0; /*!s siła nacisku klockow*/ bool SlippingWheels = false; bool SandDose = false; /*! poslizg kol, sypanie piasku*/ + bool SandDoseManual = false; /*piaskowanie reczne*/ + bool SandDoseAuto = false; /*piaskowanie automatyczne*/ + bool SandDoseAutoAllow = true; /*zezwolenie na automatyczne piaskowanie*/ double Sand = 0.0; /*ilosc piasku*/ double BrakeSlippingTimer = 0.0; /*pomocnicza zmienna do wylaczania przeciwposlizgu*/ double dpBrake = 0.0; double dpPipe = 0.0; double dpMainValve = 0.0; double dpLocalValve = 0.0; @@ -1488,6 +1491,8 @@ public: bool AddPulseForce(int Multipler);/*dla drezyny*/ + bool SandboxManual( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ + bool SandboxAuto( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ /*! zbijanie czuwaka/SHP*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 1e5d59aa..eb490ede 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2341,6 +2341,63 @@ bool TMoverParameters::AddPulseForce(int Multipler) return APF; } +// ************************************************************************************************* +// yB: 20190909 +// sypanie piasku reczne +// ************************************************************************************************* +bool TMoverParameters::SandboxManual(bool const State, range_t const Notify) +{ + bool result{ false }; + + if (SandDoseManual != State) { + if (SandDoseManual == false) { + // switch on + if (Sand > 0) { + SandDoseManual = true; + result = true; + } + } + else { + // switch off + SandDoseManual = false; + result = true; + } + } + + Sandbox(SandDoseManual || SandDoseAuto, Notify); + + return result; +} + +// ************************************************************************************************* +// yB: 20190909 +// sypanie piasku automatyczne +// ************************************************************************************************* +bool TMoverParameters::SandboxAuto(bool const State, range_t const Notify) +{ + bool result{ false }; + bool NewState = State && SandDoseAutoAllow; + if (SandDoseAuto != NewState) { + if (SandDoseAuto == false) { + // switch on + if (Sand > 0) { + SandDoseAuto = true; + result = true; + } + } + else { + // switch off + SandDoseAuto = false; + result = true; + } + } + + Sandbox(SandDoseManual || SandDoseAuto, Notify); + + return result; +} + + // ************************************************************************************************* // Q: 20160713 // sypanie piasku @@ -5507,11 +5564,11 @@ double TMoverParameters::TractionForce( double dt ) { if( ( SlippingWheels ) ) { PosRatio = 0; tmp = 10; - Sandbox( true, range_t::unit ); + SandboxAuto( true, range_t::unit ); } // przeciwposlizg else { // switch sandbox off - Sandbox( false, range_t::unit ); + SandboxAuto( false, range_t::unit ); } eimv_pr += Max0R(Min0R(PosRatio - eimv_pr, 0.02), -0.02) * 12 * diff --git a/Train.cpp b/Train.cpp index 36b276d8..f4d802a5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -1437,13 +1437,13 @@ void TTrain::OnCommand_sandboxactivate( TTrain *Train, command_data const &Comma // visual feedback Train->ggSandButton.UpdateValue( 1.0, Train->dsbSwitch ); - Train->mvControlled->Sandbox( true ); + Train->mvControlled->SandboxManual( true ); } else if( Command.action == GLFW_RELEASE) { // visual feedback Train->ggSandButton.UpdateValue( 0.0 ); - Train->mvControlled->Sandbox( false ); + Train->mvControlled->SandboxManual( false ); } } From 12a95fc423fe1b94188fc1c2ed89f1200f8ffb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Mon, 9 Sep 2019 23:05:45 +0200 Subject: [PATCH 08/15] Added automatic sanding allowance switch --- McZapkie/MOVER.h | 5 +++-- McZapkie/Mover.cpp | 18 ++++++++++++++++++ Train.cpp | 32 ++++++++++++++++++++++++++++++++ Train.h | 4 ++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 944d917c..c5d192b1 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1491,9 +1491,10 @@ public: bool AddPulseForce(int Multipler);/*dla drezyny*/ - bool SandboxManual( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ - bool SandboxAuto( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ + bool SandboxManual( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza reczne sypanie piasku*/ + bool SandboxAuto( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza automatyczne sypanie piasku*/ bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ + bool SandboxAutoAllow(bool const State);/*wlacza/wylacza zezwolenie na automatyczne sypanie piasku*/ /*! zbijanie czuwaka/SHP*/ void SSReset(void); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index eb490ede..7d34c73c 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2441,6 +2441,24 @@ bool TMoverParameters::Sandbox( bool const State, range_t const Notify ) return result; } +// ************************************************************************************************* +// yB: 20190909 +// włączenie / wyłączenie automatycznej piasecznicy +// ************************************************************************************************* +bool TMoverParameters::SandboxAutoAllow(bool State) +{ + //SendCtrlToNext("SandboxAutoAllow", int(State), CabNo, ctrain_controll); + + if (SandDoseAutoAllow != State) + { + SandDoseAutoAllow = State; + return true; + } + else + return false; + +} + void TMoverParameters::SSReset(void) { // funkcja pomocnicza dla SecuritySystemReset - w Delphi Reset() SecuritySystem.SystemTimer = 0; diff --git a/Train.cpp b/Train.cpp index f4d802a5..379b0d2c 100644 --- a/Train.cpp +++ b/Train.cpp @@ -1447,6 +1447,37 @@ void TTrain::OnCommand_sandboxactivate( TTrain *Train, command_data const &Comma } } +void TTrain::OnCommand_autosandboxtoggle(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + if (false == Train->mvOccupied->SandDoseAutoAllow) { + // turn on + OnCommand_autosandboxactivate(Train, Command); + } + else { + //turn off + OnCommand_autosandboxdeactivate(Train, Command); + } + } +}; + +void TTrain::OnCommand_autosandboxactivate(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SandboxAutoAllow(true); + Train->ggAutoSandAllow.UpdateValue(1.0, Train->dsbSwitch); + } +}; + +void TTrain::OnCommand_autosandboxdeactivate(TTrain *Train, command_data const &Command) { + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SandboxAutoAllow(false); + Train->ggAutoSandAllow.UpdateValue(0.0, Train->dsbSwitch); + } +}; + void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { @@ -8122,6 +8153,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "security_reset_bt:", ggSecurityResetButton }, { "releaser_bt:", ggReleaserButton }, { "sand_bt:", ggSandButton }, + { "autosandallow_sw:", ggAutoSandAllow }, { "antislip_bt:", ggAntiSlipButton }, { "horn_bt:", ggHornButton }, { "hornlow_bt:", ggHornLowButton }, diff --git a/Train.h b/Train.h index 591495a3..fcc2859f 100644 --- a/Train.h +++ b/Train.h @@ -200,6 +200,9 @@ class TTrain { static void OnCommand_alarmchaintoggle( TTrain *Train, command_data const &Command ); static void OnCommand_wheelspinbrakeactivate( TTrain *Train, command_data const &Command ); static void OnCommand_sandboxactivate( TTrain *Train, command_data const &Command ); + static void OnCommand_autosandboxtoggle(TTrain *Train, command_data const &Command); + static void OnCommand_autosandboxactivate(TTrain *Train, command_data const &Command); + static void OnCommand_autosandboxdeactivate(TTrain *Train, command_data const &Command); static void OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &Command ); static void OnCommand_trainbrakeoperationmodeincrease(TTrain *Train, command_data const &Command); static void OnCommand_trainbrakeoperationmodedecrease(TTrain *Train, command_data const &Command); @@ -413,6 +416,7 @@ public: // reszta może by?publiczna TGauge ggSecurityResetButton; TGauge ggReleaserButton; TGauge ggSandButton; // guzik piasecznicy + TGauge ggAutoSandAllow; // przełącznik piasecznicy TGauge ggAntiSlipButton; TGauge ggFuseButton; TGauge ggConverterFuseButton; // hunter-261211: przycisk odblokowania nadmiarowego przetwornic i ogrzewania From f259c6b96a85f1414f29793bdcbe8e75483927d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 10 Sep 2019 19:52:36 +0200 Subject: [PATCH 09/15] Spring brake disables propulsion in EIM --- Driver.cpp | 5 +++++ McZapkie/Mover.cpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index 20de084e..c784d753 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1788,6 +1788,7 @@ void TController::Activation() auto const localbrakelevel { mvOccupied->LocalBrakePosA }; ZeroSpeed(); ZeroDirection(); + mvOccupied->SpringBrakeActivate(true); if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? 1 : 0].CouplingFlag, ctrain_controll)) { mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe @@ -2694,6 +2695,7 @@ bool TController::ReleaseEngine() { } // gasimy światła Lights( 0, 0 ); + mvOccupied->SpringBrakeActivate(true); mvOccupied->BatterySwitch( false ); } } @@ -3005,6 +3007,9 @@ bool TController::IncSpeed() // zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime) Doors( false ); } + if (mvOccupied->SpringBrake.IsActive && mvOccupied->SpringBrake.Activate) { + mvOccupied->SpringBrakeActivate(false); + } if( fActionTime < 0.0 ) { // gdy jest nakaz poczekać z jazdą, to nie ruszać return false; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 7d34c73c..c39c7a3e 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6537,7 +6537,8 @@ void TMoverParameters::CheckEIMIC(double dt) auto const eimicpowerenabled { ( ( true == Mains ) || ( Power == 0.0 ) ) && ( ( Doors.instances[ side::left ].open_permit == false ) - && ( Doors.instances[ side::right ].open_permit == false ) ) }; + && ( Doors.instances[ side::right ].open_permit == false ) ) + && ( !SpringBrake.IsActive ) }; eimic = clamp(eimic, -1.0, eimicpowerenabled ? 1.0 : 0.0); } From 10c1497e76013f7e80f1a76741a1143747bf1f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 10 Sep 2019 23:23:56 +0200 Subject: [PATCH 10/15] Added emergency valve for main tank and more complex compressor preset switch --- McZapkie/MOVER.h | 21 ++++++++- McZapkie/Mover.cpp | 107 +++++++++++++++++++++++++++++++++++++------ Train.cpp | 77 +++++++++++++++++++++++++++++++ Train.h | 4 ++ command.cpp | 6 +++ command.h | 6 +++ drivermouseinput.cpp | 3 ++ 7 files changed, 208 insertions(+), 16 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index c5d192b1..133dc3ab 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -306,6 +306,14 @@ enum TProblem // lista problemów taboru, które uniemożliwiają jazdę pr_Ostatni = 0x80000000 // ostatnia flaga bitowa }; +enum TCompressorList // lista parametrów w programatorze sprężarek +{ // pozycje kolejne + cl_Allow = 0, // zezwolenie na pracę sprężarek + cl_SpeedFactor = 1, // mnożnik wydajności + cl_MinFactor = 2, // mnożnik progu załącznika ciśnieniowego + cl_MaxFactor = 3 // mnożnik progu wyłącznika ciśnieniowego +}; + /*ogolne*/ /*lokacja*/ struct TLocation @@ -988,6 +996,14 @@ public: double MinCompressor = 0.0; double MaxCompressor = 0.0; double CompressorSpeed = 0.0; + int CompressorList[4][9]; // pozycje świateł, przód - tył, 1 .. 16 + double EmergencyValveOn = 0.0; + double EmergencyValveOff = 0.0; + bool EmergencyValveOpen = false; + double EmergencyValveArea = 0.0; + int CompressorListPosNo = 0; + int CompressorListDefPos = 1; + bool CompressorListWrap = false; /*cisnienie wlaczania, zalaczania sprezarki, wydajnosc sprezarki*/ TBrakeDelayTable BrakeDelay; /*opoznienie hamowania/odhamowania t/o*/ double AirLeakRate{ 0.01 }; // base rate of air leak from brake system components ( 0.001 = 1 l/sec ) @@ -1285,7 +1301,8 @@ public: double MainsInitTimeCountdown{ 0.0 }; // current state of main circuit initialization, remaining time (in seconds) until it's ready int MainCtrlPos = 0; /*polozenie glownego nastawnika*/ int ScndCtrlPos = 0; /*polozenie dodatkowego nastawnika*/ - int LightsPos = 0; + int LightsPos = 0; /*polozenie przelacznika wielopozycyjnego swiatel*/ + int CompressorListPos = 0; /*polozenie przelacznika wielopozycyjnego sprezarek*/ int ActiveDir = 0; //czy lok. jest wlaczona i w ktorym kierunku: //względem wybranej kabiny: -1 - do tylu, +1 - do przodu, 0 - wylaczona int MaxMainCtrlPosNoDirChange { 0 }; // can't change reverser state with master controller set above this position @@ -1667,6 +1684,7 @@ private: void LoadFIZ_DList( std::string const &Input ); void LoadFIZ_FFList( std::string const &Input ); void LoadFIZ_LightsList( std::string const &Input ); + void LoadFIZ_CompressorList(std::string const &Input); void LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Input ); TPowerType LoadFIZ_PowerDecode( std::string const &Power ); TPowerSource LoadFIZ_SourceDecode( std::string const &Source ); @@ -1683,6 +1701,7 @@ private: bool readFFList( std::string const &line ); bool readWWList( std::string const &line ); bool readLightsList( std::string const &Input ); + bool readCompressorList(std::string const &Input); void BrakeValveDecode( std::string const &s ); //Q 20160719 void BrakeSubsystemDecode(); //Q 20160719 bool EIMDirectionChangeAllow( void ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index c39c7a3e..6f1d78c4 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -295,6 +295,12 @@ ActiveCab( Cab ) for (int k = 0; k < 17; ++k) Lights[b][k] = 0; + for (int b = 0; b < 4; ++b) + for (int k = 1; k < 9; ++k) + CompressorList[ b ][ k ] = 0; + CompressorList[0][0] = 0.0; + CompressorList[1][0] = CompressorList[2][0] = CompressorList[3][0] = 1.0; + for (int b = -1; b <= MainBrakeMaxPos; ++b) { BrakePressureTable[b].PipePressureVal = 0.0; @@ -3612,12 +3618,31 @@ void TMoverParameters::UpdateBrakePressure(double dt) // TODO: clean the method up, a lot of the code is redundant void TMoverParameters::CompressorCheck(double dt) { + + double MaxCompressorF = CompressorList[TCompressorList::cl_MaxFactor][CompressorListPos] * MaxCompressor; + double MinCompressorF = CompressorList[TCompressorList::cl_MinFactor][CompressorListPos] * MinCompressor; + double CompressorSpeedF = CompressorList[TCompressorList::cl_SpeedFactor][CompressorListPos] * CompressorSpeed; + double AllowFactor = CompressorList[TCompressorList::cl_Allow][CompressorListPos]; + + //checking the impact on the compressor allowance + if (AllowFactor > 0.5) { + CompressorAllow = AllowFactor > 1.5; + } + if( VeselVolume == 0.0 ) { return; } + //EmergencyValve + EmergencyValveOpen = (Compressor > (EmergencyValveOpen ? EmergencyValveOff : EmergencyValveOn)); + if (EmergencyValveOpen) { + float dV = PF(0, Compressor, EmergencyValveArea)* dt; + CompressedVolume -= dV; + } + + CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s if( ( true == CompressorGovernorLock ) - && ( Compressor < MinCompressor ) ) { + && ( Compressor < MinCompressorF ) ) { // if the pressure drops below the cut-in level, we can reset compressor governor // TBD, TODO: don't operate the lock without battery power? CompressorGovernorLock = false; @@ -3627,25 +3652,25 @@ void TMoverParameters::CompressorCheck(double dt) CompressorAllow = ConverterAllow; } - if (MaxCompressor - MinCompressor < 0.0001) { + if (MaxCompressorF - MinCompressorF < 0.0001) { // TODO: investigate purpose of this branch and whether it can be removed as it duplicates later code if( ( true == CompressorAllow ) && ( true == CompressorAllowLocal ) && ( true == Mains ) && ( MainCtrlPowerPos() > 0 ) ) { - if( Compressor < MaxCompressor ) { + if( Compressor < MaxCompressorF ) { if( ( EngineType == TEngineType::DieselElectric ) && ( CompressorPower > 0 ) ) { CompressedVolume += - CompressorSpeed - * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor + CompressorSpeedF + * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) * dt; } else { CompressedVolume += - CompressorSpeed - * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor + CompressorSpeedF + * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * dt; TotalCurrent += 0.0015 * Voltage; // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę } @@ -3697,7 +3722,7 @@ void TMoverParameters::CompressorCheck(double dt) || ( CompressorPower == 0 ) || ( CompressorPower == 3 ) ) ); - if( Compressor > MaxCompressor ) { + if( Compressor > MaxCompressorF ) { // wyłącznik ciśnieniowy jest niezależny od sposobu zasilania // TBD, TODO: don't operate the lock without battery power? if( CompressorPower == 3 ) { @@ -3733,8 +3758,8 @@ void TMoverParameters::CompressorCheck(double dt) else { // jeśli nie załączona if( ( LastSwitchingTime > CtrlDelay ) - && ( ( Compressor < MinCompressor ) - || ( ( Compressor < MaxCompressor ) + && ( ( Compressor < MinCompressorF ) + || ( ( Compressor < MaxCompressorF ) && ( false == CompressorGovernorLock ) ) ) ) { // załączenie przy małym ciśnieniu // jeśli nie załączona, a ciśnienie za małe @@ -3809,7 +3834,7 @@ void TMoverParameters::CompressorCheck(double dt) 1.0 ) }; // shouldn't ever get here but, eh CompressedVolume += CompressorSpeed - * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor + * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * enginefactor * dt; } @@ -3823,8 +3848,8 @@ void TMoverParameters::CompressorCheck(double dt) else { // the compressor is a stand-alone device, working at steady pace CompressedVolume += - CompressorSpeed - * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor + CompressorSpeedF + * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * dt; if( ( CompressorPower == 5 ) && ( Couplers[ 1 ].Connected != NULL ) ) { @@ -7892,6 +7917,7 @@ bool startMPT, startMPT0; bool startRLIST, startUCLIST; bool startDLIST, startFFLIST, startWWLIST; bool startLIGHTSLIST; +bool startCOMPRESSORLIST; int LISTLINE; bool issection( std::string const &Name, std::string const &Input ) { @@ -8191,12 +8217,33 @@ bool TMoverParameters::readLightsList( std::string const &Input ) { return false; } parser - >> Lights[ 0 ][ idx ] - >> Lights[ 1 ][ idx ]; + >> Lights[0][idx] + >> Lights[1][idx]; return true; } +bool TMoverParameters::readCompressorList(std::string const &Input) { + + cParser parser(Input); + if (false == parser.getTokens(4, false)) { + WriteLog("Read CompressorList: arguments missing in line " + std::to_string(LISTLINE + 1)); + return false; + } + int idx = LISTLINE++; + if (idx > 8) { + WriteLog("Read CompressorList: number of entries exceeded capacity of the data table"); + return false; + } + parser + >> CompressorList[ 0 ][ idx + 1 ] + >> CompressorList[ 1 ][ idx + 1 ] + >> CompressorList[ 2 ][ idx + 1 ] + >> CompressorList[ 3 ][ idx + 1 ]; + + return true; +} + // ************************************************************************************************* // Q: 20160719 // ************************************************************************************************* @@ -8303,6 +8350,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) startFFLIST = false; startWWLIST = false; startLIGHTSLIST = false; + startCOMPRESSORLIST = false; std::string file = chkpath + TypeName + ".fiz"; WriteLog("LOAD FIZ FROM " + file); @@ -8386,6 +8434,11 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) startLIGHTSLIST = false; continue; } + if ( issection( "endCL", inputline ) ) { + startBPT = false; + startCOMPRESSORLIST = false; + continue; + } // ...then all recognized sections... if( issection( "Param.", inputline ) ) { @@ -8617,6 +8670,14 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) continue; } + if (issection("CompressorList:", inputline)) { + startBPT = false; + fizlines.emplace("CompressorList", inputline); + startCOMPRESSORLIST = true; LISTLINE = 0; + LoadFIZ_CompressorList( inputline ); + continue; + } + // ...and finally, table parsers. // NOTE: once table parsing is enabled it lasts until switched off, when another section is recognized if( true == startBPT ) { @@ -8655,6 +8716,10 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) readLightsList( inputline ); continue; } + if (true == startCOMPRESSORLIST) { + readCompressorList(inputline); + continue; + } } // while line /* in.close(); @@ -8896,6 +8961,9 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { extract_value( MinCompressor, "MinCP", line, "" ); extract_value( MaxCompressor, "MaxCP", line, "" ); extract_value( CompressorSpeed, "CompressorSpeed", line, "" ); + extract_value( EmergencyValveOff, "MinEVP", line, "" ); + extract_value( EmergencyValveOn, "MaxEVP", line, "" ); + extract_value( EmergencyValveArea, "EVArea", line, "" ); { std::map compressorpowers{ { "Main", 0 }, @@ -9767,6 +9835,13 @@ void TMoverParameters::LoadFIZ_LightsList( std::string const &Input ) { extract_value( LightsDefPos, "Default", Input, "" ); } +void TMoverParameters::LoadFIZ_CompressorList(std::string const &Input) { + + extract_value( CompressorListPosNo, "Size", Input, "" ); + extract_value( CompressorListWrap, "Wrap", Input, "" ); + extract_value( CompressorListDefPos, "Default", Input, "" ); +} + void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Line ) { switch( Powerparameters.SourceType ) { @@ -10132,6 +10207,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) if( LightsPosNo > 0 ) LightsPos = LightsDefPos; + if (CompressorListPosNo > 0) + CompressorListPos = CompressorListDefPos; // NOTE: legacy compatibility behaviour for vehicles without defined heating power source if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) diff --git a/Train.cpp b/Train.cpp index 379b0d2c..ed4867a5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -262,6 +262,9 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::compressorenable, &TTrain::OnCommand_compressorenable }, { user_command::compressordisable, &TTrain::OnCommand_compressordisable }, { user_command::compressortogglelocal, &TTrain::OnCommand_compressortogglelocal }, + { user_command::compressorpresetactivatenext, &TTrain::OnCommand_compressorpresetactivatenext }, + { user_command::compressorpresetactivateprevious, &TTrain::OnCommand_compressorpresetactivateprevious }, + { user_command::compressorpresetactivatedefault, &TTrain::OnCommand_compressorpresetactivatedefault }, { user_command::motorblowerstogglefront, &TTrain::OnCommand_motorblowerstogglefront }, { user_command::motorblowerstogglerear, &TTrain::OnCommand_motorblowerstogglerear }, { user_command::motorblowersdisableall, &TTrain::OnCommand_motorblowersdisableall }, @@ -2962,6 +2965,77 @@ void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const } } +void TTrain::OnCommand_compressorpresetactivatenext(TTrain *Train, command_data const &Command) { + + if (Train->mvOccupied->CompressorListPosNo == 0) { + // lights are controlled by preset selector + return; + } + if (Command.action != GLFW_PRESS) { + // one change per key press + return; + } + + if ((Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo) + || (true == Train->mvOccupied->CompressorListWrap)) { + // active light preset is stored as value in range 1-LigthPosNo + Train->mvOccupied->CompressorListPos = ( + Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ? + Train->mvOccupied->CompressorListPos + 1 : + 1); // wrap mode + + // visual feedback + if (Train->ggCompressorListButton.SubModel != nullptr) { + Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch); + } + } +} + +void TTrain::OnCommand_compressorpresetactivateprevious(TTrain *Train, command_data const &Command) { + + if (Train->mvOccupied->CompressorListPosNo == 0) { + // lights are controlled by preset selector + return; + } + if (Command.action != GLFW_PRESS) { + // one change per key press + return; + } + + if ((Train->mvOccupied->CompressorListPos > 1) + || (true == Train->mvOccupied->CompressorListWrap)) { + // active light preset is stored as value in range 1-LigthPosNo + Train->mvOccupied->CompressorListPos = ( + Train->mvOccupied->CompressorListPos > 1 ? + Train->mvOccupied->CompressorListPos - 1 : + Train->mvOccupied->CompressorListPosNo); // wrap mode + + // visual feedback + if (Train->ggCompressorListButton.SubModel != nullptr) { + Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch); + } + } +} + +void TTrain::OnCommand_compressorpresetactivatedefault(TTrain *Train, command_data const &Command) { + + if (Train->mvOccupied->CompressorListPosNo == 0) { + // lights are controlled by preset selector + return; + } + if (Command.action != GLFW_PRESS) { + // one change per key press + return; + } + + Train->mvOccupied->CompressorListPos = Train->mvOccupied->CompressorListDefPos; + + // visual feedback + if (Train->ggCompressorListButton.SubModel != nullptr) { + Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch); + } +} + void TTrain::OnCommand_motorblowerstogglefront( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_REPEAT ) { return; } @@ -6264,6 +6338,7 @@ bool TTrain::Update( double const Deltatime ) // NBMX dzwignia sprezarki ggCompressorButton.Update(); ggCompressorLocalButton.Update(); + ggCompressorListButton.Update(); //--------- // hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy @@ -7774,6 +7849,7 @@ void TTrain::set_cab_controls( int const Cab ) { mvControlled->CompressorAllowLocal ? 1.f : 0.f ); + ggCompressorListButton.PutValue(mvOccupied->CompressorListPos - 1); // motor overload relay threshold / shunt mode ggMaxCurrentCtrl.PutValue( ( true == mvControlled->ShuntModeAllow ? @@ -8189,6 +8265,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "rearrightend_sw:", ggRearRightEndLightButton }, { "compressor_sw:", ggCompressorButton }, { "compressorlocal_sw:", ggCompressorLocalButton }, + { "compressorlist_sw:", ggCompressorListButton }, { "converter_sw:", ggConverterButton }, { "converterlocal_sw:", ggConverterLocalButton }, { "converteroff_sw:", ggConverterOffButton }, diff --git a/Train.h b/Train.h index fcc2859f..b9dcef61 100644 --- a/Train.h +++ b/Train.h @@ -266,6 +266,9 @@ class TTrain { static void OnCommand_compressorenable( TTrain *Train, command_data const &Command ); static void OnCommand_compressordisable( TTrain *Train, command_data const &Command ); static void OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command ); + static void OnCommand_compressorpresetactivatenext( TTrain *Train, command_data const &Command ); + static void OnCommand_compressorpresetactivateprevious( TTrain *Train, command_data const &Command ); + static void OnCommand_compressorpresetactivatedefault(TTrain *Train, command_data const &Command); static void OnCommand_motorblowerstogglefront( TTrain *Train, command_data const &Command ); static void OnCommand_motorblowersenablefront( TTrain *Train, command_data const &Command ); static void OnCommand_motorblowersdisablefront( TTrain *Train, command_data const &Command ); @@ -447,6 +450,7 @@ public: // reszta może by?publiczna TGauge ggCompressorButton; TGauge ggCompressorLocalButton; // controls only compressor of its own unit (et42-specific) + TGauge ggCompressorListButton; // controls compressors with various settings TGauge ggConverterButton; TGauge ggConverterLocalButton; // controls only converter of its own unit (et42-specific) TGauge ggConverterOffButton; diff --git a/command.cpp b/command.cpp index 9d7bdc6e..6a7b24eb 100644 --- a/command.cpp +++ b/command.cpp @@ -59,6 +59,9 @@ commanddescription_sequence Commands_descriptions = { { "alarmchaintoggle", command_target::vehicle }, { "wheelspinbrakeactivate", command_target::vehicle }, { "sandboxactivate", command_target::vehicle }, + { "autosandboxtoggle", command_target::vehicle }, + { "autosandboxactivate", command_target::vehicle }, + { "autosandboxdeactivate", command_target::vehicle }, { "reverserincrease", command_target::vehicle }, { "reverserdecrease", command_target::vehicle }, { "reverserforwardhigh", command_target::vehicle }, @@ -98,6 +101,9 @@ commanddescription_sequence Commands_descriptions = { { "compressorenable", command_target::vehicle }, { "compressordisable", command_target::vehicle }, { "compressortogglelocal", command_target::vehicle }, + { "compressorpresetactivatenext", command_target::vehicle }, + { "compressorpresetactivateprevious", command_target::vehicle }, + { "compressorpresetactivatedefault", command_target::vehicle }, { "motoroverloadrelaythresholdtoggle", command_target::vehicle }, { "motoroverloadrelaythresholdsetlow", command_target::vehicle }, { "motoroverloadrelaythresholdsethigh", command_target::vehicle }, diff --git a/command.h b/command.h index 89904862..713903f0 100644 --- a/command.h +++ b/command.h @@ -53,6 +53,9 @@ enum class user_command { alarmchaintoggle, wheelspinbrakeactivate, sandboxactivate, + autosandboxtoggle, + autosandboxactivate, + autosandboxdeactivate, reverserincrease, reverserdecrease, reverserforwardhigh, @@ -92,6 +95,9 @@ enum class user_command { compressorenable, compressordisable, compressortogglelocal, + compressorpresetactivatenext, + compressorpresetactivateprevious, + compressorpresetactivatedefault, motoroverloadrelaythresholdtoggle, motoroverloadrelaythresholdsetlow, motoroverloadrelaythresholdsethigh, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index e4db62b5..c4f713f6 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -681,6 +681,9 @@ drivermouse_input::default_bindings() { { "compressorlocal_sw:", { user_command::compressortogglelocal, user_command::none } }, + { "compressorlist_sw:", { + user_command::compressorpresetactivatenext, + user_command::compressorpresetactivateprevious } }, { "converter_sw:", { user_command::convertertoggle, user_command::none } }, From a919443e40fb6d2d296d85d968b9e13ccde4a1fa Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sun, 15 Sep 2019 15:25:09 +0200 Subject: [PATCH 11/15] light state readout for python scripts, reflection map calculation fix --- Train.cpp | 2 ++ renderer.cpp | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Train.cpp b/Train.cpp index ed4867a5..4bf069a5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -468,6 +468,8 @@ dictionary_source *TTrain::GetTrainState() { dict->insert( "converter", mvControlled->ConverterFlag ); dict->insert( "converter_overload", mvControlled->ConvOvldFlag ); dict->insert( "compress", mvControlled->CompressorFlag ); + dict->insert( "lights_front", mvOccupied->iLights[ end::front ] ); + dict->insert( "lights_rear", mvOccupied->iLights[ end::rear ] ); // reverser dict->insert( "direction", mover->ActiveDir ); // throttle diff --git a/renderer.cpp b/renderer.cpp index e1c23d04..d94d2984 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -943,12 +943,7 @@ opengl_renderer::Render_reflections() { if( Global.ReflectionUpdatesPerSecond == 0 ) { return false; } - auto const &time = simulation::Time.data(); - auto const timestamp = - time.wMilliseconds - + time.wSecond * 1000 - + time.wMinute * 1000 * 60 - + time.wHour * 1000 * 60 * 60; + auto const timestamp { static_cast( Timer::GetTime() * 1000 ) }; if( ( timestamp - m_environmentupdatetime < Global.ReflectionUpdatesPerSecond ) && ( glm::length( m_renderpass.camera.position() - m_environmentupdatelocation ) < 1000.0 ) ) { // run update every 5+ mins of simulation time, or at least 1km from the last location From 31c8b69fcabde60ab4d12863efcc33e8419f4725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 14 Sep 2019 16:35:14 +0200 Subject: [PATCH 12/15] More flexible brake handles and universal brake buttons --- McZapkie/MOVER.h | 8 ++++++ McZapkie/Mover.cpp | 53 +++++++++++++++++++++++++++++++---- McZapkie/hamulce.cpp | 64 ++++++++++++++++++++++++++++++++---------- McZapkie/hamulce.h | 18 ++++++++++-- Train.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++ Train.h | 6 ++++ command.cpp | 3 ++ command.h | 3 ++ drivermouseinput.cpp | 9 ++++++ 9 files changed, 208 insertions(+), 22 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 133dc3ab..9856f781 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -959,6 +959,7 @@ public: TBrakePressureTable BrakePressureTable; /*wyszczegolnienie cisnien w rurze*/ TBrakePressure BrakePressureActual; //wartości ważone dla aktualnej pozycji kranu int ASBType = 0; /*0: brak hamulca przeciwposlizgowego, 1: reczny, 2: automat*/ + int UniversalBrakeButtonFlag[3] = { 0, 0, 0 }; /* mozliwe działania przycisków hamulcowych */ int TurboTest = 0; double MaxBrakeForce = 0.0; /*maksymalna sila nacisku hamulca*/ double MaxBrakePress[5]; //pomocniczy, proz, sred, lad, pp @@ -1001,6 +1002,9 @@ public: double EmergencyValveOff = 0.0; bool EmergencyValveOpen = false; double EmergencyValveArea = 0.0; + double LockPipeOn = -1.0; + double LockPipeOff = -1.0; + double HandleUnlock = -3.0; int CompressorListPosNo = 0; int CompressorListDefPos = 1; bool CompressorListWrap = false; @@ -1259,11 +1263,14 @@ public: int ManualBrakePos = 0; /*nastawa hamulca recznego*/ double LocalBrakePosA = 0.0; /*nastawa hamulca pomocniczego*/ double LocalBrakePosAEIM = 0.0; /*pozycja hamulca pomocniczego ep dla asynchronicznych ezt*/ + bool UniversalBrakeButtonActive[3] = { false, false, false }; /* brake button pressed */ /* int BrakeStatus = b_off; //0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R */ bool AlarmChainFlag = false; // manual emergency brake bool RadioStopFlag = false; /*hamowanie nagle*/ + bool LockPipe = false; /*locking brake pipe in emergency state*/ + bool UnlockPipe = false; /*unlockig brake pipe button pressed*/ int BrakeDelayFlag = 0; /*nastawa opoznienia ham. osob/towar/posp/exp 0/1/2/4*/ int BrakeDelays = 0; /*nastawy mozliwe do uzyskania*/ int BrakeOpModeFlag = 0; /*nastawa trybu pracy PS/PN/EP/MED 1/2/4/8*/ @@ -1537,6 +1544,7 @@ public: bool AlarmChainSwitch( bool const State ); bool AntiSlippingBrake(void); bool BrakeReleaser(int state); + bool UniversalBrakeButton(int button, int state); /*uniwersalny przycisk hamulca*/ bool SwitchEPBrake(int state); bool AntiSlippingButton(void); /*! reczny wlacznik urzadzen antyposlizgowych*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 6f1d78c4..b92d6d0f 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3440,6 +3440,37 @@ bool TMoverParameters::BrakeReleaser(int state) return OK; } +// ************************************************************************************************* +// yB: 20160711 +// włączenie / wyłączenie uniwersalnego przycisku hamulcowego +// ************************************************************************************************* +bool TMoverParameters::UniversalBrakeButton(int button, int state) +{ + bool OK = true; //false tylko jeśli nie uda się wysłać, GF 20161124 + UniversalBrakeButtonActive[button] = state > 0; + int flag = 0; + if (Battery) { + for (int i = 0; i < 3; i++) { + flag = flag | (UniversalBrakeButtonActive[i] ? UniversalBrakeButtonFlag[i] : 0); + } + } + + Hamulec->SetUniversalFlag(flag); + Handle->SetUniversalFlag(flag); + LocHandle->SetUniversalFlag(flag); + UnlockPipe = (flag & TUniversalBrake::ub_UnlockPipe) > 0; + + //if the releaser can be activated by switch + if ( TestFlag ( UniversalBrakeButtonFlag[0] & UniversalBrakeButtonFlag[1] & UniversalBrakeButtonFlag[2], + TUniversalBrake::ub_Release ) ) + { + Hamulec->Releaser( int ( TestFlag ( flag, TUniversalBrake::ub_Release ) )); + if (CabNo != 0) // rekurencyjne wysłanie do następnego + OK = SendCtrlToNext("BrakeReleaser", state, CabNo); + } + return OK; +} + // ************************************************************************************************* // Q: 20160711 // włączenie / wyłączenie hamulca elektro-pneumatycznego @@ -3898,11 +3929,17 @@ void TMoverParameters::UpdatePipePressure(double dt) dpLocalValve = LocHandle->GetPF(std::max(LocalBrakePosA, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0); else dpLocalValve = LocHandle->GetPF(LocalBrakePosAEIM, Hamulec->GetBCP(), ScndPipePress, dt, 0); - if( ( BrakeHandle == TBrakeHandle::FV4a ) - && ( ( PipePress < 2.75 ) - && ( ( Hamulec->GetStatus() & b_rls ) == 0 ) ) - && ( BrakeSubsystem == TBrakeSubSystem::ss_LSt ) - && ( TrainType != dt_EZT ) ) { + + LockPipe = PipePress < (LockPipe ? LockPipeOff : LockPipeOn); + bool lock_new = (LockPipe && !UnlockPipe && (BrakeCtrlPosR > HandleUnlock)); //new simple codition based on .fiz + bool lock_old = ((BrakeHandle == TBrakeHandle::FV4a) //old complex condition based on assumptions + && ((PipePress < 2.75) + && ((Hamulec->GetStatus() & b_rls) == 0)) + && (BrakeSubsystem == TBrakeSubSystem::ss_LSt) + && (TrainType != dt_EZT) + && (!UnlockPipe)); + + if( ( lock_old ) || ( lock_new ) ) { temp = PipePress + 0.00001; } else { @@ -8964,6 +9001,12 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { extract_value( EmergencyValveOff, "MinEVP", line, "" ); extract_value( EmergencyValveOn, "MaxEVP", line, "" ); extract_value( EmergencyValveArea, "EVArea", line, "" ); + extract_value( UniversalBrakeButtonFlag[0], "UBB1", line, ""); + extract_value( UniversalBrakeButtonFlag[1], "UBB2", line, ""); + extract_value( UniversalBrakeButtonFlag[2], "UBB3", line, ""); + extract_value( LockPipeOn, "LPOn", line, "-1"); + extract_value( LockPipeOff, "LPOff", line, "-1"); + extract_value( HandleUnlock, "HandlePipeUnlockPos", line, "-3"); { std::map compressorpowers{ { "Main", 0 }, diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 59ffb5bb..a707d174 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -1300,7 +1300,9 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel ) SoundFlag |= sf_CylU; } // equivalent of checkreleaser() in the base class? - if( ( BrakeStatus & b_rls ) == b_rls ) { + bool is_releasing = ( ( BrakeStatus & b_rls) + || ( UniversalFlag & TUniversalBrake::ub_Release ) ); + if ( is_releasing ) { if( CVP < 0.0 ) { BrakeStatus &= ~b_rls; } @@ -1373,9 +1375,12 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel ) temp = 1 - RapidTemp; if (EDFlag > 0.2) temp = 10000; - + double tempasb = 0; + if ( ( (UniversalFlag & TUniversalBrake::ub_AntiSlipBrake) > 0) + || ( (BrakeStatus & b_asb_unbrake) == b_asb_unbrake ) ) + tempasb = ASBP; // powtarzacz — podwojny zawor zwrotny - temp = Max0R(((CVP - BCP) * BVM + ASBP * int((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) / temp, LBP); + temp = Max0R( ( (CVP - BCP) * BVM + tempasb ) / temp, LBP ); // luzowanie CH if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28)) // dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt @@ -1556,6 +1561,10 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel ) // powtarzacz — podwojny zawor zwrotny temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP); + + if ( ( UniversalFlag & TUniversalBrake::ub_AntiSlipBrake ) > 0 ) + temp = std::max(temp, ASBP); + double speed = 1; if ((ASBP < 0.1) && ((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) { @@ -2292,6 +2301,11 @@ void TDriverHandle::OvrldButton(bool Active) { ManualOvrldActive = Active; } + +void TDriverHandle::SetUniversalFlag(int flag) +{ + UniversalFlag = flag; +} //---FV4a--- double TFV4a::GetPF(double i_bcp, double PP, double HP, double dt, double ep) @@ -2576,7 +2590,7 @@ double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double e i_bcp = Max0R(Min0R(i_bcp, 9.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)) + if ((TP > 0)&&(CP > 4.9)) { DP = 0.045; if (EQ(i_bcp, 0)) @@ -2591,8 +2605,13 @@ double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double e LimPP = Min0R(LPP_RP(i_bcp) + TP * 0.08 + RedAdj, HP); // pozycja + czasowy lub zasilanie ActFlowSpeed = 4; - if ((EQ(i_bcp, -1))) - pom = Min0R(HP, 5.4 + RedAdj); + double uop = UnbrakeOverPressure; //unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed + if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + uop = 0; + + if ( ( EQ( i_bcp, -1 ) ) && ( uop > 0 ) ) + pom = Min0R(HP, 5.4 + RedAdj + uop); else pom = Min0R(CP, HP); @@ -2602,9 +2621,9 @@ double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double e CP = CP + 13 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy LimPP = pom; // cp - if (EQ(i_bcp, -1)) - dpPipe = HP; - else + //if (EQ(i_bcp, -1)) + // dpPipe = HP; + // else dpPipe = Min0R(HP, LimPP); if (dpPipe > PP) @@ -2612,7 +2631,8 @@ double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double e else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if (EQ(i_bcp, -1)) + if ( ( EQ(i_bcp, -1) && ( AutoOvrld ) ) + ||(i_bcp<0.5 && (UniversalFlag & TUniversalBrake::ub_Overload))) { if ((TP < 5)) TP = TP + dt; // 5/10 @@ -2691,6 +2711,15 @@ double TMHZ_EN57::LPP_RP(double pos) // cisnienie z zaokraglonej pozycji; return 5.0; } +void TMHZ_EN57::SetParams(bool AO, bool MO, double OverP, double) +{ + AutoOvrld = AO; + ManualOvrld = MO; + UnbrakeOverPressure = std::max(0.0, OverP); + Fala = (OverP > 0.01); + +} + bool TMHZ_EN57::EQ(double pos, double i_pos) { return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); @@ -2716,7 +2745,7 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) i_bcp = Max0R(Min0R(i_bcp, 2.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)) + if ((TP > 0)&&(CP>4.9)) { DP = 0.004; TP = TP - DP * dt; @@ -2749,7 +2778,7 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ((EQ(i_bcp, -1)&&(AutoOvrld))||(ManualOvrld && ManualOvrldActive)) + if ((EQ(i_bcp, -1)&&(AutoOvrld))||(i_bcp<0.5 && ManualOvrldActive )) { if ((TP < 1)) TP = TP + 0.03 * dt; @@ -2836,7 +2865,7 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) i_bcp = Max0R(Min0R(i_bcp, 3.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)) + if ((TP > 0)&&(CP>4.9)) { DP = 0.004; TP = TP - DP * dt; @@ -2864,9 +2893,14 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) dpPipe = Min0R(HP, CP + TP + RedAdj); + double uop = UnbrakeOverPressure; //unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed + if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + uop = 0; + if (Fala && EQ(i_bcp, -1)) { - dpPipe = 5.0 + TP + RedAdj + UnbrakeOverPressure; + dpPipe = 5.0 + TP + RedAdj + uop; ActFlowSpeed = 12; } @@ -2875,7 +2909,7 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ((EQ(i_bcp, -1) && (AutoOvrld)) || (ManualOvrld && ManualOvrldActive)) + if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp<0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) { if ((TP < 1)) TP = TP + 0.03 * dt; diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index 814718da..15263b88 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -133,6 +133,16 @@ static double const BPT_394[7][2] = { {13 , 10.0} , {5 , 5.0} , {0 , -1} , {5 , static int const i_bcpno = 6; // static double const pi = 3.141592653589793; //definicja w mctools +enum TUniversalBrake // możliwe działania uniwersalnego przycisku hamulca +{ // kolejne flagi + ub_Release = 0x01, // odluźniacz - ZR + ub_UnlockPipe = 0x02, // odblok PG / mostkowanie hamulca bezpieczeństwa - POJAZD + ub_HighPressure = 0x04, // impuls wysokiego ciśnienia - ZM + ub_Overload = 0x08, // przycisk asymilacji / kontrolowanego przeładowania - ZM + ub_AntiSlipBrake = 0x10, // przycisk przyhamowania przeciwposlizgowego - ZR + ub_Ostatni = 0x80000000 // ostatnia flaga bitowa +}; + //klasa obejmujaca pojedyncze zbiorniki class TReservoir { @@ -183,6 +193,7 @@ class TBrake { double SizeBC = 0.0; //rozmiar^2 CH (w stosunku do 14") bool DCV = false; //podwojny zawor zwrotny double ASBP = 0.0; //cisnienie hamulca pp + int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych int BrakeStatus{ b_off }; //flaga stanu int SoundFlag = 0; @@ -220,6 +231,7 @@ class TBrake { int GetBrakeStatus() const { return BrakeStatus; } void SetBrakeStatus( int const Status ) { BrakeStatus = Status; } virtual void SetED( double const EDstate ) {}; //stan hamulca ED do luzowania + virtual void SetUniversalFlag(int flag) { UniversalFlag = flag; } //przycisk uniwersalny }; class TWest : public TBrake { @@ -520,6 +532,7 @@ class TDriverHandle { bool AutoOvrld = false; //czy jest asymilacja automatyczna na pozycji -1 bool ManualOvrld = false; //czy jest asymilacja reczna przyciskiem bool ManualOvrldActive = false; //czy jest wcisniety przycisk asymilacji + int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych public: bool Time = false; bool TimeEP = false; @@ -534,7 +547,7 @@ class TDriverHandle { virtual double GetEP(double pos); //pobranie sily hamulca ep virtual void SetParams(bool AO, bool MO, double, double) {}; //ustawianie jakichs parametrów dla zaworu virtual void OvrldButton(bool Active); //przycisk recznego przeladowania/asymilacji - + virtual void SetUniversalFlag(int flag); //przycisk uniwersalny inline TDriverHandle() { memset( Sounds, 0, sizeof( Sounds ) ); } }; @@ -589,6 +602,7 @@ class TMHZ_EN57 : public TDriverHandle { double RP = 0.0; //zbiornik redukcyjny double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) bool Fala = false; + double UnbrakeOverPressure = 0.0; static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; double LPP_RP(double pos); @@ -602,7 +616,7 @@ class TMHZ_EN57 : public TDriverHandle { double GetPos(int i)/*override*/; double GetCP()/*override*/; double GetEP(double pos); - + void SetParams(bool AO, bool MO, double OverP, double); inline TMHZ_EN57(void) : TDriverHandle() {} diff --git a/Train.cpp b/Train.cpp index 4bf069a5..77ab410e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -180,6 +180,9 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::independentbrakedecreasefast, &TTrain::OnCommand_independentbrakedecreasefast }, { user_command::independentbrakeset, &TTrain::OnCommand_independentbrakeset }, { user_command::independentbrakebailoff, &TTrain::OnCommand_independentbrakebailoff }, + { user_command::universalbrakebutton1, &TTrain::OnCommand_universalbrakebutton1 }, + { user_command::universalbrakebutton2, &TTrain::OnCommand_universalbrakebutton2 }, + { user_command::universalbrakebutton3, &TTrain::OnCommand_universalbrakebutton3 }, { user_command::trainbrakeincrease, &TTrain::OnCommand_trainbrakeincrease }, { user_command::trainbrakedecrease, &TTrain::OnCommand_trainbrakedecrease }, { user_command::trainbrakeset, &TTrain::OnCommand_trainbrakeset }, @@ -1166,6 +1169,60 @@ void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data cons } } +void TTrain::OnCommand_universalbrakebutton1(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // press or hold + // visual feedback + Train->ggUniveralBrakeButton1.UpdateValue(1.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(0,1); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggUniveralBrakeButton1.UpdateValue(0.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(0,0); + } +} + +void TTrain::OnCommand_universalbrakebutton2(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // press or hold + // visual feedback + Train->ggUniveralBrakeButton2.UpdateValue(1.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(1, 1); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggUniveralBrakeButton2.UpdateValue(0.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(1, 0); + } +} + +void TTrain::OnCommand_universalbrakebutton3(TTrain *Train, command_data const &Command) { + + if (Command.action == GLFW_PRESS) { + // press or hold + // visual feedback + Train->ggUniveralBrakeButton3.UpdateValue(1.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(2, 1); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggUniveralBrakeButton3.UpdateValue(0.0, Train->dsbSwitch); + + Train->mvOccupied->UniversalBrakeButton(2, 0); + } +} + void TTrain::OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Command ) { if( Command.action != GLFW_RELEASE ) { @@ -6374,6 +6431,9 @@ bool TTrain::Update( double const Deltatime ) ggMainButton.Update(); ggSecurityResetButton.Update(); ggReleaserButton.Update(); + ggUniveralBrakeButton1.Update(); + ggUniveralBrakeButton2.Update(); + ggUniveralBrakeButton3.Update(); ggAntiSlipButton.Update(); ggSandButton.Update(); ggFuseButton.Update(); @@ -7568,6 +7628,9 @@ void TTrain::clear_cab_controls() ggMainOnButton.Clear(); ggSecurityResetButton.Clear(); ggReleaserButton.Clear(); + ggUniveralBrakeButton1.Clear(); + ggUniveralBrakeButton2.Clear(); + ggUniveralBrakeButton3.Clear(); ggSandButton.Clear(); ggAntiSlipButton.Clear(); ggHornButton.Clear(); @@ -8230,6 +8293,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "main_on_bt:", ggMainOnButton }, { "security_reset_bt:", ggSecurityResetButton }, { "releaser_bt:", ggReleaserButton }, + { "universalbrake1_bt:", ggUniveralBrakeButton1 }, + { "universalbrake2_bt:", ggUniveralBrakeButton2 }, + { "universalbrake3_bt:", ggUniveralBrakeButton3 }, { "sand_bt:", ggSandButton }, { "autosandallow_sw:", ggAutoSandAllow }, { "antislip_bt:", ggAntiSlipButton }, diff --git a/Train.h b/Train.h index b9dcef61..ab41b6d7 100644 --- a/Train.h +++ b/Train.h @@ -181,6 +181,9 @@ class TTrain { static void OnCommand_independentbrakedecreasefast( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakeset( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakebailoff( TTrain *Train, command_data const &Command ); + static void OnCommand_universalbrakebutton1(TTrain *Train, command_data const &Command); + static void OnCommand_universalbrakebutton2(TTrain *Train, command_data const &Command); + static void OnCommand_universalbrakebutton3(TTrain *Train, command_data const &Command); static void OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Command ); static void OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Command ); static void OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ); @@ -418,6 +421,9 @@ public: // reszta może by?publiczna TGauge ggMainButton; // EZT TGauge ggSecurityResetButton; TGauge ggReleaserButton; + TGauge ggUniveralBrakeButton1; + TGauge ggUniveralBrakeButton2; + TGauge ggUniveralBrakeButton3; TGauge ggSandButton; // guzik piasecznicy TGauge ggAutoSandAllow; // przełącznik piasecznicy TGauge ggAntiSlipButton; diff --git a/command.cpp b/command.cpp index 6a7b24eb..f1e1dbaa 100644 --- a/command.cpp +++ b/command.cpp @@ -40,6 +40,9 @@ commanddescription_sequence Commands_descriptions = { { "independentbrakedecreasefast", command_target::vehicle }, { "independentbrakeset", command_target::vehicle }, { "independentbrakebailoff", command_target::vehicle }, + { "universalbrakebutton1", command_target::vehicle }, + { "universalbrakebutton2", command_target::vehicle }, + { "universalbrakebutton3", command_target::vehicle }, { "trainbrakeincrease", command_target::vehicle }, { "trainbrakedecrease", command_target::vehicle }, { "trainbrakeset", command_target::vehicle }, diff --git a/command.h b/command.h index 713903f0..064d49cf 100644 --- a/command.h +++ b/command.h @@ -34,6 +34,9 @@ enum class user_command { independentbrakedecreasefast, independentbrakeset, independentbrakebailoff, + universalbrakebutton1, + universalbrakebutton2, + universalbrakebutton3, trainbrakeincrease, trainbrakedecrease, trainbrakeset, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index c4f713f6..99d9b06f 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -570,6 +570,15 @@ drivermouse_input::default_bindings() { { "releaser_bt:", { user_command::independentbrakebailoff, user_command::none } }, + { "universalbrake1_bt:",{ + user_command::universalbrakebutton1, + user_command::none } }, + { "universalbrake2_bt:",{ + user_command::universalbrakebutton2, + user_command::none } }, + { "universalbrake3_bt:",{ + user_command::universalbrakebutton3, + user_command::none } }, { "sand_bt:", { user_command::sandboxactivate, user_command::none } }, From c7094929657b2259cf7c847ea054dbd07a5e0d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 14 Sep 2019 21:30:51 +0200 Subject: [PATCH 13/15] Buttons for spring brake --- Train.cpp | 33 +++++++++++++++++++++++++++++++++ Train.h | 3 +++ drivermouseinput.cpp | 9 +++++++++ 3 files changed, 45 insertions(+) diff --git a/Train.cpp b/Train.cpp index 77ab410e..7e98b6bf 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4415,12 +4415,27 @@ void TTrain::OnCommand_springbraketoggle(TTrain *Train, command_data const &Comm OnCommand_springbrakedisable(Train, Command); } } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpringBrakeOffButton.UpdateValue(0.0, Train->dsbSwitch); + Train->ggSpringBrakeOnButton.UpdateValue(0.0, Train->dsbSwitch); + } }; void TTrain::OnCommand_springbrakeenable(TTrain *Train, command_data const &Command) { if (Command.action == GLFW_PRESS) { // only reacting to press, so the switch doesn't flip back and forth if key is held down Train->mvOccupied->SpringBrakeActivate(true); + // visual feedback + Train->ggSpringBrakeOnButton.UpdateValue(1.0, Train->dsbSwitch); + Train->ggSpringBrakeToggleButton.UpdateValue(1.0, Train->dsbSwitch); + Train->ggSpringBrakeOffButton.UpdateValue(0.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpringBrakeOnButton.UpdateValue(0.0, Train->dsbSwitch); } }; @@ -4428,6 +4443,15 @@ void TTrain::OnCommand_springbrakedisable(TTrain *Train, command_data const &Com if (Command.action == GLFW_PRESS) { // only reacting to press, so the switch doesn't flip back and forth if key is held down Train->mvOccupied->SpringBrakeActivate(false); + // visual feedback + Train->ggSpringBrakeOffButton.UpdateValue(1.0, Train->dsbSwitch); + Train->ggSpringBrakeToggleButton.UpdateValue(0.0, Train->dsbSwitch); + Train->ggSpringBrakeOnButton.UpdateValue(0.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpringBrakeOffButton.UpdateValue(0.0, Train->dsbSwitch); } }; void TTrain::OnCommand_springbrakeshutofftoggle(TTrain *Train, command_data const &Command) { @@ -6431,6 +6455,9 @@ bool TTrain::Update( double const Deltatime ) ggMainButton.Update(); ggSecurityResetButton.Update(); ggReleaserButton.Update(); + ggSpringBrakeToggleButton.Update(); + ggSpringBrakeOnButton.Update(); + ggSpringBrakeOffButton.Update(); ggUniveralBrakeButton1.Update(); ggUniveralBrakeButton2.Update(); ggUniveralBrakeButton3.Update(); @@ -7628,6 +7655,9 @@ void TTrain::clear_cab_controls() ggMainOnButton.Clear(); ggSecurityResetButton.Clear(); ggReleaserButton.Clear(); + ggSpringBrakeToggleButton.Clear(); + ggSpringBrakeOnButton.Clear(); + ggSpringBrakeOffButton.Clear(); ggUniveralBrakeButton1.Clear(); ggUniveralBrakeButton2.Clear(); ggUniveralBrakeButton3.Clear(); @@ -8293,6 +8323,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "main_on_bt:", ggMainOnButton }, { "security_reset_bt:", ggSecurityResetButton }, { "releaser_bt:", ggReleaserButton }, + { "springbraketoggle_bt:", ggSpringBrakeToggleButton }, + { "springbrakeon_bt:", ggSpringBrakeOnButton }, + { "springbrakeoff_bt:", ggSpringBrakeOffButton }, { "universalbrake1_bt:", ggUniveralBrakeButton1 }, { "universalbrake2_bt:", ggUniveralBrakeButton2 }, { "universalbrake3_bt:", ggUniveralBrakeButton3 }, diff --git a/Train.h b/Train.h index ab41b6d7..46439150 100644 --- a/Train.h +++ b/Train.h @@ -421,6 +421,9 @@ public: // reszta może by?publiczna TGauge ggMainButton; // EZT TGauge ggSecurityResetButton; TGauge ggReleaserButton; + TGauge ggSpringBrakeToggleButton; + TGauge ggSpringBrakeOnButton; + TGauge ggSpringBrakeOffButton; TGauge ggUniveralBrakeButton1; TGauge ggUniveralBrakeButton2; TGauge ggUniveralBrakeButton3; diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index 99d9b06f..39b500a3 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -570,6 +570,15 @@ drivermouse_input::default_bindings() { { "releaser_bt:", { user_command::independentbrakebailoff, user_command::none } }, + { "springbraketoggle_bt:",{ + user_command::springbraketoggle, + user_command::none } }, + { "springbrakeon_bt:",{ + user_command::springbrakeenable, + user_command::none } }, + { "springbrakeoff_bt:",{ + user_command::springbrakedisable, + user_command::none } }, { "universalbrake1_bt:",{ user_command::universalbrakebutton1, user_command::none } }, From dbfda7c1e57a57e870370f79fcc11f695150de28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 14 Sep 2019 23:26:37 +0200 Subject: [PATCH 14/15] Modified overpressure for MHZ_K5P --- McZapkie/hamulce.cpp | 14 +++++++++++--- McZapkie/hamulce.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index a707d174..aff55a1e 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -2771,14 +2771,19 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else CP = CP + 9 * Min0R(abs(LimCP - CP), 0.05) * PR(CP, LimCP) * dt; // zbiornik sterujacy - dpPipe = Min0R(HP, CP + TP + RedAdj); + double uop = UnbrakeOverPressure; //unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed + if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + uop = 0; + + dpPipe = Min0R(HP, CP + TP + RedAdj); if (dpPipe > PP) dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4); else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ((EQ(i_bcp, -1)&&(AutoOvrld))||(i_bcp<0.5 && ManualOvrldActive )) + if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp<0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) { if ((TP < 1)) TP = TP + 0.03 * dt; @@ -2834,10 +2839,13 @@ double TMHZ_K5P::GetCP() return CP; } -void TMHZ_K5P::SetParams(bool AO, bool MO, double, double) +void TMHZ_K5P::SetParams(bool AO, bool MO, double OverP, double) { AutoOvrld = AO; ManualOvrld = MO; + UnbrakeOverPressure = std::max(0.0, OverP); + Fala = (OverP > 0.01); + } bool TMHZ_K5P::EQ(double pos, double i_pos) diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index 15263b88..12f43950 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -630,6 +630,7 @@ private: double RP = 0.0; //zbiornik redukcyjny double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) bool Fala = false; //czy jest napelnianie uderzeniowe + double UnbrakeOverPressure = 0.0; static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; bool EQ(double pos, double i_pos); From b2b49f933ccfd2db6b4b81397143c7def558535b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 15 Sep 2019 12:21:30 +0200 Subject: [PATCH 15/15] AI lesson for UniversalBrakeButtons --- Driver.cpp | 22 ++++++++++++++++++++++ Driver.h | 1 + 2 files changed, 23 insertions(+) diff --git a/Driver.cpp b/Driver.cpp index c784d753..42a3504d 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3650,6 +3650,18 @@ void TController::SetTimeControllers() } } } + //6. UniversalBrakeButtons + //6.1. Checking flags for Over pressure + if (std::abs(BrakeCtrlPosition - gbh_FS)<0.5) { + UniversalBrakeButtons |= (TUniversalBrake::ub_HighPressure | TUniversalBrake::ub_Overload); + } + else { + UniversalBrakeButtons &= ~(TUniversalBrake::ub_HighPressure | TUniversalBrake::ub_Overload); + } + //6.2. Setting buttons + for (int i = 0; i < 3; i++) { + mvOccupied->UniversalBrakeButton(i, (UniversalBrakeButtons & mvOccupied->UniversalBrakeButtonFlag[i])); + } }; void TController::CheckTimeControllers() @@ -5888,6 +5900,8 @@ TController::UpdateSituation(double dt) { // napełnianie uderzeniowe if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) || ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P ) + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K5P) + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P) || ( mvOccupied->BrakeHandle == TBrakeHandle::M394 ) ) { if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == -2 ) { @@ -5948,6 +5962,14 @@ TController::UpdateSituation(double dt) { } } } + // unlocking main pipe + if ((AccDesired > -0.03) + && (true == mvOccupied->LockPipe)) { + UniversalBrakeButtons |= TUniversalBrake::ub_UnlockPipe; + } + else if (false == mvOccupied->LockPipe) { + UniversalBrakeButtons &= ~TUniversalBrake::ub_UnlockPipe; + } #if LOGVELOCITY WriteLog("Dist=" + FloatToStrF(ActualProximityDist, ffFixed, 7, 1) + ", VelDesired=" + FloatToStrF(VelDesired, ffFixed, 7, 1) + diff --git a/Driver.h b/Driver.h index 062691af..852b3282 100644 --- a/Driver.h +++ b/Driver.h @@ -263,6 +263,7 @@ public: int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller + int UniversalBrakeButtons = 0.0; // flag of which universal buttons need to be pressed int DizelPercentage = 0; // oczekiwane procenty jazdy/hamowania szynobusem int DizelPercentage_Speed = 0; // oczekiwane procenty jazdy/hamowania szynobusem w związku z osiąganiem VelDesired private: