mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 12:09: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:
179
Driver.cpp
179
Driver.cpp
@@ -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;
|
||||||
@@ -919,25 +919,25 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
Drugi parametr ujemny - wskazanie zatrzymania dla krótszych składów (W32).
|
Drugi parametr ujemny - wskazanie zatrzymania dla krótszych składów (W32).
|
||||||
Drugi paramer dodatni - długość peronu (W4).
|
Drugi paramer dodatni - długość peronu (W4).
|
||||||
*/
|
*/
|
||||||
auto L = 0.0;
|
auto L = 0.0;
|
||||||
auto Par1 = sSpeedTable[i].evEvent->input_value(1);
|
auto Par1 = sSpeedTable[i].evEvent->input_value(1);
|
||||||
auto Par2 = sSpeedTable[i].evEvent->input_value(2);
|
auto Par2 = sSpeedTable[i].evEvent->input_value(2);
|
||||||
if ((Par2 >= 0) || (fLength < -Par2)) { //użyj tego W4
|
if ((Par2 >= 0) || (fLength < -Par2)) { //użyj tego W4
|
||||||
if (Par1 < 0) {
|
if (Par1 < 0) {
|
||||||
L = -Par1;
|
L = -Par1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//środek
|
//środek
|
||||||
L = Par1 - fMinProximityDist - fLength * 0.5;
|
L = Par1 - fMinProximityDist - fLength * 0.5;
|
||||||
}
|
}
|
||||||
L = std::max(0.0, std::min(L, std::abs(Par2) - fMinProximityDist - fLength));
|
L = std::max(0.0, std::min(L, std::abs(Par2) - fMinProximityDist - fLength));
|
||||||
sSpeedTable[i].UpdateDistance(L);
|
sSpeedTable[i].UpdateDistance(L);
|
||||||
sSpeedTable[i].bMoved = true;
|
sSpeedTable[i].bMoved = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sSpeedTable[i].iFlags = 0;
|
sSpeedTable[i].iFlags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IsAtPassengerStop = (
|
IsAtPassengerStop = (
|
||||||
( sSpeedTable[ i ].fDist <= passengerstopmaxdistance )
|
( sSpeedTable[ i ].fDist <= passengerstopmaxdistance )
|
||||||
// Ra 2F1I: odległość plus długość pociągu musi być mniejsza od długości
|
// Ra 2F1I: odległość plus długość pociągu musi być mniejsza od długości
|
||||||
@@ -946,9 +946,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
// przyjąć odległość fMinProximityDist
|
// przyjąć odległość fMinProximityDist
|
||||||
&& ( ( iDrivigFlags & moveStopCloser ) != 0 ?
|
&& ( ( iDrivigFlags & moveStopCloser ) != 0 ?
|
||||||
sSpeedTable[ i ].fDist + fLength <=
|
sSpeedTable[ i ].fDist + fLength <=
|
||||||
std::max(
|
std::max(
|
||||||
std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ),
|
std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ),
|
||||||
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
|
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
|
||||||
sSpeedTable[ i ].fDist < d_to_next_sem ) );
|
sSpeedTable[ i ].fDist < d_to_next_sem ) );
|
||||||
|
|
||||||
if( !eSignNext ) {
|
if( !eSignNext ) {
|
||||||
@@ -959,12 +959,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
||||||
sSpeedTable[ i ].fVelNext = 0;
|
sSpeedTable[ i ].fVelNext = 0;
|
||||||
} else if( true == IsAtPassengerStop ) {
|
} else if( true == IsAtPassengerStop ) {
|
||||||
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
||||||
if( !AIControllFlag ) {
|
if( !AIControllFlag ) {
|
||||||
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
|
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
|
||||||
iDrivigFlags &= ~moveStopCloser;
|
iDrivigFlags &= ~moveStopCloser;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
|
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
|
||||||
// drzwi otwierać jednorazowo
|
// drzwi otwierać jednorazowo
|
||||||
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
||||||
@@ -1032,8 +1032,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if ( ( true == IsCargoTrain )
|
if ( ( true == IsCargoTrain )
|
||||||
|| ( true == TrainParams.IsMaintenance() )
|
|| ( true == TrainParams.IsMaintenance() )
|
||||||
|| ( TrainParams.IsTimeToGo( simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 ) ) ) {
|
|| ( TrainParams.IsTimeToGo( simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 ) ) ) {
|
||||||
// z dalszą akcją czekamy do godziny odjazdu
|
// z dalszą akcją czekamy do godziny odjazdu
|
||||||
// cargo trains and passenger trains at maintenance stop don't need to wait
|
// cargo trains and passenger trains at maintenance stop don't need to wait
|
||||||
IsAtPassengerStop = false;
|
IsAtPassengerStop = false;
|
||||||
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
||||||
fLastStopExpDist = mvOccupied->DistCounter + 0.050 + 0.001 * fLength;
|
fLastStopExpDist = mvOccupied->DistCounter + 0.050 + 0.001 * fLength;
|
||||||
@@ -1166,8 +1166,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( ( SemNextStopIndex == -1 )
|
if( ( SemNextStopIndex == -1 )
|
||||||
|| ( ( sSpeedTable[ SemNextStopIndex ].fVelNext != 0 )
|
|| ( ( sSpeedTable[ SemNextStopIndex ].fVelNext != 0 )
|
||||||
&& ( sSpeedTable[ i ].fVelNext == 0 ) ) ) {
|
&& ( sSpeedTable[ i ].fVelNext == 0 ) ) ) {
|
||||||
SemNextStopIndex = i;
|
SemNextStopIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1199,9 +1199,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( mvOccupied->Vel < 2.0 ) {
|
if( mvOccupied->Vel < 2.0 ) {
|
||||||
// stanąć nie musi, ale zwolnić przynajmniej
|
// stanąć nie musi, ale zwolnić przynajmniej
|
||||||
if( ( sSpeedTable[ i ].fDist < fMaxProximityDist )
|
if( ( sSpeedTable[ i ].fDist < fMaxProximityDist )
|
||||||
&& ( Obstacle.distance > 1000 ) ) {
|
&& ( Obstacle.distance > 1000 ) ) {
|
||||||
// jest w maksymalnym zasięgu to można go pominąć (wziąć drugą prędkosć)
|
// jest w maksymalnym zasięgu to można go pominąć (wziąć drugą prędkosć)
|
||||||
// as long as there isn't any obstacle in arbitrary view range
|
// as long as there isn't any obstacle in arbitrary view range
|
||||||
eSignSkip = sSpeedTable[ i ].evEvent;
|
eSignSkip = sSpeedTable[ i ].evEvent;
|
||||||
// jazda na widoczność - skanować możliwość kolizji i nie podjeżdżać zbyt blisko
|
// jazda na widoczność - skanować możliwość kolizji i nie podjeżdżać zbyt blisko
|
||||||
// usunąć flagę po podjechaniu blisko semafora zezwalającego na jazdę
|
// usunąć flagę po podjechaniu blisko semafora zezwalającego na jazdę
|
||||||
@@ -1285,8 +1285,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
|
|
||||||
//sprawdzenie eventów pasywnych przed nami
|
//sprawdzenie eventów pasywnych przed nami
|
||||||
if( ( mvOccupied->CategoryFlag & 1 )
|
if( ( mvOccupied->CategoryFlag & 1 )
|
||||||
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
|
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
|
||||||
// jak sygnał jest dalej niż zawalidroga
|
// jak sygnał jest dalej niż zawalidroga
|
||||||
v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był
|
v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1318,7 +1318,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( sSpeedTable[ i ].fDist < 0.0 ) {
|
if( sSpeedTable[ i ].fDist < 0.0 ) {
|
||||||
// jeśli przejechany
|
// jeśli przejechany
|
||||||
//!!! ustawienie, gdy przejechany jest lepsze niż wcale, ale to jeszcze nie to
|
//!!! ustawienie, gdy przejechany jest lepsze niż wcale, ale to jeszcze nie to
|
||||||
VelSignal = v;
|
VelSignal = v;
|
||||||
// to można usunąć (nie mogą być usuwane w skanowaniu)
|
// to można usunąć (nie mogą być usuwane w skanowaniu)
|
||||||
sSpeedTable[ i ].iFlags = 0;
|
sSpeedTable[ i ].iFlags = 0;
|
||||||
}
|
}
|
||||||
@@ -1330,8 +1330,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( go == TCommandType::cm_Unknown ) {
|
if( go == TCommandType::cm_Unknown ) {
|
||||||
// jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal
|
// jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal
|
||||||
if( ( v < 0.0 )
|
if( ( v < 0.0 )
|
||||||
|| ( v >= 1.0 ) ) {
|
|| ( v >= 1.0 ) ) {
|
||||||
// bo wartość 0.1 służy do hamowania tylko
|
// bo wartość 0.1 służy do hamowania tylko
|
||||||
go = TCommandType::cm_SetVelocity; // może odjechać
|
go = TCommandType::cm_SetVelocity; // może odjechać
|
||||||
// Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko
|
// Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko
|
||||||
// VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać...
|
// VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać...
|
||||||
@@ -1346,9 +1346,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( sSpeedTable[ i ].iFlags & spEvent ) {
|
if( sSpeedTable[ i ].iFlags & spEvent ) {
|
||||||
// jeśli event
|
// jeśli event
|
||||||
if( ( sSpeedTable[ i ].evEvent != eSignSkip )
|
if( ( sSpeedTable[ i ].evEvent != eSignSkip )
|
||||||
|| ( sSpeedTable[ i ].fVelNext != VelRestricted ) ) {
|
|| ( sSpeedTable[ i ].fVelNext != VelRestricted ) ) {
|
||||||
// ale inny niż ten, na którym minięto S1, chyba że się już zmieniło
|
// ale inny niż ten, na którym minięto S1, chyba że się już zmieniło
|
||||||
// sygnał zezwalający na jazdę wyłącza jazdę na widoczność (po S1 na SBL)
|
// sygnał zezwalający na jazdę wyłącza jazdę na widoczność (po S1 na SBL)
|
||||||
iDrivigFlags &= ~moveVisibility;
|
iDrivigFlags &= ~moveVisibility;
|
||||||
// remove restricted speed
|
// remove restricted speed
|
||||||
VelRestricted = -1.0;
|
VelRestricted = -1.0;
|
||||||
@@ -1377,66 +1377,85 @@ 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( ( d > 0.0 )
|
if( v >= 0.0 ) {
|
||||||
&& ( false == TestFlag( sSpeedTable[ i ].iFlags, spElapsed ) ) ) {
|
if( ( d > 0.0 )
|
||||||
// sygnał lub ograniczenie z przodu (+32=przejechane)
|
&& ( false == TestFlag( sSpeedTable[ i ].iFlags, spElapsed ) ) ) {
|
||||||
// 2014-02: jeśli stoi, a ma do przejechania kawałek, to niech jedzie
|
// sygnał lub ograniczenie z przodu (+32=przejechane)
|
||||||
if( ( mvOccupied->Vel < 0.01 )
|
// 2014-02: jeśli stoi, a ma do przejechania kawałek, to niech jedzie
|
||||||
&& ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) )
|
if( ( mvOccupied->Vel < 0.01 )
|
||||||
&& ( false == IsAtPassengerStop ) ) {
|
&& ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) )
|
||||||
// ma podjechać bliżej - czy na pewno w tym miejscu taki warunek?
|
&& ( false == IsAtPassengerStop ) ) {
|
||||||
a = ( ( d > passengerstopmaxdistance ) || ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
|
// ma podjechać bliżej - czy na pewno w tym miejscu taki warunek?
|
||||||
fAcc :
|
a = ( ( d > passengerstopmaxdistance ) || ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
|
||||||
0.0 );
|
fAcc :
|
||||||
}
|
0.0 );
|
||||||
else {
|
}
|
||||||
// przyspieszenie: ujemne, gdy trzeba hamować
|
else {
|
||||||
a = ( v * v - mvOccupied->Vel * mvOccupied->Vel ) / ( 25.92 * d );
|
// przyspieszenie: ujemne, gdy trzeba hamować
|
||||||
if( ( mvOccupied->Vel < v )
|
if( v >= 0.0 ) {
|
||||||
|| ( v == 0.0 ) ) {
|
a = ( v * v - mvOccupied->Vel * mvOccupied->Vel ) / ( 25.92 * d );
|
||||||
// if we're going slower than the target velocity and there's enough room for safe stop, speed up
|
if( ( mvOccupied->Vel < v )
|
||||||
auto const brakingdistance { 1.2 * fBrakeDist * braking_distance_multiplier( v ) };
|
|| ( v == 0.0 ) ) {
|
||||||
if( brakingdistance > 0.0 ) {
|
// if we're going slower than the target velocity and there's enough room for safe stop, speed up
|
||||||
// maintain desired acc while we have enough room to brake safely, when close enough start paying attention
|
auto const brakingdistance { 1.2 * fBrakeDist * braking_distance_multiplier( v ) };
|
||||||
// try to make a smooth transition instead of sharp change
|
if( brakingdistance > 0.0 ) {
|
||||||
a = interpolate( a, AccPreferred, clamp( ( d - brakingdistance ) / brakingdistance, 0.0, 1.0 ) );
|
// maintain desired acc while we have enough room to brake safely, when close enough start paying attention
|
||||||
|
// try to make a smooth transition instead of sharp change
|
||||||
|
a = interpolate( a, AccPreferred, clamp( ( d - brakingdistance ) / brakingdistance, 0.0, 1.0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( d < fMinProximityDist )
|
||||||
|
&& ( v < fVelDes ) ) {
|
||||||
|
// jak jest już blisko, ograniczenie aktualnej prędkości
|
||||||
|
fVelDes = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( ( d < fMinProximityDist )
|
}
|
||||||
&& ( v < fVelDes ) ) {
|
else if (sSpeedTable[i].iFlags & spTrack) // jeśli tor
|
||||||
|
{ // tor ogranicza prędkość, dopóki cały skład nie przejedzie,
|
||||||
|
if( v >= 1.0 ) // EU06 się zawieszało po dojechaniu na koniec toru postojowego
|
||||||
|
if( d + sSpeedTable[ i ].trTrack->Length() < -fLength )
|
||||||
|
if( false == railwaytrackend )
|
||||||
|
continue; // zapętlenie, jeśli już wyjechał za ten odcinek
|
||||||
|
if( v < fVelDes ) {
|
||||||
|
// ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie
|
||||||
|
fVelDes = v;
|
||||||
|
}
|
||||||
|
if( false == railwaytrackend )
|
||||||
|
continue; // i tyle wystarczy
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// event trzyma tylko jeśli VelNext=0, nawet po przejechaniu (nie powinno dotyczyć samochodów?)
|
||||||
|
a = (v > 0.0 ?
|
||||||
|
fAcc :
|
||||||
|
mvOccupied->Vel < 0.01 ?
|
||||||
|
0.0 : // already standing still so no need to bother with brakes
|
||||||
|
-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
|
// jak jest już blisko, ograniczenie aktualnej prędkości
|
||||||
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
|
|
||||||
{ // 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( d + sSpeedTable[ i ].trTrack->Length() < -fLength )
|
|
||||||
continue; // zapętlenie, jeśli już wyjechał za ten odcinek
|
|
||||||
if( v < fVelDes ) {
|
|
||||||
// ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie
|
|
||||||
fVelDes = v;
|
|
||||||
}
|
|
||||||
// if (v==0.0) fAcc=-0.9; //hamowanie jeśli stop
|
|
||||||
continue; // i tyle wystarczy
|
|
||||||
}
|
|
||||||
else // event trzyma tylko jeśli VelNext=0, nawet po przejechaniu (nie powinno dotyczyć samochodów?)
|
|
||||||
a = (v > 0.0 ?
|
|
||||||
fAcc :
|
|
||||||
mvOccupied->Vel < 0.01 ?
|
|
||||||
0.0 : // already standing still so no need to bother with brakes
|
|
||||||
-2.0 ); // ruszanie albo hamowanie
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
@@ -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?
|
|
||||||
|
|
||||||
if (ConverterAllow != State)
|
auto const initialstate { ConverterAllow };
|
||||||
{
|
|
||||||
ConverterAllow = State;
|
ConverterAllow = State;
|
||||||
CS = true;
|
|
||||||
}
|
if( Notify != range_t::local ) {
|
||||||
if( ConverterAllow == true ) {
|
SendCtrlToNext(
|
||||||
if( Notify != range_t::local ) {
|
"ConverterSwitch",
|
||||||
SendCtrlToNext(
|
( State ? 1 : 0 ),
|
||||||
"ConverterSwitch", 1, CabActive,
|
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( Notify != range_t::local ) {
|
||||||
}
|
SendCtrlToNext(
|
||||||
if( CompressorAllow == true ) {
|
"CompressorSwitch",
|
||||||
if( Notify != range_t::local ) {
|
( State ? 1 : 0 ),
|
||||||
SendCtrlToNext(
|
CabActive,
|
||||||
"CompressorSwitch", 1, CabActive,
|
( Notify == range_t::unit ?
|
||||||
( Notify == range_t::unit ?
|
coupling::control | coupling::permanent :
|
||||||
ctrain_controll | ctrain_depot :
|
coupling::control ) );
|
||||||
ctrain_controll ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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,20 +3694,8 @@ 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; }
|
||||||
|
|
||||||
//EmergencyValve
|
//EmergencyValve
|
||||||
@@ -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 ) {
|
||||||
CompressorAllow = ConverterAllow;
|
case 2: {
|
||||||
}
|
CompressorAllow = ConverterAllow;
|
||||||
// TODO: clean up compressor CompressorFlag state code, large parts are cloned and an utter mess
|
break;
|
||||||
if (MaxCompressorF - MinCompressorF < 0.0001) {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
case 3: {
|
||||||
else {
|
// HACK: make sure compressor coupled with diesel engine is always ready for work
|
||||||
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)
|
|
||||||
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 ) );
|
|
||||||
|
|
||||||
if( Compressor > MaxCompressorF ) {
|
|
||||||
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
|
|
||||||
// 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 )
|
|
||||||
|| ( TrainType == dt_ET42 ) ) {
|
|
||||||
// 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
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
// jeśli nie załączona
|
|
||||||
if( ( LastSwitchingTime > CtrlDelay )
|
|
||||||
&& ( ( Compressor < MinCompressorF )
|
|
||||||
|| ( ( Compressor < MaxCompressorF )
|
|
||||||
&& ( false == CompressorGovernorLock ) ) ) ) {
|
|
||||||
// załączenie przy małym ciśnieniu
|
|
||||||
// jeśli nie załączona, a ciśnienie za małe
|
|
||||||
// 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
|
auto *compressorowner { (
|
||||||
// TODO: replace this with a more universal activation system down the road
|
CompressorPower == 4 ? Couplers[ end::front ].Connected :
|
||||||
if( ( TrainType == dt_ET41 )
|
CompressorPower == 5 ? Couplers[ end::rear ].Connected :
|
||||||
|| ( TrainType == dt_ET42 ) ) {
|
this ) };
|
||||||
|
auto const compressorpower { (
|
||||||
|
CompressorPower == 0 ? Mains :
|
||||||
|
CompressorPower == 3 ? Mains :
|
||||||
|
( compressorowner != nullptr ) && ( compressorowner->ConverterFlag ) ) };
|
||||||
|
auto const compressorallow {
|
||||||
|
( CompressorAllowLocal )
|
||||||
|
&& ( ( CompressorStart == start_t::automatic )
|
||||||
|
|| ( ( compressorowner != nullptr ) && ( compressorowner->CompressorAllow ) ) ) };
|
||||||
|
|
||||||
if( ( Couplers[1].Connected != nullptr )
|
auto const pressureistoolow { Compressor < MinCompressorF };
|
||||||
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
|
auto const pressureistoohigh { Compressor > MaxCompressorF };
|
||||||
// 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 ) {
|
// TBD, TODO: break the lock with no low voltage power?
|
||||||
// jeśli została załączona
|
auto const governorlockispresent { MaxCompressorF - MinCompressorF > 0.0001 };
|
||||||
LastSwitchingTime = 0; // to trzeba ograniczyć ponowne włączenie
|
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
|
||||||
|
// NOTE: this is crude implementation, limited only to adjacent vehicles
|
||||||
|
// TODO: re-implement when a more elegant/flexible system is in place
|
||||||
|
auto const coupledgovernorlock {
|
||||||
|
( ( Couplers[ end::rear ].Connected != nullptr )
|
||||||
|
&& ( true == TestFlag( Couplers[ end::rear ].CouplingFlag, coupling::permanent ) )
|
||||||
|
&& ( Couplers[ end::rear ].Connected->CompressorGovernorLock ) )
|
||||||
|
|| ( ( Couplers[ end::front ].Connected != nullptr )
|
||||||
|
&& ( true == TestFlag( Couplers[ end::front ].CouplingFlag, coupling::permanent ) )
|
||||||
|
&& ( Couplers[ end::front ].Connected->CompressorGovernorLock ) ) };
|
||||||
|
auto const governorlock { CompressorGovernorLock || coupledgovernorlock };
|
||||||
|
|
||||||
|
auto const compressorflag { CompressorFlag };
|
||||||
|
CompressorFlag =
|
||||||
|
( compressorpower )
|
||||||
|
&& ( ( false == governorlock ) || ( CompressorPower == 3 ) )
|
||||||
|
&& ( ( CompressorFlag )
|
||||||
|
|| ( ( compressorallow ) && ( LastSwitchingTime > CtrlDelay ) ) );
|
||||||
|
|
||||||
|
if( ( CompressorFlag ) && ( CompressorFlag != compressorflag ) ) {
|
||||||
|
// jeśli została załączona to trzeba ograniczyć ponowne włączenie
|
||||||
|
LastSwitchingTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == CompressorFlag ) { return; }
|
||||||
|
|
||||||
|
// working compressor adds air to the air reservoir
|
||||||
|
switch( CompressorPower ) {
|
||||||
|
case 3: {
|
||||||
|
// the compressor is coupled with the diesel engine, engine revolutions affect the output
|
||||||
|
auto const enginefactor { (
|
||||||
|
EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) :
|
||||||
|
EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) :
|
||||||
|
1.0 ) }; // shouldn't ever get here but, eh
|
||||||
|
CompressedVolume +=
|
||||||
|
CompressorSpeedF
|
||||||
|
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
|
||||||
|
* enginefactor
|
||||||
|
* dt;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
// the compressor is a stand-alone device, working at steady pace
|
||||||
|
CompressedVolume +=
|
||||||
|
CompressorSpeedF
|
||||||
|
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
|
||||||
|
* dt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( CompressorFlag ) {
|
if( ( pressureistoohigh )
|
||||||
// working compressor adds air to the air reservoir
|
&& ( false == governorlockispresent ) ) {
|
||||||
if( CompressorPower == 3 ) {
|
// vent some air out if there's no governor lock to stop the compressor from exceeding acceptable pressure level
|
||||||
// the compressor is coupled with the diesel engine, engine revolutions affect the output
|
SetFlag( SoundFlag, sound::relay | sound::loud );
|
||||||
if( false == CompressorGovernorLock ) {
|
CompressedVolume *= 0.8;
|
||||||
auto const enginefactor { (
|
}
|
||||||
EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) :
|
|
||||||
EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) :
|
|
||||||
1.0 ) }; // shouldn't ever get here but, eh
|
|
||||||
CompressedVolume +=
|
|
||||||
CompressorSpeed
|
|
||||||
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
|
|
||||||
* enginefactor
|
|
||||||
* dt;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
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
|
|
||||||
CompressedVolume +=
|
|
||||||
CompressorSpeedF
|
|
||||||
* ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF
|
|
||||||
* dt;
|
|
||||||
|
|
||||||
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ę
|
// TODO: draw power from proper high- or low voltage circuit
|
||||||
Couplers[ 1 ].Connected->TotalCurrent += 0.0015 * Couplers[ 1 ].Connected->PantographVoltage;
|
switch( CompressorPower ) {
|
||||||
}
|
case 3: {
|
||||||
else if( ( CompressorPower == 4 ) && ( Couplers[ 0 ].Connected != NULL ) ) {
|
// diesel-powered compressor doesn't draw power
|
||||||
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
|
break;
|
||||||
Couplers[ 0 ].Connected->TotalCurrent += 0.0015 * Couplers[ 0 ].Connected->PantographVoltage;
|
}
|
||||||
}
|
default: {
|
||||||
else {
|
if( compressorowner != nullptr ) {
|
||||||
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
|
compressorowner->TotalCurrent += 0.0015 * compressorowner->PantographVoltage;
|
||||||
TotalCurrent += 0.0015 * 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 };
|
||||||
|
|||||||
103
Train.cpp
103
Train.cpp
@@ -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,48 +3125,54 @@ 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 (Command.action != GLFW_PRESS) {
|
|
||||||
// one change per key press
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo)
|
if( Train->ggCompressorListButton.type() == TGaugeType::push ) {
|
||||||
|| (true == Train->mvOccupied->CompressorListWrap)) {
|
// impulse switch
|
||||||
// active light preset is stored as value in range 1-LigthPosNo
|
if( Train->mvOccupied->CompressorListPosNo < Train->mvOccupied->CompressorListDefPos + 1 ) { return; }
|
||||||
Train->mvOccupied->CompressorListPos = (
|
|
||||||
Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ?
|
|
||||||
Train->mvOccupied->CompressorListPos + 1 :
|
|
||||||
1); // wrap mode
|
|
||||||
|
|
||||||
// visual feedback
|
Train->mvOccupied->ChangeCompressorPreset( (
|
||||||
if (Train->ggCompressorListButton.SubModel != nullptr) {
|
Command.action == GLFW_PRESS ?
|
||||||
Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch);
|
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 )
|
||||||
|
|| ( true == Train->mvOccupied->CompressorListWrap ) ) {
|
||||||
|
// active light preset is stored as value in range 1-LigthPosNo
|
||||||
|
Train->mvOccupied->ChangeCompressorPreset( (
|
||||||
|
Train->mvOccupied->CompressorListPos < Train->mvOccupied->CompressorListPosNo ?
|
||||||
|
Train->mvOccupied->CompressorListPos + 1 :
|
||||||
|
1 ) ); // wrap mode
|
||||||
|
// visual feedback
|
||||||
|
Train->ggCompressorListButton.UpdateValue( Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,18 +3183,12 @@ 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) {
|
||||||
Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch);
|
Train->ggCompressorListButton.UpdateValue(Train->mvOccupied->CompressorListPos - 1, Train->dsbSwitch);
|
||||||
}
|
}
|
||||||
@@ -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 },
|
||||||
|
|||||||
1
Train.h
1
Train.h
@@ -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
|
||||||
|
|||||||
2
color.h
2
color.h
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user