diff --git a/vehicle/Driver.cpp b/vehicle/Driver.cpp index 55311b19..75bbb29e 100644 --- a/vehicle/Driver.cpp +++ b/vehicle/Driver.cpp @@ -154,6 +154,11 @@ const double HeavyPassengetTrainAcceleration = 0.20; const double CargoTrainAcceleration = 0.25; const double HeavyCargoTrainAcceleration = 0.10; const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu +const double FSOverchargePipePress = 5.2; +const double FSOverchargeTime = 2.0; +const double FSOverchargeCRP = 0.05; +const double FSMaxTime = 10.0; +const double DepartBlockedFSDelay = 10.0; bool WriteLogFlag = false; double const deltalog = 0.05; // przyrost czasu @@ -6009,6 +6014,17 @@ TController::determine_consist_state() { && fReady < 0.8 ) { // delikatniejszy warunek, obejmuje wszystkie wagony Ready = true; //żeby uznać za odhamowany } + auto const departblocked { + AIControllFlag + && mvOccupied->Vel < EU07_AI_NOMOVEMENT + && VelDesired > 0.0 + && ( false == Ready || fReady > 0.4 ) }; + if( false == departblocked ) { + DepartBlockedStart = -1.0; + } + else if( DepartBlockedStart < 0.0 ) { + DepartBlockedStart = ElapsedTime; + } // second pass, for diesel engines verify the (live) engines are fully started // TODO: cache presence of diesel engines in the consist, to skip this test if there isn't any p = pVehicles[ end::front ]; // pojazd na czole składu @@ -8014,8 +8030,9 @@ void TController::control_main_pipe() { || mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P || mvOccupied->BrakeHandle == TBrakeHandle::M394 ) { - if( (iDrivigFlags & moveOerlikons || true == IsCargoTrain) && BrakeCtrlPosition == gbh_RP && AbsAccS < 0.03 && AccDesired > -0.03 && VelDesired - mvOccupied->Vel > 2.0 && fReady > 0.35 && - mvOccupied->EqvtPipePress < 4.5 // don't charge with a risk of overcharging the main pipe + auto const departblocked { is_departure_blocked( DepartBlockedFSDelay ) }; + if( (iDrivigFlags & moveOerlikons || true == IsCargoTrain || departblocked) && BrakeCtrlPosition == gbh_RP && AbsAccS < 0.03 && AccDesired > -0.03 && VelDesired - mvOccupied->Vel > 2.0 && fReady > 0.35 && + ( mvOccupied->EqvtPipePress < 4.5 || departblocked ) // don't charge with a risk of overcharging the main pipe && mvOccupied->Compressor >= 7.5 // don't charge without sufficient pressure in the tank && BrakeChargingCooldown >= 0.0 // don't charge while cooldown is active && (ActualProximityDist > 100.0 // don't charge if we're about to be braking soon @@ -8026,14 +8043,66 @@ void TController::control_main_pipe() { BrakeChargingCooldown = -1 * std::clamp(iVehicles * 3, 30, 90); } + update_brake_charging(); + if( mvOccupied->Compressor < 5.0 || ( BrakeCtrlPosition < gbh_RP - && mvOccupied->EqvtPipePress > (fReady < 0.25 ? 5.1 : 5.2) ) ) { + && ( mvOccupied->EqvtPipePress > (fReady < 0.25 ? 5.1 : 5.2) || is_brake_charging_done() ) ) ) { cue_action( driver_hint::trainbrakerelease ); } } } +void TController::update_brake_charging() { + + if( std::abs( BrakeCtrlPosition - gbh_FS ) >= 0.5 ) { + BrakeChargingStart = -1.0; + BrakeChargingPipeOverchargeStart.clear(); + return; + } + if( BrakeChargingStart < 0.0 ) { + BrakeChargingStart = ElapsedTime; + } + for( auto const *vehicle { pVehicles[ end::front ] }; vehicle != nullptr; vehicle = vehicle->Next() ) { + auto const isovercharged { + vehicle->MoverParameters != mvOccupied + && vehicle->MoverParameters->PipePress > FSOverchargePipePress }; + if( isovercharged ) { + BrakeChargingPipeOverchargeStart.try_emplace( vehicle, ElapsedTime ); + } + else { + BrakeChargingPipeOverchargeStart.erase( vehicle ); + } + } +} + +bool TController::is_departure_blocked( double const Delay ) const { + + return DepartBlockedStart >= 0.0 + && ElapsedTime - DepartBlockedStart > Delay; +} + +double TController::consist_max_crp() const { + + auto result { 0.0 }; + for( auto const *vehicle { pVehicles[ end::front ] }; vehicle != nullptr; vehicle = vehicle->Next() ) { + result = std::max( result, vehicle->MoverParameters->Hamulec->GetCRP() ); + } + return result; +} + +bool TController::is_brake_charging_done() const { + + if( BrakeChargingStart < 0.0 ) { + return false; + } + return ElapsedTime - BrakeChargingStart > FSMaxTime + || consist_max_crp() > mvOccupied->HighPipePress + FSOverchargeCRP + || std::ranges::any_of( + BrakeChargingPipeOverchargeStart, + [this]( auto const &Vehicle ) { return ElapsedTime - Vehicle.second > FSOverchargeTime; } ); +} + void TController::check_route_ahead( double const Range ) { diff --git a/vehicle/Driver.h b/vehicle/Driver.h index 644b8122..da14b1b3 100644 --- a/vehicle/Driver.h +++ b/vehicle/Driver.h @@ -348,6 +348,10 @@ private: void control_tractive_and_braking_force(); void control_releaser(); void control_main_pipe(); + void update_brake_charging(); + bool is_brake_charging_done() const; + double consist_max_crp() const; + bool is_departure_blocked( double const Delay ) const; void control_relays(); void control_motor_connectors(); void control_tractive_force(); @@ -450,6 +454,9 @@ private: double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca double BrakeChargingCooldown{}; // prevents the ai from trying to charge the train brake too frequently + double BrakeChargingStart = -1.0; + std::unordered_map BrakeChargingPipeOverchargeStart; + double DepartBlockedStart = -1.0; TBrakeSystem BrakeSystem = TBrakeSystem::Individual; //type of main brake bool ForcePNBrake = false; //is it necessary to use PN brake instead of EP brake int DynamicBrakeTest = 0; //is it necessary to make brake test while driving