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