From edb98f41e792aff6af6f9f890c93c7644c1d739a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 23 Mar 2019 22:18:17 +0100 Subject: [PATCH 1/7] AI uses SpeedCtrl in TRAXX properly --- Driver.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index cb4397bb..d96a7a45 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3372,7 +3372,7 @@ void TController::SpeedCntrl(double DesiredSpeed) mvControlling->IncScndCtrl(1); mvControlling->RunCommand("SpeedCntrl", DesiredSpeed, mvControlling->CabNo); } - else if (mvControlling->ScndCtrlPosNo > 1) + else if ((mvControlling->ScndCtrlPosNo > 1) && (!mvOccupied->SpeedCtrlTypeTime)) { int DesiredPos = 1 + mvControlling->ScndCtrlPosNo * ((DesiredSpeed - 1.0) / mvControlling->Vmax); while( ( mvControlling->ScndCtrlPos > DesiredPos ) && ( true == mvControlling->DecScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop @@ -3414,6 +3414,22 @@ void TController::SetTimeControllers() if (mvOccupied->LocalBrakePosA > 0.95) mvOccupied->MainCtrlPos = 1; } } + //4. Check Speed Control System + if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo > 1 && mvOccupied->SpeedCtrlTypeTime) + { + double SpeedCntrlVel = + (ActualProximityDist > std::max(50.0, fMaxProximityDist)) ? + VelDesired : + min_speed(VelDesired, VelNext); + SpeedCntrlVel = 10 * std::floor(SpeedCntrlVel*0.1); + if (mvOccupied->ScndCtrlPosNo == 4) + { + if (mvOccupied->NewSpeed + 0.1 < SpeedCntrlVel) + mvOccupied->ScndCtrlPos = 3; + if (mvOccupied->NewSpeed - 0.1 > SpeedCntrlVel) + mvOccupied->ScndCtrlPos = 1; + } + } }; void TController::CheckTimeControllers() @@ -3446,6 +3462,14 @@ void TController::CheckTimeControllers() if (mvOccupied->eimic < 0) mvOccupied->MainCtrlPos = 2; } } + //4. Check Speed Control System + if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo>1 && mvOccupied->SpeedCtrlTypeTime) + { + if (mvOccupied->ScndCtrlPosNo == 4) + { + mvOccupied->ScndCtrlPos = 2; + } + } }; // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT From 916a611c8de005076ebff9f1040d7d89109bad77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 23 Mar 2019 08:52:47 +0100 Subject: [PATCH 2/7] Fix for AI decoupling old Knorr/West locomotives --- Driver.cpp | 1 + McZapkie/hamulce.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Driver.cpp b/Driver.cpp index 39c1d15b..cb4397bb 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -5002,6 +5002,7 @@ TController::UpdateSituation(double dt) { TableClear(); // skanowanie od nowa iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy + mvOccupied->BrakeReleaser(0); // wyłączyć luzowanie } } diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 3544b002..6d258f8e 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -481,6 +481,12 @@ double TWest::GetPF( double const PP, double const dt, double const Vel ) dv = 0; BrakeCyl->Flow(-dv); + if ((BrakeStatus & b_rls) == b_rls) //odluzniacz + dv = PF(0, CVP, 0.1 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); + // hamulec EP temp = BVP * int(EPS > 0); dv = PF(temp, LBP, 0.0015) * dt * EPS * EPS * int(LBP * EPS < MaxBP * LoadC); From b9117c6fa8c7c086d993415ac8e390b4b1648aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 23 Mar 2019 11:51:24 +0100 Subject: [PATCH 3/7] Added SpeedCtrl for TRAXX --- McZapkie/MOVER.h | 1 + McZapkie/Mover.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- Train.cpp | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 77ed3e3f..f02bd64d 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1306,6 +1306,7 @@ public: double eimic = 0; /*aktualna pozycja zintegrowanego sterowania jazda i hamowaniem*/ double eimic_real = 0; /*faktycznie uzywana pozycja zintegrowanego sterowania jazda i hamowaniem*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ + bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ double eimv[21]; static std::vector const eimv_labels; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 2dfc3537..c3f0c534 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -5011,7 +5011,44 @@ double TMoverParameters::TractionForce( double dt ) { { if( true == Mains ) { //tempomat - if (ScndCtrlPosNo > 1) + if (ScndCtrlPosNo == 4 && SpeedCtrlTypeTime) + { + switch (ScndCtrlPos) { + case 0: + NewSpeed = 0; + ScndCtrlActualPos = 0; + SpeedCtrlTimer = 10; + break; + case 1: + if (SpeedCtrlTimer > SpeedCtrlDelay) { + SpeedCtrlTimer = 0; + NewSpeed -= 10; + if (NewSpeed < 0) NewSpeed = 0; + } + else + SpeedCtrlTimer += dt; + break; + case 2: + SpeedCtrlTimer = 10; + ScndCtrlActualPos = NewSpeed; + break; + case 3: + if (SpeedCtrlTimer > SpeedCtrlDelay) { + SpeedCtrlTimer = 0; + NewSpeed += 10; + if (NewSpeed > Vmax) NewSpeed = Vmax; + } + else + SpeedCtrlTimer += dt; + break; + case 4: + NewSpeed = Vmax; + ScndCtrlActualPos = Vmax; + SpeedCtrlTimer = 10; + break; + } + } + else if (ScndCtrlPosNo > 1) { if (ScndCtrlPos != NewSpeed) { @@ -8604,6 +8641,10 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { // speed control extract_value( SpeedCtrlDelay, "SpeedCtrlDelay", line, "" ); + SpeedCtrlTypeTime = + (extract_value("SpeedCtrlType", line) == "Time") ? + true : + false; // converter { diff --git a/Train.cpp b/Train.cpp index 41c0416a..6c2da0f5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -453,6 +453,7 @@ dictionary_source *TTrain::GetTrainState() { dict->insert( "main_ctrl_actual_pos", mover->MainCtrlActualPos ); dict->insert( "scndctrl_pos", mover->ScndCtrlPos ); dict->insert( "scnd_ctrl_actual_pos", mover->ScndCtrlActualPos ); + dict->insert( "new_speed", mover->NewSpeed); // brakes dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) ); bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 ); From 9a94693f969ce4337560233603ad5cd31500e1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 23 Mar 2019 22:18:17 +0100 Subject: [PATCH 4/7] AI uses SpeedCtrl in TRAXX properly --- Driver.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index cb4397bb..d96a7a45 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3372,7 +3372,7 @@ void TController::SpeedCntrl(double DesiredSpeed) mvControlling->IncScndCtrl(1); mvControlling->RunCommand("SpeedCntrl", DesiredSpeed, mvControlling->CabNo); } - else if (mvControlling->ScndCtrlPosNo > 1) + else if ((mvControlling->ScndCtrlPosNo > 1) && (!mvOccupied->SpeedCtrlTypeTime)) { int DesiredPos = 1 + mvControlling->ScndCtrlPosNo * ((DesiredSpeed - 1.0) / mvControlling->Vmax); while( ( mvControlling->ScndCtrlPos > DesiredPos ) && ( true == mvControlling->DecScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop @@ -3414,6 +3414,22 @@ void TController::SetTimeControllers() if (mvOccupied->LocalBrakePosA > 0.95) mvOccupied->MainCtrlPos = 1; } } + //4. Check Speed Control System + if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo > 1 && mvOccupied->SpeedCtrlTypeTime) + { + double SpeedCntrlVel = + (ActualProximityDist > std::max(50.0, fMaxProximityDist)) ? + VelDesired : + min_speed(VelDesired, VelNext); + SpeedCntrlVel = 10 * std::floor(SpeedCntrlVel*0.1); + if (mvOccupied->ScndCtrlPosNo == 4) + { + if (mvOccupied->NewSpeed + 0.1 < SpeedCntrlVel) + mvOccupied->ScndCtrlPos = 3; + if (mvOccupied->NewSpeed - 0.1 > SpeedCntrlVel) + mvOccupied->ScndCtrlPos = 1; + } + } }; void TController::CheckTimeControllers() @@ -3446,6 +3462,14 @@ void TController::CheckTimeControllers() if (mvOccupied->eimic < 0) mvOccupied->MainCtrlPos = 2; } } + //4. Check Speed Control System + if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo>1 && mvOccupied->SpeedCtrlTypeTime) + { + if (mvOccupied->ScndCtrlPosNo == 4) + { + mvOccupied->ScndCtrlPos = 2; + } + } }; // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT From 9bca1797526e7c34a33a66cc1c36820ce171f375 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 27 Mar 2019 20:42:31 +0100 Subject: [PATCH 5/7] build 190327. tempomat status cab indicator, nullptr crash fixes, ai logic tweaks. --- Driver.cpp | 188 +++++++++++++++++++++++++++------------------ DynObj.cpp | 4 + McZapkie/Mover.cpp | 9 ++- Train.cpp | 4 + Train.h | 1 + version.h | 2 +- 6 files changed, 132 insertions(+), 76 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index d96a7a45..865089a5 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1824,8 +1824,7 @@ void TController::Activation() } } // Ra: to przełączanie poniżej jest tu bez sensu - mvOccupied->ActiveCab = - iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?) + mvOccupied->ActiveCab = iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?) // mvOccupied->CabNo=iDirection; // mvOccupied->ActiveDir=0; //żeby sam ustawił kierunek mvOccupied->CabActivisation(); // uruchomienie kabin w członach @@ -1965,6 +1964,7 @@ void TController::AutoRewident() && ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) { fAccThreshold += 0.10; } + fNominalAccThreshold = fAccThreshold; } if( OrderCurrentGet() & ( Obey_train | Bank ) ) { @@ -2356,8 +2356,10 @@ void TController::SetVelocity(double NewVel, double NewVelNext, TStopReason r) double TController::BrakeAccFactor() const { double Factor = 1.0; - if( ( ActualProximityDist > fMinProximityDist ) - || ( mvOccupied->Vel > VelDesired + fVelPlus ) ) { + + if( ( fAccThreshold != 0.0 ) + && ( ( ActualProximityDist > fMinProximityDist ) + || ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) { Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold ); } return Factor; @@ -2522,7 +2524,15 @@ bool TController::PrepareEngine() // enable train brake if it's off if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) { mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); - BrakeLevelSet(gbh_RP); // GBH + } + // sync virtual brake state with the 'real' one + std::unordered_map const brakepositions { + { mvOccupied->Handle->GetPos( bh_RP ), gbh_RP }, + { mvOccupied->Handle->GetPos( bh_NP ), gbh_NP }, + { mvOccupied->Handle->GetPos( bh_FS ), gbh_FS } }; + auto const lookup { brakepositions.find( static_cast( mvOccupied->fBrakeCtrlPos ) ) }; + if( lookup != brakepositions.end() ) { + BrakeLevelSet( lookup->second ); // GBH } } } @@ -2861,7 +2871,7 @@ bool TController::DecBrake() // mvOccupied->BrakeLevelAdd(-1.0); /* if (mvOccupied->BrakeCtrlPosR < 0.74) GBH */ if (BrakeCtrlPosition < 0.74) - /*mvOccupied->*/BrakeLevelSet(0.0); + /*mvOccupied->*/BrakeLevelSet(gbh_RP); } } if( !OK ) { @@ -3067,7 +3077,7 @@ bool TController::IncSpeed() if (!mvControlling->FuseFlag) if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)} { - OK = mvControlling->IncMainCtrl(std::max(1,mvOccupied->MainCtrlPosNo/10)); + OK = IncSpeedEIM(); // cruise control auto const SpeedCntrlVel { ( ( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) ? @@ -3169,6 +3179,34 @@ bool TController::DecSpeed(bool force) return OK; }; +bool TController::IncSpeedEIM() { + + bool OK = false; // domyślnie false, aby wyszło z pętli while + switch( mvControlling->EIMCtrlType ) { + case 0: + OK = mvControlling->IncMainCtrl( std::max( 1, mvOccupied->MainCtrlPosNo / 10 ) ); + break; + case 1: + OK = mvControlling->MainCtrlPos < 6; + if( OK ) + mvControlling->MainCtrlPos = 6; +/* + // TBD, TODO: set position based on desired acceleration? + OK = mvControlling->MainCtrlPos < mvControlling->MainCtrlPosNo; + if( OK ) { + mvControlling->MainCtrlPos = clamp( mvControlling->MainCtrlPos + 1, 6, mvControlling->MainCtrlPosNo ); + } +*/ + break; + case 2: + OK = mvControlling->MainCtrlPos < 4; + if( OK ) + mvControlling->MainCtrlPos = 4; + break; + } + return OK; +} + bool TController::DecSpeedEIM() { // zmniejszenie prędkości (ale nie hamowanie) bool OK = false; // domyślnie false, aby wyszło z pętli while @@ -3216,59 +3254,59 @@ void TController::SpeedSet() if (mvControlling->MainCtrlPosNo > 0) { // jeśli ma czym kręcić // TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck()) - if ((AccDesired < fAccGravity - 0.05) || - (mvOccupied->Vel > VelDesired)) // jeśli nie ma przyspieszać - mvControlling->DecMainCtrl(2); // na zero - else if (fActionTime >= 0.0) - { // jak już można coś poruszać, przetok rozłączać od razu - if (iDrivigFlags & moveIncSpeed) - { // jak ma jechać - if (fReady < 0.4) // 0.05*Controlling->MaxBrakePress) - { // jak jest odhamowany - if (mvOccupied->ActiveDir > 0) - mvOccupied->DirectionForward(); //żeby EN57 jechały na drugiej nastawie - { - if (mvControlling->MainCtrlPos && - !mvControlling->StLinFlag) // jak niby jedzie, ale ma rozłączone liniowe - mvControlling->DecMainCtrl(2); // to na zero i czekać na przewalenie kułakowego - else - switch (mvControlling->MainCtrlPos) - { // ruch nastawnika uzależniony jest od aktualnie ustawionej - // pozycji - case 0: - if (mvControlling->MainCtrlActualPos) // jeśli kułakowy nie jest - // wyzerowany - break; // to czekać na wyzerowanie - mvControlling->IncMainCtrl(1); // przetok; bez "break", bo nie - // ma czekania na 1. pozycji - case 1: - if (VelDesired >= 20) - mvControlling->IncMainCtrl(1); // szeregowa - case 2: - if (VelDesired >= 50) - mvControlling->IncMainCtrl(1); // równoległa - case 3: - if (VelDesired >= 80) - mvControlling->IncMainCtrl(1); // bocznik 1 - case 4: - if (VelDesired >= 90) - mvControlling->IncMainCtrl(1); // bocznik 2 - case 5: - if (VelDesired >= 100) - mvControlling->IncMainCtrl(1); // bocznik 3 - } - if (mvControlling->MainCtrlPos) // jak załączył pozycję - { - fActionTime = -5.0; // niech trochę potrzyma - mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania + if( ( iDrivigFlags & moveIncSpeed ) == 0 ) { + // przetok rozłączać od razu (no dependency on fActionTime) + while( ( mvControlling->MainCtrlPos ) + && ( mvControlling->DecMainCtrl( 1 ) ) ) { + ; // na zero + } + if( fActionTime >= 0.0 ) { + fActionTime = -5.0; // niech trochę potrzyma + } + mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania + } + else { + // jak ma jechać + if( fActionTime < 0.0 ) { break; } + if( fReady > 0.4 ) { break; } + + if( mvOccupied->ActiveDir > 0 ) { + mvOccupied->DirectionForward(); //żeby EN57 jechały na drugiej nastawie + } + + if( ( mvControlling->MainCtrlPos > 0 ) + && ( false == mvControlling->StLinFlag ) ) { + // jak niby jedzie, ale ma rozłączone liniowe to na zero i czekać na przewalenie kułakowego + mvControlling->DecMainCtrl( 2 ); + } + else { + // ruch nastawnika uzależniony jest od aktualnie ustawionej pozycji + switch( mvControlling->MainCtrlPos ) { + case 0: + if( mvControlling->MainCtrlActualPos ) { + // jeśli kułakowy nie jest wyzerowany to czekać na wyzerowanie + break; } - } + mvControlling->IncMainCtrl( 1 ); // przetok; bez "break", bo nie ma czekania na 1. pozycji + case 1: + if( VelDesired >= 20 ) + mvControlling->IncMainCtrl( 1 ); // szeregowa + case 2: + if( VelDesired >= 50 ) + mvControlling->IncMainCtrl( 1 ); // równoległa + case 3: + if( VelDesired >= 80 ) + mvControlling->IncMainCtrl( 1 ); // bocznik 1 + case 4: + if( VelDesired >= 90 ) + mvControlling->IncMainCtrl( 1 ); // bocznik 2 + case 5: + if( VelDesired >= 100 ) + mvControlling->IncMainCtrl( 1 ); // bocznik 3 } } - else + if( mvControlling->MainCtrlPos ) // jak załączył pozycję { - while (mvControlling->MainCtrlPos) - mvControlling->DecMainCtrl(1); // na zero fActionTime = -5.0; // niech trochę potrzyma mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania } @@ -3872,15 +3910,14 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N if( ( NewCommand == "Shunt" ) || ( NewCommand == "Loose_shunt" ) ) { // NewValue1 - ilość wagonów (-1=wszystkie); NewValue2: 0=odczep, 1..63=dołącz, -1=bez zmian - //-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w - // trybie pociągowym + //-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w trybie pociągowym //-2,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać //-2, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i czekać //-1,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać w powrotną stronę //-1, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać dalej //-1, 0 - tryb manewrowy bez zmian (odczepianie z pozostawieniem wagonów nie ma sensu) // 0, 0 - odczepienie lokomotywy - // 1,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x) wagonów + // x,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x) wagonów // 1, 0 - odczepienie lokomotywy z jednym wagonem iDrivigFlags &= ~moveStopHere; // podjeżanie do semaforów zezwolone if (!iEngineActive) @@ -4167,7 +4204,7 @@ TController::UpdateSituation(double dt) { Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego } // check door state - auto const switchsides { p->DirectionGet() <= 0 }; + auto const switchsides { p->DirectionGet() != iDirection }; IsAnyDoorOpen[ side::right ] = IsAnyDoorOpen[ side::right ] || ( false == vehicle->Doors.instances[ ( switchsides ? side::left : side::right ) ].is_closed ); @@ -4589,20 +4626,21 @@ TController::UpdateSituation(double dt) { auto *vehicleparameters { vehicle->MoverParameters }; int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) }; auto const &neighbour { vehicleparameters->Neighbours[ end ] }; - // próba podczepienia - vehicleparameters->Attach( - end, neighbour.vehicle_end, - neighbour.vehicle->MoverParameters, - iCoupler ); - if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) { - // jeżeli został podłączony - iCoupler = 0; // dalsza jazda manewrowa już bez łączenia - iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania - SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie - CheckVehicles(); // sprawdzić światła nowego składu - JumpToNextOrder(); // wykonanie następnej komendy + if( neighbour.vehicle != nullptr ) { + // próba podczepienia + vehicleparameters->Attach( + end, neighbour.vehicle_end, + neighbour.vehicle->MoverParameters, + iCoupler ); + if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) { + // jeżeli został podłączony + iCoupler = 0; // dalsza jazda manewrowa już bez łączenia + iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania + SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie + CheckVehicles(); // sprawdzić światła nowego składu + JumpToNextOrder(); // wykonanie następnej komendy + } } - } // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna } else { @@ -5788,6 +5826,7 @@ TController::UpdateSituation(double dt) { // przy odłączaniu nie zwalniamy tu hamulca if( AbsAccS < AccDesired - 0.05 ) { // jeśli opóźnienie większe od wymaganego (z histerezą) luzowanie, gdy za dużo + // TBD: check if the condition isn't redundant with the DecBrake() code if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition >= 0 ) { DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu } @@ -6552,6 +6591,9 @@ void TController::TakeControl(bool yes) void TController::DirectionForward(bool forward) { // ustawienie jazdy do przodu dla true i do tyłu dla false (zależy od kabiny) ZeroSpeed( true ); // TODO: check if force switch is needed anymore here + // HACK: make sure the master controller isn't set in position which prevents direction change + mvControlling->MainCtrlPos = std::min( mvControlling->MainCtrlPos, mvControlling->MaxMainCtrlPosNoDirChange ); + if( forward ) { // do przodu w obecnej kabinie while( ( mvOccupied->ActiveDir <= 0 ) diff --git a/DynObj.cpp b/DynObj.cpp index 41856d78..172c20bf 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6810,6 +6810,9 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) { if( pantograph->hvPowerWire != nullptr ) { // jeżeli znamy drut z poprzedniego przebiegu for( int attempts = 0; attempts < 30; ++attempts ) { + // sanity check. shouldn't happen in theory, but did happen in practice + if( pantograph->hvPowerWire == nullptr ) { break; } + // powtarzane aż do znalezienia odpowiedniego odcinka na liście dwukierunkowej if( pantograph->hvPowerWire->iLast & 0x3 ) { // dla ostatniego i przedostatniego przęsła wymuszamy szukanie innego @@ -6825,6 +6828,7 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) { } // obliczamy wyraz wolny równania płaszczyzny (to miejsce nie jest odpowienie) // podstawiamy równanie parametryczne drutu do równania płaszczyzny pantografu + // TODO: investigate this routine with reardriver/negative speed, does it picks the right wire? auto const fRaParam = -( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) ) / glm::dot( pantograph->hvPowerWire->vParametric, vFront ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index c3f0c534..dd61392d 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -502,7 +502,7 @@ bool TMoverParameters::Dettach(int ConnectNo) bool TMoverParameters::DirectionForward() { - if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) + if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (EIMDirectionChangeAllow())) { ++ActiveDir; DirAbsolute = ActiveDir * CabNo; @@ -2345,7 +2345,7 @@ bool TMoverParameters::DirectionBackward(void) DB = true; // return DB; // exit; TODO: czy dobrze przetlumaczone? } - if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) + if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (EIMDirectionChangeAllow())) { if (EngineType == TEngineType::WheelsDriven) CabNo--; @@ -2366,7 +2366,11 @@ bool TMoverParameters::DirectionBackward(void) bool TMoverParameters::EIMDirectionChangeAllow(void) { bool OK = false; +/* + // NOTE: disabled while eimic variables aren't immediately synced with master controller changes inside ai module OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1))); +*/ + OK = ( MainCtrlPos <= MaxMainCtrlPosNoDirChange ); return OK; } @@ -4326,6 +4330,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { // zderzenie coupler.CheckCollision = true; if( ( coupler.CouplerType == TCouplerType::Automatic ) + && ( coupler.CouplerType == othercoupler.CouplerType ) && ( coupler.CouplingFlag == coupling::faux ) ) { // sprzeganie wagonow z samoczynnymi sprzegami // EN57 diff --git a/Train.cpp b/Train.cpp index 6c2da0f5..2a437c25 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5725,6 +5725,7 @@ bool TTrain::Update( double const Deltatime ) btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA ); btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) ); btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 ); + btLampkaTempomat.Turn( mvControlled->ScndCtrlPos > 0 ); // universal devices state indicators for( auto idx = 0; idx < btUniversals.size(); ++idx ) { btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 ); @@ -5786,6 +5787,7 @@ bool TTrain::Update( double const Deltatime ) btLampkaMalfunction.Turn( false ); btLampkaMotorBlowers.Turn( false ); btLampkaCoolingFans.Turn( false ); + btLampkaTempomat.Turn( false ); // universal devices state indicators for( auto &universal : btUniversals ) { universal.Turn( false ); @@ -7424,6 +7426,7 @@ void TTrain::clear_cab_controls() btLampkaMalfunctionB.Clear(); btLampkaMotorBlowers.Clear(); btLampkaCoolingFans.Clear(); + btLampkaTempomat.Clear(); ggLeftLightButton.Clear(); ggRightLightButton.Clear(); @@ -7769,6 +7772,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co { "i-vent_trim:", btLampkaWentZaluzje }, { "i-motorblowers:", btLampkaMotorBlowers }, { "i-coolingfans:", btLampkaCoolingFans }, + { "i-tempomat:", btLampkaTempomat }, { "i-trainheating:", btLampkaOgrzewanieSkladu }, { "i-security_aware:", btLampkaCzuwaka }, { "i-security_cabsignal:", btLampkaSHP }, diff --git a/Train.h b/Train.h index 1e49b3a0..208cea21 100644 --- a/Train.h +++ b/Train.h @@ -583,6 +583,7 @@ public: // reszta może by?publiczna TButton btLampkaMalfunctionB; TButton btLampkaMotorBlowers; TButton btLampkaCoolingFans; + TButton btLampkaTempomat; TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine // Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys diff --git a/version.h b/version.h index 5eab7ae8..7ca02639 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 303 +#define VERSION_MINOR 327 #define VERSION_REVISION 0 From 913cfc8ae86fcb251055c99a471b3714c112f855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 2 Apr 2019 21:12:46 +0200 Subject: [PATCH 6/7] Better antislipping system in EStED --- McZapkie/MOVER.h | 1 + McZapkie/Mover.cpp | 9 ++++++--- McZapkie/hamulce.cpp | 7 ++++--- McZapkie/hamulce.h | 3 ++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index f02bd64d..fd311d9e 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1130,6 +1130,7 @@ public: double AccN = 0.0; // przyspieszenie normalne w [m/s^2] double AccVert = 0.0; // vertical acceleration double nrot = 0.0; + double nrot_eps = 0.0; //przyspieszenie kątowe kół (bez kierunku) double WheelFlat = 0.0; bool TruckHunting { true }; // enable/disable truck hunting calculation /*! rotacja kol [obr/s]*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index dd61392d..320451a8 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3708,7 +3708,7 @@ void TMoverParameters::UpdatePipePressure(double dt) Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) ); if (ASBType == 128) - Hamulec->ASB(int(SlippingWheels)); + Hamulec->ASB(int(SlippingWheels && (Vel>1))*(1+2*int(nrot_eps<-0.01))); dpPipe = 0; @@ -3956,6 +3956,7 @@ void TMoverParameters::ComputeTotalForce(double dt) { // juz zoptymalizowane: FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu + double old_nrot = abs(nrot); nrot = v2n(); // przeliczenie prędkości liniowej na obrotową if( ( true == TestFlag( BrakeMethod, bp_MHS ) ) @@ -4028,8 +4029,9 @@ void TMoverParameters::ComputeTotalForce(double dt) { } else { - Fb = -Fwheels*Sign(V); - FTrain = 0; + double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels/(FTrain - Fb * Sign(V)) : 1.0); + Fb *= factor; + FTrain *= factor; } if (nrot < 0.1) { @@ -4038,6 +4040,7 @@ void TMoverParameters::ComputeTotalForce(double dt) { nrot = temp_nrot; } + nrot_eps = (abs(nrot) - (old_nrot))/dt; // doliczenie sił z innych pojazdów for( int end = end::front; end <= end::rear; ++end ) { if( Neighbours[ end ].vehicle != nullptr ) { diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 6d258f8e..5cc3dd02 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -391,7 +391,8 @@ void TBrake::SetEPS( double const nEPS ) void TBrake::ASB( int const state ) { // 255-b_asb(32) - BrakeStatus = (BrakeStatus & ~b_asb) | ( state * b_asb ); + BrakeStatus = (BrakeStatus & ~b_asb) | ( (state / 2) * b_asb ); + BrakeStatus = (BrakeStatus & ~b_asb_unbrake) | ( (state % 2) * b_asb_unbrake); } int TBrake::GetStatus() @@ -1551,7 +1552,7 @@ 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); double speed = 1; - if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb)) + if ((ASBP < 0.1) && ((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) { temp = 0; speed = 3; @@ -1559,7 +1560,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel ) if ((BrakeCyl->P() > temp)) dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC * speed, temp) * dt; - else if ((BrakeCyl->P() < temp)) + else if ((BrakeCyl->P() < temp) && ((BrakeStatus & b_asb) == 0)) dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt; else dv = 0; diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index d09427c5..6ae70eca 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -53,7 +53,8 @@ static int const b_on = 2; //napelnianie static int const b_rfl = 4; //uzupelnianie static int const b_rls = 8; //odluzniacz static int const b_ep = 16; //elektropneumatyczny -static int const b_asb = 32; //elektropneumatyczny +static int const b_asb = 32; //przeciwposlizg-wstrzymanie +static int const b_asb_unbrake = 64; //przeciwposlizg-luzowanie static int const b_dmg = 128; //wylaczony z dzialania /*uszkodzenia hamulca*/ From 031da3baf60483b83da27ba57ebad2a512f483ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 2 Apr 2019 22:54:56 +0200 Subject: [PATCH 7/7] Added new LocalBrake algorithm for TRAXX - test of mechanism --- DynObj.cpp | 6 ++++++ McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/DynObj.cpp b/DynObj.cpp index 172c20bf..b7e14ee3 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2713,6 +2713,7 @@ bool TDynamicObject::Update(double dt, double dt1) MoverParameters->eimic_real = eimic; MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo); auto LBR = Max0R(-eimic, 0); + auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake); // 1. ustal wymagana sile hamowania calego pociagu // - opoznienie moze byc ustalane na podstawie charakterystyki @@ -2943,6 +2944,11 @@ bool TDynamicObject::Update(double dt, double dt1) p->MoverParameters->LocalBrakePosAEIM = p->MoverParameters->LocalBrakePosAEIM; else p->MoverParameters->LocalBrakePosAEIM = 0; + if (p->MoverParameters->LocHandleTimeTraxx) + { + p->MoverParameters->eim_localbrake = eim_lb; + p->MoverParameters->LocalBrakePosAEIM = std::max(p->MoverParameters->LocalBrakePosAEIM, eim_lb); + } ++i; } diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index fd311d9e..ee7031be 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -891,6 +891,7 @@ public: TBrakeValve BrakeValve = TBrakeValve::NoValve; TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle; TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle; + bool LocHandleTimeTraxx = false; /*hamulec dodatkowy typu traxx*/ double MBPM = 1.0; /*masa najwiekszego cisnienia*/ std::shared_ptr Hamulec; @@ -1306,6 +1307,7 @@ public: /*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/ double eimic = 0; /*aktualna pozycja zintegrowanego sterowania jazda i hamowaniem*/ double eimic_real = 0; /*faktycznie uzywana pozycja zintegrowanego sterowania jazda i hamowaniem*/ + double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 320451a8..132e557c 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6016,6 +6016,26 @@ void TMoverParameters::CheckEIMIC(double dt) } if (MainCtrlPos >= 3 && eimic < 0) eimic = 0; if (MainCtrlPos <= 3 && eimic > 0) eimic = 0; + if (LocHandleTimeTraxx) + { + if (LocalBrakeRatio() < 0.05) //pozycja 0 + { + eim_localbrake -= dt*0.17; //zmniejszanie + } + + if (LocalBrakeRatio() > 0.15) //pozycja 2 + { + eim_localbrake += dt*0.17; //wzrastanie + eim_localbrake = std::max(eim_localbrake, BrakePress / MaxBrakePress[0]); + } + else + { + if (eim_localbrake < Hamulec->GetEDBCP() / MaxBrakePress[0]) + eim_localbrake = 0; + } + eim_localbrake = clamp(eim_localbrake, 0.0, 1.0); + if (eim_localbrake > 0.04 && eimic > 0) eimic = 0; + } break; case 2: switch (MainCtrlPos) @@ -8631,6 +8651,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( CoupledCtrl, "CoupledCtrl", line, "" ); extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); clamp( EIMCtrlType, 0, 3 ); + LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes"); extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR