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

main breaker readiness cab indicator, compressor preset switch enhancement, compressor logic cleanup, track end detection logic fix

This commit is contained in:
tmj-fstate
2019-12-28 02:38:07 +01:00
parent 943e05462d
commit ee1a80d7a8
6 changed files with 310 additions and 408 deletions

View File

@@ -746,7 +746,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
else if( sSpeedTable[ iLast ].trTrack == tLast ) { else if( sSpeedTable[ iLast ].trTrack == tLast ) {
// otherwise just mark the last added track as the final one // otherwise just mark the last added track as the final one
// TODO: investigate exactly how we can wind up not marking the last existing track as actual end // TODO: investigate exactly how we can wind up not marking the last existing track as actual end
sSpeedTable[ iLast ].iFlags |= spEnd; sSpeedTable[ iLast ].iFlags |= ( spEnabled | spEnd );
} }
// to ostatnia pozycja, bo NULL nic nie da, a może się podpiąć obrotnica, czy jakieś transportery // to ostatnia pozycja, bo NULL nic nie da, a może się podpiąć obrotnica, czy jakieś transportery
return; return;
@@ -1377,9 +1377,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} // jeśli nie ma zawalidrogi } // jeśli nie ma zawalidrogi
} // jeśli event } // jeśli event
if (v >= 0.0) { auto const railwaytrackend { ( true == TestFlag( sSpeedTable[ i ].iFlags, spEnd ) ) && ( mvOccupied->CategoryFlag & 1 ) };
if( ( v >= 0.0 )
|| ( railwaytrackend ) ) {
// pozycje z prędkością -1 można spokojnie pomijać // pozycje z prędkością -1 można spokojnie pomijać
d = sSpeedTable[i].fDist; d = sSpeedTable[i].fDist;
if( v >= 0.0 ) {
if( ( d > 0.0 ) if( ( d > 0.0 )
&& ( false == TestFlag( sSpeedTable[ i ].iFlags, spElapsed ) ) ) { && ( false == TestFlag( sSpeedTable[ i ].iFlags, spElapsed ) ) ) {
// sygnał lub ograniczenie z przodu (+32=przejechane) // sygnał lub ograniczenie z przodu (+32=przejechane)
@@ -1394,6 +1397,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} }
else { else {
// przyspieszenie: ujemne, gdy trzeba hamować // przyspieszenie: ujemne, gdy trzeba hamować
if( v >= 0.0 ) {
a = ( v * v - mvOccupied->Vel * mvOccupied->Vel ) / ( 25.92 * d ); a = ( v * v - mvOccupied->Vel * mvOccupied->Vel ) / ( 25.92 * d );
if( ( mvOccupied->Vel < v ) if( ( mvOccupied->Vel < v )
|| ( v == 0.0 ) ) { || ( v == 0.0 ) ) {
@@ -1411,32 +1415,47 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
fVelDes = v; fVelDes = v;
} }
} }
if( ( true == TestFlag( sSpeedTable[ i ].iFlags, spEnd ) )
&& ( mvOccupied->CategoryFlag & 1 ) ) {
// if the railway track ends here set the velnext accordingly as well
// TODO: test this with turntables and such
fNext = 0.0;
} }
} }
else if (sSpeedTable[i].iFlags & spTrack) // jeśli tor else if (sSpeedTable[i].iFlags & spTrack) // jeśli tor
{ // tor ogranicza prędkość, dopóki cały skład nie przejedzie, { // tor ogranicza prędkość, dopóki cały skład nie przejedzie,
// d=fLength+d; //zamiana na długość liczoną do przodu
if( v >= 1.0 ) // EU06 się zawieszało po dojechaniu na koniec toru postojowego if( v >= 1.0 ) // EU06 się zawieszało po dojechaniu na koniec toru postojowego
if( d + sSpeedTable[ i ].trTrack->Length() < -fLength ) if( d + sSpeedTable[ i ].trTrack->Length() < -fLength )
if( false == railwaytrackend )
continue; // zapętlenie, jeśli już wyjechał za ten odcinek continue; // zapętlenie, jeśli już wyjechał za ten odcinek
if( v < fVelDes ) { if( v < fVelDes ) {
// ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie // ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie
fVelDes = v; fVelDes = v;
} }
// if (v==0.0) fAcc=-0.9; //hamowanie jeśli stop if( false == railwaytrackend )
continue; // i tyle wystarczy continue; // i tyle wystarczy
} }
else // event trzyma tylko jeśli VelNext=0, nawet po przejechaniu (nie powinno dotyczyć samochodów?) else {
// event trzyma tylko jeśli VelNext=0, nawet po przejechaniu (nie powinno dotyczyć samochodów?)
a = (v > 0.0 ? a = (v > 0.0 ?
fAcc : fAcc :
mvOccupied->Vel < 0.01 ? mvOccupied->Vel < 0.01 ?
0.0 : // already standing still so no need to bother with brakes 0.0 : // already standing still so no need to bother with brakes
-2.0 ); // ruszanie albo hamowanie -2.0 ); // ruszanie albo hamowanie
}
}
// track can potentially end, which creates another virtual point of interest with speed limit of 0 at the end of it
// TBD, TODO: when tracing the route create a dedicated table entry for it, to simplify the code?
if( ( true == TestFlag( sSpeedTable[ i ].iFlags, spEnd ) )
&& ( mvOccupied->CategoryFlag & 1 ) ) {
// if the railway track ends here set the velnext accordingly as well
// TODO: test this with turntables and such
auto const stopatendacceleration = ( -1.0 * mvOccupied->Vel * mvOccupied->Vel ) / ( 25.92 * ( d + sSpeedTable[ i ].trTrack->Length() ) );
if( stopatendacceleration < a ) {
a = stopatendacceleration;
v = 0.0;
d += sSpeedTable[ i ].trTrack->Length();
if( d < fMinProximityDist ) {
// jak jest już blisko, ograniczenie aktualnej prędkości
fVelDes = v;
}
}
}
if ((a < fAcc) && (v == std::min(v, fNext))) { if ((a < fAcc) && (v == std::min(v, fNext))) {
// mniejsze przyspieszenie to mniejsza możliwość rozpędzenia się albo konieczność hamowania // mniejsze przyspieszenie to mniejsza możliwość rozpędzenia się albo konieczność hamowania
@@ -5455,7 +5474,7 @@ TController::UpdateSituation(double dt) {
ActualProximityDist, ActualProximityDist,
Obstacle.distance ); Obstacle.distance );
if( ActualProximityDist <= ( if( Obstacle.distance <= (
( mvOccupied->CategoryFlag & 2 ) ? ( mvOccupied->CategoryFlag & 2 ) ?
100.0 : // cars 100.0 : // cars
250.0 ) ) { // others 250.0 ) ) { // others

View File

@@ -1639,6 +1639,7 @@ public:
void MainSwitch_( bool const State ); void MainSwitch_( bool const State );
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/ bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/ bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
bool ChangeCompressorPreset( int const Change, range_t const Notify = range_t::consist );
/*-funkcje typowe dla lokomotywy elektrycznej*/ /*-funkcje typowe dla lokomotywy elektrycznej*/
void MainsCheck( double const Deltatime ); void MainsCheck( double const Deltatime );

View File

@@ -3186,74 +3186,68 @@ void TMoverParameters::MainSwitch_( bool const State ) {
// Q: 20160713 // Q: 20160713
// włączenie / wyłączenie przetwornicy // włączenie / wyłączenie przetwornicy
// ************************************************************************************************* // *************************************************************************************************
bool TMoverParameters::ConverterSwitch( bool State, range_t const Notify ) bool TMoverParameters::ConverterSwitch( bool State, range_t const Notify ) {
{
bool CS = false; // Ra: normalnie chyba false? auto const initialstate { ConverterAllow };
if (ConverterAllow != State)
{
ConverterAllow = State; ConverterAllow = State;
CS = true;
}
if( ConverterAllow == true ) {
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
SendCtrlToNext( SendCtrlToNext(
"ConverterSwitch", 1, CabActive, "ConverterSwitch",
( State ? 1 : 0 ),
CabActive,
( Notify == range_t::unit ? ( Notify == range_t::unit ?
ctrain_controll | ctrain_depot : coupling::control | coupling::permanent :
ctrain_controll ) ); coupling::control ) );
}
}
else {
if( Notify != range_t::local ) {
SendCtrlToNext(
"ConverterSwitch", 0, CabActive,
( Notify == range_t::unit ?
ctrain_controll | ctrain_depot :
ctrain_controll ) );
}
} }
return CS; return ( ConverterAllow != initialstate );
} }
// ************************************************************************************************* // *************************************************************************************************
// Q: 20160713 // Q: 20160713
// włączenie / wyłączenie sprężarki // włączenie / wyłączenie sprężarki
// ************************************************************************************************* // *************************************************************************************************
bool TMoverParameters::CompressorSwitch( bool State, range_t const Notify ) bool TMoverParameters::CompressorSwitch( bool State, range_t const Notify ) {
{
if( CompressorStart != start_t::manual ) { if( CompressorStart != start_t::manual ) {
// only pay attention if the compressor can be controlled manually // only pay attention if the compressor can be controlled manually
return false; return false;
} }
bool CS = false; // Ra: normalnie chyba tak? auto const initialstate { CompressorAllow };
if ( CompressorAllow != State )
{
CompressorAllow = State; CompressorAllow = State;
CS = true;
}
if( CompressorAllow == true ) {
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
SendCtrlToNext( SendCtrlToNext(
"CompressorSwitch", 1, CabActive, "CompressorSwitch",
( State ? 1 : 0 ),
CabActive,
( Notify == range_t::unit ? ( Notify == range_t::unit ?
ctrain_controll | ctrain_depot : coupling::control | coupling::permanent :
ctrain_controll ) ); coupling::control ) );
}
}
else {
if( Notify != range_t::local ) {
SendCtrlToNext(
"CompressorSwitch", 0, CabActive,
( Notify == range_t::unit ?
ctrain_controll | ctrain_depot :
ctrain_controll ) );
}
} }
return CS; return ( CompressorAllow != initialstate );
}
bool TMoverParameters::ChangeCompressorPreset( int const State, range_t const Notify ) {
auto const initialstate { CompressorListPos };
CompressorListPos = clamp( State, 0, CompressorListPosNo );
if( Notify != range_t::local ) {
SendCtrlToNext(
"CompressorPreset", State, CabActive,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return ( CompressorListPos != initialstate );
} }
// ************************************************************************************************* // *************************************************************************************************
@@ -3700,19 +3694,7 @@ void TMoverParameters::UpdateBrakePressure(double dt)
// Q: 20160712 // Q: 20160712
// Obliczanie pracy sprężarki // Obliczanie pracy sprężarki
// ************************************************************************************************* // *************************************************************************************************
// TODO: clean the method up, a lot of the code is redundant void TMoverParameters::CompressorCheck(double dt) {
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; } if( VeselVolume == 0.0 ) { return; }
@@ -3723,231 +3705,125 @@ void TMoverParameters::CompressorCheck(double dt)
CompressedVolume -= dV; CompressedVolume -= dV;
} }
CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s
if( ( true == CompressorGovernorLock ) // assorted operational logic
&& ( Compressor < MinCompressorF ) ) { auto const MaxCompressorF { CompressorList[ TCompressorList::cl_MaxFactor ][ CompressorListPos ] * MaxCompressor };
// if the pressure drops below the cut-in level, we can reset compressor governor auto const MinCompressorF { CompressorList[ TCompressorList::cl_MinFactor ][ CompressorListPos ] * MinCompressor };
// TBD, TODO: don't operate the lock without battery power? auto const CompressorSpeedF { CompressorList[ TCompressorList::cl_SpeedFactor ][ CompressorListPos ] * CompressorSpeed };
CompressorGovernorLock = false; auto const AllowFactor { CompressorList[ TCompressorList::cl_Allow ][ CompressorListPos ] };
//checking the impact on the compressor allowance
if (AllowFactor > 0.5) {
CompressorAllow = ( AllowFactor > 1.5 );
} }
if( CompressorPower == 2 ) { switch( CompressorPower ) {
case 2: {
CompressorAllow = ConverterAllow; CompressorAllow = ConverterAllow;
break;
} }
// TODO: clean up compressor CompressorFlag state code, large parts are cloned and an utter mess case 3: {
if (MaxCompressorF - MinCompressorF < 0.0001) { // HACK: make sure compressor coupled with diesel engine is always ready for work
// 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 < MaxCompressorF ) {
if( ( EngineType == TEngineType::DieselElectric )
&& ( CompressorPower > 0 ) ) {
CompressedVolume +=
CompressorSpeedF
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
* ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM )
* dt;
}
else {
CompressedVolume +=
CompressorSpeedF
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
* dt;
TotalCurrent += 0.0015 * PantographVoltage; // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
}
}
else {
CompressedVolume = CompressedVolume * 0.8;
SetFlag(SoundFlag, sound::relay | sound::loud);
}
}
}
else {
if( CompressorPower == 3 ) {
// experimental: make sure compressor coupled with diesel engine is always ready for work
CompressorStart = start_t::automatic; CompressorStart = start_t::automatic;
break;
} }
if (CompressorFlag) // jeśli sprężarka załączona default: {
{ // sprawdzić możliwe warunki wyłączenia sprężarki break;
if (CompressorPower == 5) // jeśli zasilanie z sąsiedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = (
( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ end::rear ].Connected->ConverterFlag ) );
}
else {
// bez tamtego członu nie zadziała
CompressorFlag = false;
} }
} }
else if (CompressorPower == 4) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) auto *compressorowner { (
if( Couplers[ end::front ].Connected != NULL ) { CompressorPower == 4 ? Couplers[ end::front ].Connected :
CompressorFlag = ( CompressorPower == 5 ? Couplers[ end::rear ].Connected :
( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) this ) };
&& ( CompressorAllowLocal ) auto const compressorpower { (
&& ( Couplers[ end::front ].Connected->ConverterFlag ) ); CompressorPower == 0 ? Mains :
}
else {
CompressorFlag = false; // bez tamtego członu nie zadziała
}
}
else
CompressorFlag = (
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( CompressorPower == 0 ? Mains :
CompressorPower == 3 ? Mains : CompressorPower == 3 ? Mains :
ConverterFlag ) ); ( compressorowner != nullptr ) && ( compressorowner->ConverterFlag ) ) };
auto const compressorallow {
( CompressorAllowLocal )
&& ( ( CompressorStart == start_t::automatic )
|| ( ( compressorowner != nullptr ) && ( compressorowner->CompressorAllow ) ) ) };
if( Compressor > MaxCompressorF ) { auto const pressureistoolow { Compressor < MinCompressorF };
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania auto const pressureistoohigh { Compressor > MaxCompressorF };
// TBD, TODO: don't operate the lock without battery power?
if( CompressorPower == 3 ) {
// if the compressor is powered directly by the engine the lock can't turn it off and instead just changes the output
if( false == CompressorGovernorLock ) {
// emit relay sound when the lock engages (the state change itself is below) and presumably changes where the air goes
SetFlag( SoundFlag, sound::relay | sound::loud );
}
}
else {
// if the compressor isn't coupled with the engine the lock can control its state freely
CompressorFlag = false;
}
CompressorGovernorLock = true; // prevent manual activation until the pressure goes below cut-in level
}
if( ( TrainType == dt_ET41 ) // TBD, TODO: break the lock with no low voltage power?
|| ( TrainType == dt_ET42 ) ) { auto const governorlockispresent { MaxCompressorF - MinCompressorF > 0.0001 };
CompressorGovernorLock =
( governorlockispresent )
&& ( false == pressureistoolow ) // unlock if pressure drops below minimal threshold
&& ( pressureistoohigh || CompressorGovernorLock ); // lock if pressure goes above maximum threshold
// for these multi-unit engines compressors turn off whenever any of them was affected by the governor // for these multi-unit engines compressors turn off whenever any of them was affected by the governor
// NOTE: this is crude implementation, TODO: re-implement when a more elegant/flexible system is in place // NOTE: this is crude implementation, limited only to adjacent vehicles
if( ( Couplers[ 1 ].Connected != nullptr ) // TODO: re-implement when a more elegant/flexible system is in place
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) { auto const coupledgovernorlock {
// the first unit isn't allowed to start its compressor until second unit can start its own as well ( ( Couplers[ end::rear ].Connected != nullptr )
CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false ); && ( true == TestFlag( Couplers[ end::rear ].CouplingFlag, coupling::permanent ) )
} && ( Couplers[ end::rear ].Connected->CompressorGovernorLock ) )
if( ( Couplers[ 0 ].Connected != nullptr ) || ( ( Couplers[ end::front ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) { && ( true == TestFlag( Couplers[ end::front ].CouplingFlag, coupling::permanent ) )
// the second unit isn't allowed to start its compressor until first unit can start its own as well && ( Couplers[ end::front ].Connected->CompressorGovernorLock ) ) };
CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false ); auto const governorlock { CompressorGovernorLock || coupledgovernorlock };
}
} auto const compressorflag { CompressorFlag };
} CompressorFlag =
else { ( compressorpower )
// jeśli nie załączona && ( ( false == governorlock ) || ( CompressorPower == 3 ) )
if( ( LastSwitchingTime > CtrlDelay ) && ( ( CompressorFlag )
&& ( ( Compressor < MinCompressorF ) || ( ( compressorallow ) && ( LastSwitchingTime > CtrlDelay ) ) );
|| ( ( Compressor < MaxCompressorF )
&& ( false == CompressorGovernorLock ) ) ) ) { if( ( CompressorFlag ) && ( CompressorFlag != compressorflag ) ) {
// załączenie przy małym ciśnieniu // jeśli została załączona to trzeba ograniczyć ponowne włączenie
// jeśli nie załączona, a ciśnienie za małe LastSwitchingTime = 0;
// or if the switch is on and the pressure isn't maxed
if( CompressorPower == 5 ) // jeśli zasilanie z następnego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = (
( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ end::rear ].Connected->ConverterFlag ) );
}
else {
// bez tamtego członu nie zadziała
CompressorFlag = false;
}
}
else if( CompressorPower == 4 ) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ end::front ].Connected != NULL ) {
CompressorFlag = (
( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ end::front ].Connected->ConverterFlag ) );
}
else {
CompressorFlag = false; // bez tamtego członu nie zadziała
}
}
else {
CompressorFlag = (
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( CompressorPower == 0 ? Mains :
CompressorPower == 3 ? Mains :
ConverterFlag ) );
} }
// NOTE: crude way to enforce simultaneous activation of compressors in multi-unit setups if( false == CompressorFlag ) { return; }
// TODO: replace this with a more universal activation system down the road
if( ( TrainType == dt_ET41 )
|| ( TrainType == dt_ET42 ) ) {
if( ( Couplers[1].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
// the first unit isn't allowed to start its compressor until second unit can start its own as well
CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false );
}
if( ( Couplers[ 0 ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
// the second unit isn't allowed to start its compressor until first unit can start its own as well
CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false );
}
}
if( CompressorFlag ) {
// jeśli została załączona
LastSwitchingTime = 0; // to trzeba ograniczyć ponowne włączenie
}
}
}
if( CompressorFlag ) {
// working compressor adds air to the air reservoir // working compressor adds air to the air reservoir
if( CompressorPower == 3 ) { switch( CompressorPower ) {
case 3: {
// the compressor is coupled with the diesel engine, engine revolutions affect the output // the compressor is coupled with the diesel engine, engine revolutions affect the output
if( false == CompressorGovernorLock ) {
auto const enginefactor { ( auto const enginefactor { (
EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) : EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) :
EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) : EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) :
1.0 ) }; // shouldn't ever get here but, eh 1.0 ) }; // shouldn't ever get here but, eh
CompressedVolume += CompressedVolume +=
CompressorSpeed CompressorSpeedF
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
* enginefactor * enginefactor
* dt; * dt;
break;
} }
/* default: {
else {
// the lock is active, air is being vented out at arbitrary rate
CompressedVolume -= 0.01 * dt;
}
*/
}
else {
// the compressor is a stand-alone device, working at steady pace // the compressor is a stand-alone device, working at steady pace
CompressedVolume += CompressedVolume +=
CompressorSpeedF CompressorSpeedF
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
* dt; * dt;
break;
}
}
if( ( pressureistoohigh )
&& ( false == governorlockispresent ) ) {
// vent some air out if there's no governor lock to stop the compressor from exceeding acceptable pressure level
SetFlag( SoundFlag, sound::relay | sound::loud );
CompressedVolume *= 0.8;
}
if( ( CompressorPower == 5 ) && ( Couplers[ 1 ].Connected != NULL ) ) {
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
Couplers[ 1 ].Connected->TotalCurrent += 0.0015 * Couplers[ 1 ].Connected->PantographVoltage; // TODO: draw power from proper high- or low voltage circuit
} switch( CompressorPower ) {
else if( ( CompressorPower == 4 ) && ( Couplers[ 0 ].Connected != NULL ) ) { case 3: {
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę // diesel-powered compressor doesn't draw power
Couplers[ 0 ].Connected->TotalCurrent += 0.0015 * Couplers[ 0 ].Connected->PantographVoltage; break;
}
else {
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
TotalCurrent += 0.0015 * PantographVoltage;
} }
default: {
if( compressorowner != nullptr ) {
compressorowner->TotalCurrent += 0.0015 * compressorowner->PantographVoltage;
} }
break;
} }
} }
} }
@@ -11090,6 +10966,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "CompressorPreset" ) {
CompressorListPos = clamp( static_cast<int>( CValue1 ), 0, CompressorListPosNo );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "DoorPermit") { else if (Command == "DoorPermit") {
auto const left { CValue2 > 0 ? 1 : 2 }; auto const left { CValue2 > 0 ? 1 : 2 };

View File

@@ -3079,9 +3079,7 @@ void TTrain::OnCommand_compressorenable( TTrain *Train, command_data const &Comm
void TTrain::OnCommand_compressordisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_compressordisable( TTrain *Train, command_data const &Command ) {
if( Train->mvControlled->CompressorPower >= 2 ) { if( Train->mvControlled->CompressorPower >= 2 ) { return; }
return;
}
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// visual feedback // visual feedback
@@ -3103,12 +3101,8 @@ void TTrain::OnCommand_compressordisable( TTrain *Train, command_data const &Com
void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command ) {
if( Train->mvOccupied->CompressorPower >= 2 ) { if( Train->mvOccupied->CompressorPower >= 2 ) { return; }
return; if( Train->ggCompressorLocalButton.SubModel == nullptr ) { return; }
}
if( Train->ggCompressorLocalButton.SubModel == nullptr ) {
return;
}
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
@@ -3131,25 +3125,32 @@ void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const
void TTrain::OnCommand_compressorpresetactivatenext(TTrain *Train, command_data const &Command) { void TTrain::OnCommand_compressorpresetactivatenext(TTrain *Train, command_data const &Command) {
if (Train->mvOccupied->CompressorListPosNo == 0) { if (Train->mvOccupied->CompressorListPosNo == 0) { return; }
// lights are controlled by preset selector if( Command.action == GLFW_REPEAT ) { return; }
return;
} if( Train->ggCompressorListButton.type() == TGaugeType::push ) {
if (Command.action != GLFW_PRESS) { // impulse switch
// one change per key press if( Train->mvOccupied->CompressorListPosNo < Train->mvOccupied->CompressorListDefPos + 1 ) { return; }
return;
Train->mvOccupied->ChangeCompressorPreset( (
Command.action == GLFW_PRESS ?
Train->mvOccupied->CompressorListDefPos + 1 :
Train->mvOccupied->CompressorListDefPos ) );
// visual feedback
Train->ggCompressorListButton.UpdateValue( Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch );
} }
else {
// multi-state switch
if( Command.action == GLFW_RELEASE ) { return; }
if( ( Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ) if( ( Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo )
|| ( true == Train->mvOccupied->CompressorListWrap ) ) { || ( true == Train->mvOccupied->CompressorListWrap ) ) {
// active light preset is stored as value in range 1-LigthPosNo // active light preset is stored as value in range 1-LigthPosNo
Train->mvOccupied->CompressorListPos = ( Train->mvOccupied->ChangeCompressorPreset( (
Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ? Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ?
Train->mvOccupied->CompressorListPos + 1 : Train->mvOccupied->CompressorListPos + 1 :
1); // wrap mode 1 ) ); // wrap mode
// visual feedback // visual feedback
if (Train->ggCompressorListButton.SubModel != nullptr) {
Train->ggCompressorListButton.UpdateValue( Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch ); Train->ggCompressorListButton.UpdateValue( Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch );
} }
} }
@@ -3157,22 +3158,21 @@ void TTrain::OnCommand_compressorpresetactivatenext(TTrain *Train, command_data
void TTrain::OnCommand_compressorpresetactivateprevious(TTrain *Train, command_data const &Command) { void TTrain::OnCommand_compressorpresetactivateprevious(TTrain *Train, command_data const &Command) {
if (Train->mvOccupied->CompressorListPosNo == 0) { if (Train->mvOccupied->CompressorListPosNo == 0) { return; }
// lights are controlled by preset selector if (Command.action != GLFW_PRESS) { return; } // one change per key press
return;
} if( Train->ggCompressorListButton.type() == TGaugeType::push ) {
if (Command.action != GLFW_PRESS) { // impulse switch toggles only between positions 'default' and 'default+1'
// one change per key press
return; return;
} }
if ((Train->mvOccupied->CompressorListPos > 1) if ((Train->mvOccupied->CompressorListPos > 1)
|| (true == Train->mvOccupied->CompressorListWrap)) { || (true == Train->mvOccupied->CompressorListWrap)) {
// active light preset is stored as value in range 1-LigthPosNo // active light preset is stored as value in range 1-LigthPosNo
Train->mvOccupied->CompressorListPos = ( Train->mvOccupied->ChangeCompressorPreset( (
Train->mvOccupied->CompressorListPos > 1 ? Train->mvOccupied->CompressorListPos > 1 ?
Train->mvOccupied->CompressorListPos - 1 : Train->mvOccupied->CompressorListPos - 1 :
Train->mvOccupied->CompressorListPosNo); // wrap mode Train->mvOccupied->CompressorListPosNo) ); // wrap mode
// visual feedback // visual feedback
if (Train->ggCompressorListButton.SubModel != nullptr) { if (Train->ggCompressorListButton.SubModel != nullptr) {
@@ -3183,16 +3183,10 @@ void TTrain::OnCommand_compressorpresetactivateprevious(TTrain *Train, command_d
void TTrain::OnCommand_compressorpresetactivatedefault(TTrain *Train, command_data const &Command) { void TTrain::OnCommand_compressorpresetactivatedefault(TTrain *Train, command_data const &Command) {
if (Train->mvOccupied->CompressorListPosNo == 0) { if (Train->mvOccupied->CompressorListPosNo == 0) { return; }
// lights are controlled by preset selector if (Command.action != GLFW_PRESS) { return; } // one change per key press
return;
}
if (Command.action != GLFW_PRESS) {
// one change per key press
return;
}
Train->mvOccupied->CompressorListPos = Train->mvOccupied->CompressorListDefPos; Train->mvOccupied->ChangeCompressorPreset( Train->mvOccupied->CompressorListDefPos );
// visual feedback // visual feedback
if (Train->ggCompressorListButton.SubModel != nullptr) { if (Train->ggCompressorListButton.SubModel != nullptr) {
@@ -6166,8 +6160,12 @@ bool TTrain::Update( double const Deltatime )
true : true :
false ) ); false ) );
btLampkaWylSzybkiOff.Turn( btLampkaWylSzybkiOff.Turn(
( ( ( m_linebreakerstate == 2 )
|| ( true == mvControlled->Mains ) ) ?
false :
true ) );
btLampkaMainBreakerReady.Turn(
( ( ( mvControlled->MainsInitTimeCountdown > 0.0 ) ( ( ( mvControlled->MainsInitTimeCountdown > 0.0 )
// || ( fHVoltage == 0.0 )
|| ( m_linebreakerstate == 2 ) || ( m_linebreakerstate == 2 )
|| ( true == mvControlled->Mains ) ) ? || ( true == mvControlled->Mains ) ) ?
false : false :
@@ -6328,6 +6326,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaSHP.Turn( false ); btLampkaSHP.Turn( false );
btLampkaWylSzybki.Turn( false ); btLampkaWylSzybki.Turn( false );
btLampkaWylSzybkiOff.Turn( false ); btLampkaWylSzybkiOff.Turn( false );
btLampkaMainBreakerReady.Turn( false );
btLampkaWysRozr.Turn( false ); btLampkaWysRozr.Turn( false );
btLampkaOpory.Turn( false ); btLampkaOpory.Turn( false );
btLampkaStyczn.Turn( false ); btLampkaStyczn.Turn( false );
@@ -6406,7 +6405,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaWylSzybkiB.Turn( mover->Mains ); btLampkaWylSzybkiB.Turn( mover->Mains );
btLampkaWylSzybkiBOff.Turn( btLampkaWylSzybkiBOff.Turn(
( false == mover->Mains ) ( false == mover->Mains )
&& ( mover->MainsInitTimeCountdown <= 0.0 ) /*&& ( mover->MainsInitTimeCountdown <= 0.0 )*/
/*&& ( fHVoltage != 0.0 )*/ ); /*&& ( fHVoltage != 0.0 )*/ );
btLampkaOporyB.Turn( mover->ResistorsFlagCheck() ); btLampkaOporyB.Turn( mover->ResistorsFlagCheck() );
@@ -8024,6 +8023,7 @@ void TTrain::clear_cab_controls()
btLampkaWylSzybkiOff.Clear(); btLampkaWylSzybkiOff.Clear();
btLampkaWylSzybkiB.Clear(); btLampkaWylSzybkiB.Clear();
btLampkaWylSzybkiBOff.Clear(); btLampkaWylSzybkiBOff.Clear();
btLampkaMainBreakerReady.Clear();
btLampkaBezoporowa.Clear(); btLampkaBezoporowa.Clear();
btLampkaBezoporowaB.Clear(); btLampkaBezoporowaB.Clear();
btLampkaMaxSila.Clear(); btLampkaMaxSila.Clear();
@@ -8445,6 +8445,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-mainbreakerb:", btLampkaWylSzybkiB }, { "i-mainbreakerb:", btLampkaWylSzybkiB },
{ "i-mainbreakeroff:", btLampkaWylSzybkiOff }, { "i-mainbreakeroff:", btLampkaWylSzybkiOff },
{ "i-mainbreakerboff:", btLampkaWylSzybkiBOff }, { "i-mainbreakerboff:", btLampkaWylSzybkiBOff },
{ "i-mainbreakerready:", btLampkaMainBreakerReady },
{ "i-vent_ovld:", btLampkaNadmWent }, { "i-vent_ovld:", btLampkaNadmWent },
{ "i-comp_ovld:", btLampkaNadmSpr }, { "i-comp_ovld:", btLampkaNadmSpr },
{ "i-resistors:", btLampkaOpory }, { "i-resistors:", btLampkaOpory },

View File

@@ -566,6 +566,7 @@ public: // reszta może by?publiczna
TButton btLampkaNadmSil; TButton btLampkaNadmSil;
TButton btLampkaWylSzybki; TButton btLampkaWylSzybki;
TButton btLampkaWylSzybkiOff; TButton btLampkaWylSzybkiOff;
TButton btLampkaMainBreakerReady;
TButton btLampkaNadmWent; TButton btLampkaNadmWent;
TButton btLampkaNadmSpr; // TODO: implement TButton btLampkaNadmSpr; // TODO: implement
// yB: drugie lampki dla EP05 i ET42 // yB: drugie lampki dla EP05 i ET42

View File

@@ -4,7 +4,7 @@ namespace colors {
glm::vec4 const none{ 0.f, 0.f, 0.f, 1.f }; glm::vec4 const none{ 0.f, 0.f, 0.f, 1.f };
glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f }; glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f };
glm::vec4 const shadow{ 0.6f, 0.6f, 0.6f, 1.f }; glm::vec4 const shadow{ 0.35f, 0.40f, 0.45f, 1.f };
inline inline
glm::vec3 glm::vec3