16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 21:49:19 +02:00

Merge commit 'd8170c932b448ba6888e702746b5ae22632062d8' into sim

This commit is contained in:
milek7
2022-01-05 01:02:56 +01:00
76 changed files with 9277 additions and 5749 deletions

View File

@@ -205,6 +205,10 @@ bool TSecuritySystem::radiostop_available() const {
return radiostop_enabled;
}
bool TSecuritySystem::system_available() const {
return vigilance_enabled || cabsignal_enabled;
}
bool TSecuritySystem::is_engine_blocked() const {
if (!is_sifa)
return false;
@@ -323,6 +327,10 @@ double TMoverParameters::Current(double n, double U)
}
else {
Mn = RList[ MainCtrlActualPos ].Mn * RList[ MainCtrlActualPos ].Bn;
if( RList[ MainCtrlActualPos ].Bn > 1 ) {
Bn = 1;
R = CircuitRes;
}
}
if (DynamicBrakeFlag && (!FuseFlag) && (DynamicBrakeType == dbrake_automatic) &&
@@ -649,23 +657,39 @@ bool TMoverParameters::Dettach(int ConnectNo)
if( othervehicle == nullptr ) { return true; } // nie ma nic, to odczepiono
auto const i = DettachStatus(ConnectNo); // stan sprzęgu
if (i < 0) {
auto couplingchange { coupler.CouplingFlag }; // presume we'll uncouple all active flags
auto const couplingstate { DettachStatus( ConnectNo ) }; // stan sprzęgu
if (couplingstate < 0) {
// gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
std::tie( coupler.Connected, coupler.ConnectedNr, coupler.CouplingFlag )
= std::tie( othercoupler.Connected, othercoupler.ConnectedNr, othercoupler.CouplingFlag )
= std::make_tuple( nullptr, -1, coupling::faux );
// set sound event flag
SetFlag( coupler.sounds, sound::detachall );
return true;
}
else if (i > 0)
else if (couplingstate > 0)
{ // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym nic)
coupler.CouplingFlag &= coupling::coupler;
othercoupler.CouplingFlag &= coupling::coupler;
}
return false; // jeszcze nie rozłączony
// set sound event flag
couplingchange ^= coupler.CouplingFlag; // remaining bits were removed from coupling
if( couplingchange != 0 ) {
int soundflag { sound::detach }; // HACK: use detach flag to indicate removal of listed coupling
std::vector<std::pair<coupling, sound>> const soundmappings = {
{ coupling::coupler, sound::attachcoupler },
{ coupling::brakehose, sound::attachbrakehose },
{ coupling::mainhose, sound::attachmainhose },
{ coupling::control, sound::attachcontrol},
{ coupling::gangway, sound::attachgangway},
{ coupling::heating, sound::attachheating} };
for( auto const &soundmapping : soundmappings ) {
if( ( couplingchange & soundmapping.first ) != 0 ) {
soundflag |= soundmapping.second;
}
}
SetFlag( coupler.sounds, soundflag );
}
return ( couplingstate < 0 );
};
bool TMoverParameters::DirectionForward()
@@ -769,10 +793,12 @@ bool TMoverParameters::ChangeCab(int direction)
// rozruch wysoki (true) albo niski (false)
bool
TMoverParameters::CurrentSwitch(bool const State) {
// Ra: przeniosłem z Train.cpp, nie wiem czy ma to sens
if (MaxCurrentSwitch(State)) {
if (TrainType != dt_EZT)
return (MinCurrentSwitch(State));
if( MaxCurrentSwitch( State ) ) {
if( TrainType != dt_EZT ) {
( MinCurrentSwitch( State ) );
}
return true;
}
// TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that
// dla 2Ls150
@@ -794,6 +820,12 @@ TMoverParameters::CurrentSwitch(bool const State) {
return false;
};
bool
TMoverParameters::IsMotorOverloadRelayHighThresholdOn() const {
return ( ( ImaxHi > ImaxLo ) && ( Imax > ImaxLo ) );
}
// KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak
void TMoverParameters::UpdatePantVolume(double dt) {
// check the pantograph compressor while at it
@@ -1541,6 +1573,23 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
RunInternalCommand();
// relay settings
if( EngineType == TEngineType::ElectricSeriesMotor ) {
// adjust motor overload relay threshold
if( ImaxHi > ImaxLo ) {
if( MotorOverloadRelayHighThreshold ) { // set high threshold
if( ( TrainType != dt_ET42 ) ? ( RList[ MainCtrlPos ].Bn < 2 ) : ( MainCtrlPos == 0 ) ) {
Imax = ImaxHi;
}
}
else { // set low threshold
if( ( TrainType != dt_ET42 ) || ( MainCtrlPos == 0 ) ) {
Imax = ImaxLo;
}
}
}
}
// automatyczny rozruch
if( EngineType == TEngineType::ElectricSeriesMotor ) {
if( AutoRelayCheck() ) {
@@ -1610,13 +1659,14 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
PowerCouplersCheck( Deltatime, coupling::power110v );
PowerCouplersCheck( Deltatime, coupling::power24v );
Power24vIsAvailable = ( ( PowerCircuits[ 0 ].first > 0 ) || ( GetTrainsetVoltage( coupling::power24v ) > 0 ) );
Power24vVoltage = std::max( PowerCircuits[ 0 ].first, GetTrainsetVoltage( coupling::power24v ) );
Power24vIsAvailable = ( Power24vVoltage > 0 );
Power110vIsAvailable = ( ( PowerCircuits[ 1 ].first > 0 ) || ( GetTrainsetVoltage( coupling::power110v ) > 0 ) );
}
void TMoverParameters::MainsCheck( double const Deltatime ) {
if( MainsInitTime == 0.0 ) { return; }
// if( MainsInitTime == 0.0 ) { return; }
// TBD, TODO: move voltage calculation to separate method and use also in power coupler state calculation?
auto localvoltage { 0.0 };
@@ -1628,6 +1678,13 @@ void TMoverParameters::MainsCheck( double const Deltatime ) {
PantographVoltage );
break;
}
case TPowerSource::Accumulator: {
localvoltage =
std::max(
localvoltage,
Power24vVoltage );
break;
}
default: {
break;
}
@@ -1643,6 +1700,13 @@ void TMoverParameters::MainsCheck( double const Deltatime ) {
// this allows for simpler rejection of cases where MainsInitTime == 0
MainsInitTimeCountdown -= Deltatime;
}
else {
// optional automatic circuit start
if( ( MainsStart != start_t::manual )
&& ( false == ( Mains || dizel_startup ) ) ) {
MainSwitch( true );
}
}
}
else {
// no power supply
@@ -2137,7 +2201,28 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) {
void TMoverParameters::MotorBlowersCheck( double const Timestep ) {
// activation check
for( auto &blower : MotorBlowers ) {
auto disable = blower.is_disabled;
auto const start { ( Vel >= blower.min_start_velocity && Im > 0.5 ) };
auto const stop { ( Vel < 0.5 && Im < 0.5 ) };
if (blower.min_start_velocity >= 0)
{
if ( stop )
{
blower.stop_timer += Timestep;
if (blower.stop_timer > blower.sustain_time)
{
disable = true;
}
}
else if ( start )
{
blower.stop_timer = 0;
}
else
{
disable |= !blower.is_active;
}
}
blower.is_active = (
// TODO: bind properly power source when ld is in place
( blower.start_type == start_t::battery ? Power24vIsAvailable :
@@ -2145,11 +2230,12 @@ void TMoverParameters::MotorBlowersCheck( double const Timestep ) {
Mains ) // power source
// breaker condition disabled until it's implemented in the class data
// && ( true == blower.breaker )
&& ( false == blower.is_disabled )
&& ( false == disable)
&& ( ( true == blower.is_active )
|| ( blower.start_type == start_t::manual ?
|| ( ( blower.stop_timer == 0.f ) // HACK: will be true for blower with exceeded start_velocity, and for one without start_velocity
&& ( blower.start_type == start_t::manual ?
blower.is_enabled :
true ) ) );
true ) ) ) );
}
// update
for( auto &fan : MotorBlowers ) {
@@ -2343,14 +2429,12 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
OK = true;
if( Imax == ImaxHi ) {
if( RList[ MainCtrlPos ].Bn > 1 ) {
/* NOTE: disabled, relay configuration was moved to compute_movement_
if( true == MaxCurrentSwitch( false )) {
// wylaczanie wysokiego rozruchu
SetFlag( SoundFlag, sound::relay );
} // Q TODO:
// if (EngineType=ElectricSeriesMotor) and (MainCtrlPos=1)
// then
// MainCtrlActualPos:=1;
//
}
*/
if( TrainType == dt_ET42 ) {
--MainCtrlPos;
OK = false;
@@ -2566,6 +2650,11 @@ bool TMoverParameters::IsMainCtrlNoPowerPos() const {
return MainCtrlPos <= MainCtrlNoPowerPos();
}
bool TMoverParameters::IsMainCtrlMaxPowerPos() const {
// TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems
return MainCtrlPos == MainCtrlPosNo;
}
int TMoverParameters::MainCtrlNoPowerPos() const {
switch( EIMCtrlType ) {
@@ -2735,6 +2824,16 @@ int TMoverParameters::GetVirtualScndPos()
return ScndCtrlPos;
}
bool TMoverParameters::IsScndCtrlNoPowerPos() const {
// TODO: refine the check on account of potential electric series vehicles with speed control
return ( ( ScndCtrlPos == 0 ) || ( true == SpeedCtrl ) );
}
bool TMoverParameters::IsScndCtrlMaxPowerPos() const {
// TODO: refine the check on account of potential electric series vehicles with speed control
return ( ( ScndCtrlPos == ScndCtrlPosNo ) || ( true == SpeedCtrl ) );
}
// *************************************************************************************************
// Q: 20160710
// załączenie rozrządu
@@ -2942,7 +3041,7 @@ void TMoverParameters::SecuritySystemCheck(double dt)
{
SecuritySystem.update(dt, Vel, Power24vIsAvailable || Power110vIsAvailable);
if (!Battery || !Radio)
if (!Battery || !Radio)
{ // wyłączenie baterii deaktywuje sprzęt
RadiostopSwitch(false);
}
@@ -3474,7 +3573,7 @@ void TMoverParameters::MainSwitch_( bool const State ) {
return;
}
bool const initialstate { Mains || dizel_startup };
bool const initialstate { Mains };
if( ( false == State )
|| ( true == MainSwitchCheck() ) ) {
@@ -3519,7 +3618,8 @@ bool TMoverParameters::MainSwitchCheck() const {
}
case TEngineType::ElectricSeriesMotor:
case TEngineType::ElectricInductionMotor: {
powerisavailable = ( std::max( GetTrainsetHighVoltage(), PantographVoltage ) > 0.5 * EnginePowerSource.MaxVoltage );
// TODO: check whether we can simplify this check and skip the outer EngineType switch
powerisavailable = ( EnginePowerSourceVoltage() > 0.5 * EnginePowerSource.MaxVoltage );
break;
}
default: {
@@ -3614,6 +3714,42 @@ bool TMoverParameters::ChangeCompressorPreset( int const State, range_t const No
return ( CompressorListPos != initialstate );
}
bool TMoverParameters::HeatingSwitch( bool const State, range_t const Notify ) {
bool const initialstate { HeatingAllow };
HeatingSwitch_( State );
if( Notify != range_t::local ) {
// pass the command to other vehicles
// TBD: pass the requested state, or the actual state?
SendCtrlToNext(
"HeatingSwitch",
( State ? 1 : 0 ),
CabActive,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return ( HeatingAllow != initialstate );
}
void TMoverParameters::HeatingSwitch_( bool const State ) {
// TBD, TODO: activation dependencies?
HeatingAllow = State;
}
// returns voltage of defined main engine power source
double TMoverParameters::EnginePowerSourceVoltage() const {
return (
EnginePowerSource.SourceType == TPowerSource::CurrentCollector ? std::max( GetTrainsetHighVoltage(), PantographVoltage ) :
EnginePowerSource.SourceType == TPowerSource::Accumulator ? Power24vVoltage :
0.0 );
}
// *************************************************************************************************
// Q: 20160711
// zwiększenie nastawy hamulca
@@ -3892,17 +4028,16 @@ bool TMoverParameters::UniversalBrakeButton(int button, int state)
bool TMoverParameters::SwitchEPBrake(int state)
{
bool OK;
double temp;
OK = false;
if ((BrakeHandle == TBrakeHandle::St113) && (CabOccupied != 0))
{
if (state > 0)
temp = Handle->GetEP(); // TODO: przetlumaczyc
EpForce = Handle->GetEP(); // TODO: przetlumaczyc
else
temp = 0;
Hamulec->SetEPS(temp);
SendCtrlToNext("Brake", temp, CabActive);
EpForce = 0;
Hamulec->SetEPS(EpForce);
SendCtrlToNext("Brake", EpForce, CabActive);
}
// OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused));
// SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabActive);
@@ -4315,6 +4450,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
// ulepszony hamulec bezp.
EmergencyValveFlow = 0.0;
auto const securitysystempresent { SecuritySystem.radiostop_available() || SecuritySystem.system_available() };
auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable };
if( (( true == RadioStopFlag )
@@ -4324,12 +4460,17 @@ void TMoverParameters::UpdatePipePressure(double dt)
|| SecuritySystem.is_braking())
|| ( ( SpringBrakeDriveEmergencyVel >= 0 )
&& ( Vel > SpringBrakeDriveEmergencyVel )
&& ( SpringBrake.IsActive ) ) )
&& ( SpringBrake.IsActive ) )
/*
// NOTE: disabled because 32 is 'load destroyed' flag, what does this have to do with emergency brake?
// (if it's supposed to be broken coupler, such event sets alarmchainflag instead when appropriate)
|| ( true == TestFlag( EngDmgFlag, 32 ) )
*/ {
*/
|| ( ( SpringBrakeDriveEmergencyVel >= 0 )
&& ( Vel > SpringBrakeDriveEmergencyVel )
&& ( SpringBrake.IsActive ) )
|| ( ( true == securitysystempresent )
&& ( false == lowvoltagepower ) ) ) {
EmergencyValveFlow = PF( 0, PipePress, 0.15 ) * dt;
}
dpMainValve += EmergencyValveFlow;
@@ -4455,25 +4596,25 @@ void TMoverParameters::UpdatePipePressure(double dt)
&& (DirActive != 0)
&& (EpFuse)) // tu powinien byc jeszcze bezpiecznik EP i baterie -
// temp = (Handle as TFVel6).GetCP
temp = Handle->GetEP();
EpForce = Handle->GetEP();
else
temp = 0.0;
EpForce = 0.0;
DynamicBrakeEMUStatus = (
temp > 0.001 ?
EpForce > 0.001 ?
Power110vIsAvailable :
true );
double temp1 = temp;
double temp1 = EpForce;
if ((DCEMUED_EP_max_Vel > 0.001) && (Vel > DCEMUED_EP_max_Vel) && (DynamicBrakeEMUStatus))
temp1 = 0;
if ((DCEMUED_EP_min_Im > 0.001) && (abs(Im) > DCEMUED_EP_min_Im) && (DynamicBrakeEMUStatus))
temp1 = 0;
Hamulec->SetEPS(temp1);
TUHEX_StageActual = temp;
TUHEX_StageActual = EpForce;
TUHEX_Active = TUHEX_StageActual > 0;
// Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach
SendCtrlToNext("Brake", temp, CabActive);
SendCtrlToNext("Brake", EpForce, CabActive);
}
Pipe->Act();
@@ -4807,10 +4948,8 @@ void TMoverParameters::ComputeTotalForce(double dt) {
{ // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik
EngineVoltage = (
Mains ?
std::max(
GetTrainsetHighVoltage(),
PantographVoltage ) :
0.00 );
EnginePowerSourceVoltage() :
0.0 );
if( CabActive == 0 ) {
EngineVoltage *= DirActive;
}
@@ -5214,6 +5353,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
}
if( Attach( End, otherend, othervehicle, couplingtype ) ) {
// HACK: we're reusing sound enum to mark whether vehicle was connected to another
SetFlag( AIFlag, sound::attachcoupler );
coupler.AutomaticCouplingAllowed = false;
othercoupler.AutomaticCouplingAllowed = false;
@@ -5269,7 +5409,7 @@ double TMoverParameters::TractionForce( double dt ) {
/ 60.0 );
}
// NOTE: fake dizel_fill calculation for the sake of smoke emitter which uses this parameter to determine smoke opacity
dizel_fill = clamp( 0.2 + 0.35 * ( tmp - enrot ), 0.0, 1.0 );
dizel_fill = clamp( 0.2 + 0.35 * ( tmp - enrot ) + 0.5 * ( std::abs( Im ) / DElist[ MainCtrlPosNo ].Imax ), 0.05, 1.0 );
}
else {
tmp = 0.0;
@@ -5280,8 +5420,8 @@ double TMoverParameters::TractionForce( double dt ) {
enrot = clamp(
enrot + ( dt / dizel_AIM ) * (
enrot < tmp ?
1.0 :
-2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not
1.0 :
-1.0 * dizel_RevolutionsDecreaseRate ), // NOTE: revolutions typically drop faster than they rise
0.0, std::max( tmp, enrot ) );
if( std::abs( tmp - enrot ) < 0.001 ) {
enrot = tmp;
@@ -6506,31 +6646,23 @@ bool TMoverParameters::CutOffEngine(void)
// Q: 20160713
// Przełączenie wysoki / niski prąd rozruchu
// *************************************************************************************************
bool TMoverParameters::MaxCurrentSwitch(bool State)
bool TMoverParameters::MaxCurrentSwitch(bool State, range_t const Notify )
{
bool MCS = false;
if (EngineType == TEngineType::ElectricSeriesMotor)
if (ImaxHi > ImaxLo)
{
if (State && (Imax == ImaxLo) && (RList[MainCtrlPos].Bn < 2) &&
!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
{
Imax = ImaxHi;
MCS = true;
if (CabActive != 0)
SendCtrlToNext("MaxCurrentSwitch", 1, CabActive);
}
if (!State)
if (Imax == ImaxHi)
if (!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
{
Imax = ImaxLo;
MCS = true;
if (CabActive != 0)
SendCtrlToNext("MaxCurrentSwitch", 0, CabActive);
}
}
return MCS;
auto const initialstate { MotorOverloadRelayHighThreshold };
MotorOverloadRelayHighThreshold = State;
if( Notify != range_t::local ) {
SendCtrlToNext(
"MaxCurrentSwitch",
( State ? 1 : 0 ),
CabActive,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return State != initialstate;
}
// *************************************************************************************************
@@ -6672,19 +6804,24 @@ bool TMoverParameters::AutoRelayCheck(void)
}
else
{ // zmieniaj mainctrlactualpos
if ((DirActive < 0) && (TrainType != dt_PseudoDiesel))
if (RList[MainCtrlActualPos + 1].Bn > 1)
{
if( ( DirActive < 0 ) && ( TrainType != dt_PseudoDiesel ) ) {
if( RList[ MainCtrlActualPos + 1 ].Bn > 1 ) {
return false; // nie poprawiamy przy konwersji
// return ARC;// bbylo exit; //Ra: to powoduje, że EN57 nie wyłącza się przy
// IminLo
// return ARC;// bbylo exit; //Ra: to powoduje, że EN57 nie wyłącza się przy IminLo
}
}
// main bez samoczynnego rozruchu
if( ( MainCtrlActualPos < ( sizeof( RList ) / sizeof( TScheme ) - 1 ) ) // crude guard against running out of current fixed table
&& ( ( RList[ MainCtrlActualPos ].Relay < MainCtrlPos )
|| ( ( RList[ MainCtrlActualPos + 1 ].Relay == MainCtrlPos ) && ( MainCtrlActualPos < RlistSize ) )
|| ( ( TrainType == dt_ET22 ) && ( DelayCtrlFlag ) ) ) ) {
// prevent switch to parallel mode if motor overload relay is set to high threshold mode
if( ( IsMotorOverloadRelayHighThresholdOn() )
&& ( RList[ MainCtrlActualPos + 1 ].Bn > 1 ) ) {
return false;
}
if( ( RList[MainCtrlPos].R == 0 )
&& ( MainCtrlPos > 0 )
&& ( MainCtrlPos != MainCtrlPosNo )
@@ -6911,8 +7048,6 @@ bool TMoverParameters::OperatePantographsValve( operation_t const State, range_t
if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
&& ( EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ) {
auto const lowvoltagepower { PantsValve.solenoid ? ( Power24vIsAvailable || Power110vIsAvailable ) : true };
auto &valve { PantsValve };
switch( State ) {
@@ -7001,7 +7136,8 @@ void TMoverParameters::CheckEIMIC(double dt)
switch (EIMCtrlType)
{
case 0:
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo);
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() :
eimic_analog > 0.01 ? eimic_analog : (double)MainCtrlPos / (double)MainCtrlPosNo);
if (EIMCtrlAdditionalZeros || EIMCtrlEmergency)
{
if (eimic > 0.001)
@@ -8213,7 +8349,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
bool const initialstate { Doors.instances[Door].open_permit };
Doors.instances[ Door ].open_permit = State;
PermitDoors_( Door, State );
if( Notify != range_t::local ) {
@@ -8232,6 +8368,14 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
return ( Doors.instances[ Door ].open_permit != initialstate );
}
void TMoverParameters::PermitDoors_( side const Door, bool const State ) {
if( ( State ) && ( State != Doors.instances[ Door ].open_permit ) ) {
SetFlag( SoundFlag, sound::doorpermit );
}
Doors.instances[ Door ].open_permit = State;
}
bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) {
auto const initialstate { Doors.remote_only };
@@ -8257,7 +8401,7 @@ bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const No
OperateDoors( side::right, true );
}
return ( Doors.step_enabled != initialstate );
return ( Doors.remote_only != initialstate );
}
bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) {
@@ -8399,8 +8543,8 @@ TMoverParameters::update_doors( double const Deltatime ) {
door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.local_close = door.local_close && ( false == door.is_closed );
door.remote_close = door.remote_close && ( false == door.is_closed );
door.local_close = door.local_close && ( false == door.is_closed ) && ( ( false == remoteopencontrol ) || ( false == door.remote_open ) );
door.remote_close = door.remote_close && ( false == door.is_closed ) && ( ( false == localopencontrol ) || ( false == door.local_open ) );
auto const autoopenrequest {
( Doors.open_control == control_t::autonomous )
@@ -8460,21 +8604,15 @@ TMoverParameters::update_doors( double const Deltatime ) {
// doors
if( true == door.is_opening ) {
// open door
if( ( TrainType == dt_EZT )
|| ( TrainType == dt_DMU ) ) {
// multi-unit vehicles typically open door only after unfolding the doorstep
if( ( false == door.step_unfolding ) // no wait if no doorstep
|| ( Doors.step_type == 2 ) ) { // no wait for rotating doorstep
if( ( false == door.step_unfolding ) // no wait if no doorstep
|| ( Doors.step_type == 2 ) ) { // no wait for rotating doorstep
door.open_delay += Deltatime;
if( door.open_delay > Doors.open_delay ) {
door.position = std::min<float>(
Doors.range,
door.position + Doors.open_rate * Deltatime );
}
}
else {
door.position = std::min<float>(
Doors.range,
door.position + Doors.open_rate * Deltatime );
}
door.close_delay = 0.f;
}
if( true == door.is_closing ) {
@@ -8485,6 +8623,7 @@ TMoverParameters::update_doors( double const Deltatime ) {
0.f,
door.position - Doors.close_rate * Deltatime );
}
door.open_delay = 0.f;
}
// doorsteps
if( door.step_unfolding ) {
@@ -9121,7 +9260,7 @@ void TMoverParameters::BrakeValveDecode( std::string const &Valve ) {
TBrakeValve::Other;
if( ( BrakeValve == TBrakeValve::Other )
&& ( Valve.find( "ESt" ) != std::string::npos ) ) {
&& ( contains( Valve, "ESt" ) ) ) {
BrakeValve = TBrakeValve::ESt3;
}
@@ -9218,8 +9357,8 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
inputline = fizparser.getToken<std::string>( false, "\n\r" );
bool comment = ( ( inputline.find('#') != std::string::npos )
|| ( inputline.compare( 0, 2, "//" ) == 0 ) );
bool comment = ( ( contains( inputline, '#') )
|| ( starts_with( inputline, "//" ) ) );
if( true == comment ) {
// skip commented lines
continue;
@@ -9852,8 +9991,8 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
*/
extract_value( MinCompressor, "MinCP", line, "" );
extract_value( MaxCompressor, "MaxCP", line, "" );
extract_value( MinCompressor, "MinCP_B", line, "" );
extract_value( MaxCompressor, "MaxCP_B", line, "" );
extract_value( MinCompressor_cabB, "MinCP_B", line, "" );
extract_value( MaxCompressor_cabB, "MaxCP_B", line, "" );
extract_value( CompressorTankValve, "CompressorTankValve", line, "" );
extract_value( CompressorSpeed, "CompressorSpeed", line, "" );
extract_value( EmergencyValveOff, "MinEVP", line, "" );
@@ -9956,6 +10095,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
}
extract_value( Doors.open_rate, "OpenSpeed", line, "" );
extract_value( Doors.open_delay, "DoorOpenDelay", line, "" );
extract_value( Doors.close_rate, "CloseSpeed", line, "" );
extract_value( Doors.close_delay, "DoorCloseDelay", line, "" );
extract_value( Doors.range, "DoorMaxShiftL", line, "" );
@@ -9999,6 +10139,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
extract_value( MirrorMaxShift, "MirrorMaxShift", line, "" );
extract_value( MirrorVelClose, "MirrorVelClose", line, "");
extract_value( DoorsOpenWithPermitAfter, "DoorOpenWithPermit", line, "" );
}
void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Index ) {
@@ -10290,6 +10431,13 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
// main circuit
extract_value( MainsInitTime, "MainInitTime", line, "" );
{
auto lookup = starts.find( extract_value( "MainStart", line ) );
MainsStart =
lookup != starts.end() ?
lookup->second :
start_t::manual;
}
// battery
{
auto lookup = starts.find( extract_value( "BatteryStart", line ) );
@@ -10425,6 +10573,9 @@ void TMoverParameters::LoadFIZ_Blending(std::string const &line) {
extract_value(MED_EPVC, "MED_EPVC", line, "");
extract_value(MED_Ncor, "MED_Ncor", line, "");
extract_value(MED_MinBrakeReqED, "MED_MinBrakeReqED", line, "");
extract_value(MED_FrED_factor, "MED_FrEDFactor", line, "");
extract_value(MED_ED_Delay1, "MED_FirstDelayED", line, "");
extract_value(MED_ED_Delay2, "MED_ScndDelayED", line, "");
}
void TMoverParameters::LoadFIZ_DCEMUED(std::string const &line) {
@@ -10606,6 +10757,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
extract_value( dizel_nmax_cutoff, "nmax_cutoff", Input, "0.0" );
dizel_nmax_cutoff /= 60.0;
extract_value( dizel_AIM, "AIM", Input, "1.0" );
extract_value( dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, "" );
extract_value(engageupspeed, "EUS", Input, "0.5");
extract_value(engagedownspeed, "EDS", Input, "0.9");
@@ -10673,6 +10825,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
}
extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" );
extract_value( dizel_AIM, "AIM", Input, "1.25" );
extract_value( dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, "" );
break;
}
case TEngineType::ElectricInductionMotor: {
@@ -10757,6 +10910,8 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
// traction motors
extract_value( MotorBlowers[ end::front ].speed, "MotorBlowersSpeed", Input, "" );
extract_value( MotorBlowers[ end::front ].sustain_time, "MotorBlowersSustainTime", Input, "" );
extract_value( MotorBlowers[ end::front ].min_start_velocity, "MotorBlowersStartVelocity", Input, "" );
MotorBlowers[ end::rear ] = MotorBlowers[ end::front ];
// pressure switch
extract_value( HasControlPressureSwitch, "PressureSwitch", Input, ( TrainType != dt_EZT ? "yes" : "no" ) );
@@ -10775,6 +10930,14 @@ void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) {
extract_value( UniversalResetButtonFlag[ 0 ], "RelayResetButton1", Input, "" );
extract_value( UniversalResetButtonFlag[ 1 ], "RelayResetButton2", Input, "" );
extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" );
// pantograph presets
{
auto &presets { PantsPreset.first };
extract_value( presets, "PantographPresets", Input, "0|1|3|2" );
presets.erase(
std::remove( std::begin( presets ), std::end( presets ), '|' ),
std::end( presets ) );
}
}
void TMoverParameters::LoadFIZ_MotorParamTable( std::string const &Input ) {
@@ -11085,7 +11248,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
// WriteLog("aa = " + AxleArangement + " " + std::string( Pos("o", AxleArangement)) );
if( ( AxleArangement.find( "o" ) != std::string::npos ) && ( EngineType == TEngineType::ElectricSeriesMotor ) ) {
if( ( contains( AxleArangement, "o" ) ) && ( EngineType == TEngineType::ElectricSeriesMotor ) ) {
// test poprawnosci ilosci osi indywidualnie napedzanych
OK = ( ( RList[ 1 ].Bn * RList[ 1 ].Mn ) == NPoweredAxles );
// WriteLogSS("aa ok", BoolToYN(OK));
@@ -11405,9 +11568,6 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
BrakeDelay[b] = BrakeDelay[b] * (2.5 + Random(0.0, 0.2)) / 3.0;
}
if (TrainType == dt_ET22)
CompressorPower = 0;
Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag);
/*
ScndPipePress = Compressor;
@@ -11423,6 +11583,13 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
}
}
}
// security system
// by default place the magnet in the vehicle centre
if( SecuritySystem.MagnetLocation == 0 ) {
SecuritySystem.MagnetLocation = Dim.L / 2 - 0.5;
}
SecuritySystem.MagnetLocation = clamp( SecuritySystem.MagnetLocation, 0.0, Dim.L );
return OK;
}
@@ -11720,6 +11887,11 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
MainSwitch_( CValue1 > 0.0 );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "HeatingSwitch")
{
HeatingSwitch_( CValue1 > 0.0 );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "Direction")
{
DirActive = static_cast<int>(floor(CValue1));
@@ -11795,10 +11967,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
auto const right { 3 - left };
if( std::abs( static_cast<int>( CValue1 ) ) & right ) {
Doors.instances[ side::right ].open_permit = (CValue1 > 0);
PermitDoors_( side::right, ( CValue1 > 0 ) );
}
if( std::abs( static_cast<int>( CValue1 ) ) & left ) {
Doors.instances[ side::left ].open_permit = (CValue1 > 0);
PermitDoors_( side::left, ( CValue1 > 0 ) );
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
@@ -11902,10 +12074,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
DropAllPantographs( CValue1 == 1, range_t::local );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "MaxCurrentSwitch")
{
OK = MaxCurrentSwitch(CValue1 == 1);
}
else if (Command == "MaxCurrentSwitch") {
MaxCurrentSwitch( CValue1 == 1, range_t::local );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "MinCurrentSwitch")
{
OK = MinCurrentSwitch(CValue1 == 1);