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

ai braking test, motor overload relay threshold logic enhancement, vehicle max load parameter

This commit is contained in:
tmj-fstate
2021-06-05 21:30:53 +02:00
parent 7b816594ba
commit 2e86b3a5e9
11 changed files with 472 additions and 169 deletions

View File

@@ -885,7 +885,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
IsScheduledPassengerStopVisible = false;
mvOccupied->SecuritySystem.SHPLock = false;
// te flagi są ustawiane tutaj, w razie potrzeby
iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSemaphorFound | /*moveSpeedLimitFound*/ moveStopPointFound );
iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSignalFound | /*moveSpeedLimitFound*/ moveStopPointFound );
for( std::size_t idx = 0; idx < sSpeedTable.size(); ++idx ) {
// o ile dana pozycja tabelki jest istotna
@@ -1064,7 +1064,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// jeśli mieliśmy ograniczenie z semafora i nie ma przed nami
if( ( VelSignalLast >= 0.0 )
&& ( ( iDrivigFlags & ( moveSemaphorFound | moveSwitchFound | moveStopPointFound ) ) == 0 )
&& ( ( iDrivigFlags & ( moveSignalFound | moveSwitchFound | moveStopPointFound ) ) == 0 )
&& ( true == TestFlag( OrderCurrentGet(), Obey_train ) ) ) {
VelSignalLast = -1.0;
}
@@ -1557,7 +1557,7 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo
}
else {
//jeśli z przodu to dajemy flagę, że jest
iDrivigFlags |= moveSemaphorFound;
iDrivigFlags |= moveSignalFound;
Signaldistance = std::min( Point.fDist, Signaldistance );
// if there's another vehicle closer to the signal, then it's likely its intended recipient
// HACK: if so, make it a stop point, to prevent non-signals farther down affect us
@@ -1854,23 +1854,23 @@ void TController::TableSort() {
//---------------------------------------------------------------------------
TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche, bool primary) :// czy ma aktywnie prowadzić?
TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche, bool Primary) :// czy ma aktywnie prowadzić?
AIControllFlag( AI ), pVehicle( NewControll )
{
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu
if( pVehicle != nullptr ) {
pVehicles[ 0 ] = pVehicle->GetFirstDynamic( 0 ); // pierwszy w kierunku jazdy (Np. Pc1)
pVehicles[ 1 ] = pVehicle->GetFirstDynamic( 1 ); // ostatni w kierunku jazdy (końcówki)
pVehicles[ end::front ] = pVehicle->GetFirstDynamic( end::front ); // pierwszy w kierunku jazdy (Np. Pc1)
pVehicles[ end::rear ] = pVehicle->GetFirstDynamic( end::rear ); // ostatni w kierunku jazdy (końcówki)
}
else {
pVehicles[ 0 ] = nullptr;
pVehicles[ 1 ] = nullptr;
pVehicles[ end::front ] = nullptr;
pVehicles[ end::rear ] = nullptr;
}
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu
if( mvOccupied != nullptr ) {
iDirectionOrder = mvOccupied->CabActive; // 1=do przodu (w kierunku sprzęgu 0)
VehicleName = mvOccupied->Name;
if( mvOccupied->CategoryFlag & 2 ) { // samochody: na podst. http://www.prawko-kwartnik.info/hamowanie.html
if( is_car() ) { // samochody: na podst. http://www.prawko-kwartnik.info/hamowanie.html
// fDriverBraking=0.0065; //mnożone przez (v^2+40*v) [km/h] daje prawie drogę hamowania [m]
fDriverBraking = 0.03; // coś nie hamują te samochody zbyt dobrze
fDriverDist = 5.0; // 5m - zachowywany odstęp przed kolizją
@@ -1907,7 +1907,7 @@ TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche,
// OrderValue=0;
OrdersClear();
if( true == primary ) {
if( true == Primary ) {
iDrivigFlags |= movePrimary; // aktywnie prowadzące pojazd
}
@@ -2105,8 +2105,8 @@ void TController::Activation()
{ // jeśli zmieniony został pojazd prowadzony
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) - silnikowy dla EZT
if( ( mvOccupied->BrakeCtrlPosNo > 0 )
&& ( ( mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic )
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) {
&& ( ( BrakeSystem == TBrakeSystem::Pneumatic )
|| ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) {
mvOccupied->LimPipePress = mvOccupied->PipePress;
mvOccupied->ActFlowSpeed = 0;
}
@@ -2242,6 +2242,7 @@ void TController::AutoRewident()
}
// potentially release manual brake
d->MoverParameters->DecManualBrakeLevel( ManualBrakePosNo );
d->MoverParameters->SpringBrake.Activate = false;
}
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
@@ -2276,6 +2277,9 @@ void TController::AutoRewident()
fNominalAccThreshold = fAccThreshold;
}
BrakeSystem = consist_brake_system();
mvOccupied->EpFuseSwitch( BrakeSystem == TBrakeSystem::ElectroPneumatic );
if( OrderCurrentGet() & ( Obey_train | Bank ) ) {
// 4. Przeliczanie siły hamowania
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
@@ -2310,12 +2314,13 @@ void TController::AutoRewident()
0.25 );
if( is_emu() ) {
auto ep_factor { ( BrakeSystem == TBrakeSystem::ElectroPneumatic ? 8 : 4 ) };
if( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) {
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - ep_factor * fBrake_a1[ BrakeAccTableSize ] );
}
else {
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - ep_factor * fBrake_a1[ BrakeAccTableSize ] );
}
fBrakeReaction = 0.25;
}
@@ -2503,6 +2508,18 @@ bool TController::CheckVehicles(TOrders user)
}
}
// kasowanie pamieci hamowania kontrolnego
if (OrderCurrentGet() & (Shunt | Loose_shunt | Disconnect | Connect | Change_direction)) {
DynamicBrakeTest = 0;
DBT_VelocityBrake
= DBT_VelocityRelease
= DBT_VelocityFinish
= DBT_BrakingTime
= DBT_ReleasingTime
= DBT_MidPointAcc
= 0;
}
// HACK: ensure vehicle lights are active from the beginning, if it had pre-activated battery
if( mvOccupied->LightsPosNo > 0 ) {
pVehicle->SetLights();
@@ -2608,6 +2625,31 @@ void TController::DirectionChange() {
}
}
TBrakeSystem TController::consist_brake_system() const {
if( mvOccupied->BrakeSystem != TBrakeSystem::ElectroPneumatic ) { return mvOccupied->BrakeSystem; }
auto isepcapable = true;
if( pVehicles[ end::front ] != pVehicles[ end::rear ] ) {
// more detailed version, will use manual braking also for coupled sets of controlled vehicles
auto *vehicle = pVehicles[ end::front ]; // start from first
while( ( true == isepcapable )
&& ( vehicle != nullptr ) ) {
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
isepcapable = (
( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
|| ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > -1 ) ) )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr )
|| ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > -1 ) ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
}
return ( isepcapable ? TBrakeSystem::ElectroPneumatic : TBrakeSystem::Pneumatic );
}
int TController::OrderDirectionChange(int newdir, TMoverParameters *Vehicle)
{ // zmiana kierunku jazdy, niezależnie od kabiny
int testd = newdir;
@@ -2961,8 +3003,12 @@ bool TController::ReleaseEngine() {
bool TController::IncBrake()
{ // zwiększenie hamowania
bool OK = false;
switch( mvOccupied->BrakeSystem ) {
auto OK { false };
auto const bs {
( ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) && ( ForcePNBrake ) ) ?
TBrakeSystem::Pneumatic :
BrakeSystem };
switch( bs ) {
case TBrakeSystem::Individual: {
if( mvOccupied->LocalBrake == TLocalBrake::ManualBrake ) {
OK = mvOccupied->IncManualBrakeLevel( 1 + static_cast<int>( std::floor( 0.5 + std::fabs( AccDesired ) ) ) );
@@ -2973,8 +3019,15 @@ bool TController::IncBrake()
break;
}
case TBrakeSystem::Pneumatic: {
if (bs != mvOccupied->BrakeSystem)
{
while (mvOccupied->BrakeOpModeFlag > bom_PN)
{
mvOccupied->BrakeOpModeFlag >>= 1;
}
}
// NOTE: can't perform just test whether connected vehicle == nullptr, due to virtual couplers formed with nearby vehicles
bool standalone { true };
auto standalone { true };
if( ( mvOccupied->TrainType == dt_ET41 )
|| ( mvOccupied->TrainType == dt_ET42 ) ) {
// NOTE: we're doing simplified checks full of presuptions here.
@@ -3024,7 +3077,7 @@ bool TController::IncBrake()
//standalone = standalone && ( mvControlling->EIMCtrlType == 0 );
if( true == standalone ) {
if( ( true == standalone ) && ( false == ForcePNBrake ) ) {
if( mvControlling->EIMCtrlType > 0 ) {
OK = IncBrakeEIM();
}
@@ -3101,6 +3154,9 @@ bool TController::IncBrake()
break;
}
case TBrakeSystem::ElectroPneumatic: {
while( ( mvOccupied->BrakeOpModeFlag << 1 ) <= mvOccupied->BrakeOpModes ) {
mvOccupied->BrakeOpModeFlag <<= 1;
}
if( mvOccupied->EngineType == TEngineType::ElectricInductionMotor ) {
if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57) {
if (mvOccupied->BrakeCtrlPos < mvOccupied->Handle->GetPos(bh_FB))
@@ -3188,8 +3244,11 @@ bool TController::IncBrakeEIM()
bool TController::DecBrake() {
auto OK { false };
switch( mvOccupied->BrakeSystem ) {
auto const bs {
( ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) && ( ForcePNBrake ) ) ?
TBrakeSystem::Pneumatic :
BrakeSystem };
switch( bs ) {
case TBrakeSystem::Individual: {
auto const positionchange { 1 + std::floor( 0.5 + std::abs( AccDesired ) ) };
OK = (
@@ -3357,12 +3416,24 @@ bool TController::IncSpeed()
|| (mvControlling->StLinFlag)) { // youBy polecił dodać 2012-09-08 v367
// na pozycji 0 przejdzie, a na pozostałych będzie czekać, aż się załączą liniowe (zgaśnie DelayCtrlFlag)
if (Ready || (iDrivigFlags & movePress)) {
auto const usehighoverloadrelaythreshold {
( mvControlling->TrainType != dt_ET42 ) // ET42 uses these variables for different purpose. TODO: fix this
&& ( mvControlling->ImaxHi > mvControlling->ImaxLo )
&& ( mvOccupied->Vel < ( mvControlling->IsMotorOverloadRelayHighThresholdOn() ? 30.0 : 20.0 ) )
&& ( iVehicles - ControlledEnginesCount > 0 )
// && ( std::fabs( mvControlling->Im ) > 0.85 * mvControlling->Imax )
&& ( ( mvControlling->Imax * mvControlling->EngineVoltage * ControlledEnginesCount )
/ ( fMass * (
fAccGravity == 0.025 ?
-0.01 : // prevent div/0
fAccGravity - 0.025 ) )
< -2.8 ) };
// use series mode:
// if high threshold is set for motor overload relay,
// if the power station is heavily burdened,
// if it generates enough traction force
// to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill)
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 75 : 50 ) * 1000.0 };
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) * ControlledEnginesCount > ( IsHeavyCargoTrain ? 75 : 50 ) * 1000.0 };
auto const sufficientacceleration { AbsAccS >= ( IsHeavyCargoTrain ? 0.03 : IsCargoTrain ? 0.06 : 0.09 ) };
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
@@ -3373,6 +3444,7 @@ bool TController::IncSpeed()
( IsHeavyCargoTrain ? 0.35 : 0.40 ) ) };
auto const useseriesmode = (
( mvControlling->Imax > mvControlling->ImaxLo )
|| ( true == usehighoverloadrelaythreshold )
|| ( fVoltage < useseriesmodevoltage )
|| ( ( true == sufficientacceleration )
&& ( true == sufficienttractionforce )
@@ -3390,6 +3462,32 @@ bool TController::IncSpeed()
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 :
mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) );
// if needed enable high threshold for overload relay...
if( mvControlling->TrainType != dt_ET42 ) { // ET42 uses these variables for different purpose. TODO: fix this
if( usehighoverloadrelaythreshold ) {
if( mvControlling->Imax < mvControlling->ImaxHi ) {
// to enable this setting we'll typically need the main controller in series mode (which is not guaranteed)
if( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) {
if( false == mvControlling->IsScndCtrlNoPowerPos() ) {
mvControlling->DecScndCtrl( 2 );
}
while( ( false == mvControlling->IsMainCtrlNoPowerPos() )
&& ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) ) {
mvControlling->DecMainCtrl( 1 ); // kręcimy nastawnik jazdy o 1 wstecz
}
}
mvControlling->CurrentSwitch( true ); // rozruch wysoki (za to może się ślizgać)
}
}
// ...or disable high threshold for overload relay if no longer needed
else {
if( ( mvControlling->IsMotorOverloadRelayHighThresholdOn() )
&& ( std::fabs( mvControlling->Im ) < mvControlling->ImaxLo ) ) {
mvControlling->CurrentSwitch( false ); // rozruch wysoki wyłącz
}
}
}
double Vs = 99999;
if( usefieldshunting ?
( mvControlling->ScndCtrlPos < mvControlling->ScndCtrlPosNo ) :
@@ -3677,21 +3775,36 @@ bool TController::IncSpeedEIM() {
bool TController::DecSpeedEIM( int const Amount )
{ // zmniejszenie prędkości (ale nie hamowanie)
bool OK = false; // domyślnie false, aby wyszło z pętli while
switch (mvControlling->EIMCtrlType)
{
case 0:
OK = mvControlling->DecMainCtrl( Amount );
break;
case 1:
OK = mvControlling->MainCtrlPos > 4;
if (OK)
mvControlling->MainCtrlPos = 4;
break;
case 2:
OK = mvControlling->MainCtrlPos > 2;
if (OK)
mvControlling->MainCtrlPos = 2;
break;
switch( mvControlling->EIMCtrlType ) {
case 0: {
OK = mvControlling->DecMainCtrl( Amount );
break;
}
case 1: {
OK = mvControlling->MainCtrlPos > 4;
if( OK ) {
mvControlling->MainCtrlPos = 4;
}
break;
}
case 2: {
if( ( AccDesired > 0 )
&& ( mvControlling->SpeedCtrlUnit.IsActive )
&& ( mvControlling->SpeedCtrlUnit.PowerStep > 0 )
&& ( mvControlling->SpeedCtrlUnit.DesiredPower > mvControlling->SpeedCtrlUnit.MinPower ) ) {
mvControlling->SpeedCtrlPowerDec();
}
else {
OK = mvControlling->MainCtrlPos > 2;
if( OK ) {
mvControlling->MainCtrlPos = 2;
}
}
break;
}
default: {
break;
}
}
return OK;
}
@@ -3785,56 +3898,51 @@ void TController::SpeedSet() {
break;
}
case TEngineType::ElectricSeriesMotor: {
/*
if (Ready || (iDrivigFlags & movePress)) { // o ile może jechać
if (fAccGravity < -0.10) // i jedzie pod górę większą niż 10 promil
// if (fAccGravity < -0.10) // i jedzie pod górę większą niż 10 promil
{ // procedura wjeżdżania na ekstremalne wzniesienia
if (fabs(mvControlling->Im) > 0.85 * mvControlling->Imax) // a prąd jest większy niż 85% nadmiarowego
if (mvControlling->Imax * mvControlling->EngineVoltage / (fMass * fAccGravity) < -2.8) // a na niskim się za szybko nie pojedzie
if( std::fabs( mvControlling->Im ) > 0.85 * mvControlling->Imax ) { // a prąd jest większy niż 85% nadmiarowego
if( mvControlling->Imax * mvControlling->EngineVoltage / ( fMass * fAccGravity ) < -2.8 ) // a na niskim się za szybko nie pojedzie
{ // włączenie wysokiego rozruchu;
// (I*U)[A*V=W=kg*m*m/sss]/(m[kg]*a[m/ss])=v[m/s]; 2.8m/ss=10km/h
if (mvControlling->RList[mvControlling->MainCtrlPos].Bn > 1)
{ // jeśli jedzie na równoległym, to zbijamy do szeregowego, aby włączyć
// wysoki rozruch
if (mvControlling->ScndCtrlPos > 0) // jeżeli jest bocznik
mvControlling->DecScndCtrl(2); // wyłączyć bocznik, bo może blokować skręcenie NJ
do // skręcanie do bezoporowej na szeregowym
mvControlling->DecMainCtrl(1); // kręcimy nastawnik jazdy o 1 wstecz
while (mvControlling->MainCtrlPos ?
mvControlling->RList[mvControlling->MainCtrlPos].Bn > 1 :
false); // oporowa zapętla
if( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) { // jeśli jedzie na równoległym, to zbijamy do szeregowego, aby włączyć wysoki rozruch
if( mvControlling->ScndCtrlPos > 0 ) { // jeżeli jest bocznik
mvControlling->DecScndCtrl( 2 ); // wyłączyć bocznik, bo może blokować skręcenie NJ
}
do { // skręcanie do bezoporowej na szeregowym
mvControlling->DecMainCtrl( 1 ); // kręcimy nastawnik jazdy o 1 wstecz
}
while( ( false == mvControlling->IsMainCtrlNoPowerPos() )
&& ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) ); // oporowa zapętla
}
if (mvControlling->Imax < mvControlling->ImaxHi) // jeśli da się na wysokim
mvControlling->CurrentSwitch(true); // rozruch wysoki (za to może się ślizgać)
if (ReactionTime > 0.1)
if( mvControlling->Imax < mvControlling->ImaxHi ) { // jeśli da się na wysokim
mvControlling->CurrentSwitch( true ); // rozruch wysoki (za to może się ślizgać)
}
if( ReactionTime > 0.1 ) {
ReactionTime = 0.1; // orientuj się szybciej
}
} // if (Im>Imin)
// NOTE: this step is likely to conflict with directive to operate sandbox based on the state of slipping wheels
// TODO: gather all sandbox operating logic in one place
if( fabs( mvControlling->Im ) > 0.75 * mvControlling->ImaxHi ) {
// jeśli prąd jest duży
mvControlling->Sandbox( true ); // piaskujemy tory, coby się nie ślizgać
}
else {
// otherwise we switch the sander off, if it's active
if( mvControlling->SandDose ) {
mvControlling->Sandbox( false );
if( std::fabs( mvControlling->Im ) > 0.96 * mvControlling->Imax ) {// jeśli prąd jest duży (można 690 na 750)
if( mvControlling->ScndCtrlPos > 0 ) { // jeżeli jest bocznik
mvControlling->DecScndCtrl( 2 ); // zmniejszyć bocznik
}
else {
mvControlling->DecMainCtrl( 1 ); // kręcimy nastawnik jazdy o 1 wstecz
}
}
if ((fabs(mvControlling->Im) > 0.96 * mvControlling->Imax) ||
mvControlling->SlippingWheels) // jeśli prąd jest duży (można 690 na 750)
if (mvControlling->ScndCtrlPos > 0) // jeżeli jest bocznik
mvControlling->DecScndCtrl(2); // zmniejszyć bocznik
else
mvControlling->DecMainCtrl(1); // kręcimy nastawnik jazdy o 1 wstecz
}
else // gdy nie jedzie ambitnie pod górę
// else // gdy nie jedzie ambitnie pod górę
{ // sprawdzenie, czy rozruch wysoki jest potrzebny
if (mvControlling->Imax > mvControlling->ImaxLo)
if (mvOccupied->Vel >= 30.0) // jak się rozpędził
if (fAccGravity > -0.02) // a i pochylenie mnijsze niż 2‰
mvControlling->CurrentSwitch(false); // rozruch wysoki wyłącz
if( ( mvControlling->Imax > mvControlling->ImaxLo )
&& ( mvOccupied->Vel >= 30.0 ) ) { // jak się rozpędził
// if (fAccGravity > -0.02) // a i pochylenie mnijsze niż 2‰
mvControlling->CurrentSwitch( false ); // rozruch wysoki wyłącz
}
}
}
*/
break;
}
case TEngineType::Dumb: {
@@ -3926,13 +4034,14 @@ void TController::SetTimeControllers()
if( false == AIControllFlag ) { return; }
//1. Check the type of Main Brake Handle
if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic)
{
if( BrakeSystem == TBrakeSystem::Pneumatic || ForcePNBrake )
{
if (mvOccupied->Handle->Time)
{
if ((BrakeCtrlPosition > 0) && (mvOccupied->Handle->GetCP() - 0.05 > mvOccupied->HighPipePress - BrakeCtrlPosition*0.25*mvOccupied->DeltaPipePress))
auto const pressuredifference { mvOccupied->Handle->GetCP() - ( mvOccupied->HighPipePress - BrakeCtrlPosition * 0.25*mvOccupied->DeltaPipePress ) };
if ((BrakeCtrlPosition > 0) && (pressuredifference > 0.05))
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_FB));
else if ((BrakeCtrlPosition > 0) && (mvOccupied->Handle->GetCP() + 0.05 < mvOccupied->HighPipePress - BrakeCtrlPosition*0.25*mvOccupied->DeltaPipePress))
else if ((BrakeCtrlPosition > 0) && (pressuredifference < -0.05))
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP));
else if (BrakeCtrlPosition == 0)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP));
@@ -3941,21 +4050,29 @@ void TController::SetTimeControllers()
else if (BrakeCtrlPosition == -2)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP));
}
if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) mvOccupied->BrakeLevelSet(BrakeCtrlPosition);
if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)
{
if (BrakeCtrlPosition == 0)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP));
else if (BrakeCtrlPosition == -1)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_FS));
else if (BrakeCtrlPosition == -2)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP));
else if (BrakeCtrlPosition > 4.5)
mvOccupied->BrakeLevelSet(10);
else if (BrakeCtrlPosition > 3.70)
mvOccupied->BrakeLevelSet(9);
else
mvOccupied->BrakeLevelSet(round((BrakeCtrlPosition * 0.4 - 0.1) / 0.15));
if( mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) {
mvOccupied->BrakeLevelSet( BrakeCtrlPosition );
}
if( ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57 ) ) {
if( BrakeCtrlPosition == 0 ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) );
}
else if( BrakeCtrlPosition == -1 ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) );
}
else if( BrakeCtrlPosition == -2 ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_NP ) );
}
else if( BrakeCtrlPosition > 4.5 ) {
mvOccupied->BrakeLevelSet( 10 );
}
else if( BrakeCtrlPosition > 3.70 ) {
mvOccupied->BrakeLevelSet( 9 );
}
else {
mvOccupied->BrakeLevelSet( round( ( BrakeCtrlPosition * 0.4 - 0.1 ) / 0.15 ) );
}
}
}
//2. Check the type of Secondary Brake Handle
@@ -4130,12 +4247,12 @@ void TController::CheckTimeControllers()
if( false == AIControllFlag ) { return; }
//1. Check the type of Main Brake Handle
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic && mvOccupied->Handle->TimeEP)
{
if( BrakeSystem == TBrakeSystem::ElectroPneumatic && mvOccupied->Handle->TimeEP && !ForcePNBrake )
{
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_EPN));
}
if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic && mvOccupied->Handle->Time)
{
if( ( BrakeSystem == TBrakeSystem::Pneumatic || ForcePNBrake ) && mvOccupied->Handle->Time )
{
if (BrakeCtrlPosition > 0)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_MB));
else
@@ -5754,6 +5871,7 @@ void TController::ControllingSet()
lookup->MoverParameters :
mvControlling );
}
BrakeSystem = consist_brake_system();
};
std::string TController::TableText( std::size_t const Index ) const
@@ -5872,7 +5990,7 @@ TController::determine_consist_state() {
Ready = true; // wstępnie gotowy
fReady = 0.0; // założenie, że odhamowany
IsConsistBraked = (
mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
( ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) && ( false == ForcePNBrake ) ) ?
mvOccupied->BrakePress > 2.0 :
mvOccupied->PipePress < std::max( 3.9, mvOccupied->BrakePressureActual.PipePressureVal ) + 0.1 );
fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia
@@ -5888,8 +6006,10 @@ TController::determine_consist_state() {
auto const bp { std::max( 0.0, vehicle->BrakePress - ( vehicle->SpeedCtrlUnit.Parking ? vehicle->MaxBrakePress[ 0 ] * vehicle->StopBrakeDecc : 0.0 ) ) };
if (Ready) {
// bo jak coś nie odhamowane, to dalej nie ma co sprawdzać
if( ( TestFlag( vehicle->Hamulec->GetBrakeStatus(), b_hld ) )
|| ( ( vehicle->Vel < 1.0 ) && ( bp > 0.4 ) ) ) { // ensure the brakes are sufficiently released when starting to move
if( ( TestFlagAny( vehicle->Hamulec->GetBrakeStatus(), ( b_hld | b_on ) ) )
|| ( ( vehicle->Vel < 1.0 ?
( bp > 0.4 ) : // ensure the brakes are sufficiently released when starting to move
( vehicle->Fb * 0.001 > 10.0 ) ) ) ) { // once in motion we can make a more lenient check
Ready = false;
}
// Ra: odluźnianie przeładowanych lokomotyw, ciągniętych na zimno - prowizorka...
@@ -6028,6 +6148,9 @@ TController::control_wheelslip() {
cue_action( locale::string::driver_hint_antislip );
++iDriverFailCount;
}
else if( std::fabs( mvControlling->Im ) > 0.75 * mvControlling->ImaxHi ) {
cue_action( locale::string::driver_hint_sandingon ); // piaskujemy tory, coby się nie ślizgać
}
else {
// deactivate sandbox if we aren't slipping
if( mvControlling->SandDose ) {
@@ -6970,7 +7093,7 @@ TController::UpdateDisconnect() {
else {
WriteLog( "Uncoupling [" + mvOccupied->Name + "]: direction change" );
/* // TODO: test if this block is needed
if( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
if( BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
// wyłączenie EP, gdy wystarczy (może nie być potrzebne, bo na początku jest)
mvOccupied->BrakeLevelSet( 0 );
}
@@ -7159,6 +7282,7 @@ TController::pick_optimal_speed( double const Range ) {
adjust_desired_speed_for_limits();
adjust_desired_speed_for_target_speed( Range );
adjust_desired_speed_for_current_speed();
adjust_desired_speed_for_braking_test();
// Ra 2F1I: wyłączyć kiedyś to uśrednianie i przeanalizować skanowanie, czemu migocze
if( AccDesired > EU07_AI_NOACCELERATION ) { // hamowania lepeiej nie uśredniać
@@ -7619,6 +7743,82 @@ TController::adjust_desired_speed_for_current_speed() {
}
}
// hamowanie kontrolne
void
TController::adjust_desired_speed_for_braking_test() {
// if( false == Global.DynamicBrakeTest ) { return; }
if( DynamicBrakeTest >= 5 ) { return; } // all done
if( false == is_train() ) { return; } // not applicable
if( false == TestFlag( OrderCurrentGet(), Obey_train ) ) { return; } // not applicable
if( false == AIControllFlag ) { return; } // TBD: add notification about braking test and enable it for human driver as well?
auto const vel { DirectionalVel() };
switch( DynamicBrakeTest ) {
case 0: {
if( ( primary() )
&& ( vel < VelDesired )
&& ( fAccGravity >= 0.0 ) // not if going uphill
&& ( AccDesired >= EU07_AI_ACCELERATION )
&& ( TrainParams.TTVmax >= 10.0 )
&& ( vel > std::min( TrainParams.TTVmax, 60.0 ) - 2.0 ) ) {
DynamicBrakeTest = 1;
DBT_BrakingTime = ElapsedTime;
DBT_VelocityBrake = vel;
}
break;
}
case 1: {
AccDesired = EU07_AI_BRAKINGTESTACCELERATION;
VelDesired = DBT_VelocityBrake;
if( ElapsedTime - DBT_BrakingTime > 1 ) {
ForcePNBrake = true;
mvOccupied->EpFuseSwitch( false );
DynamicBrakeTest = 2;
}
break;
}
case 2: {
AccDesired = EU07_AI_BRAKINGTESTACCELERATION;
VelDesired = DBT_VelocityBrake;
if( ElapsedTime - DBT_BrakingTime > 2 ) {
DBT_BrakingTime = ElapsedTime;
DBT_VelocityBrake = vel;
DBT_VelocityRelease = vel - 8.0;
DynamicBrakeTest = 3;
}
break;
}
case 3: {
AccDesired = clamp( -AbsAccS, fAccThreshold * 1.01, fAccThreshold * 1.21 );
VelDesired = DBT_VelocityBrake;
if( vel <= DBT_VelocityRelease ) {
DynamicBrakeTest = 4;
DBT_BrakingTime = ElapsedTime - DBT_BrakingTime;
DBT_MidPointAcc = AbsAccS;
DBT_ReleasingTime = ElapsedTime;
}
break;
}
case 4: {
if( Ready ) {
if( BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
mvOccupied->EpFuseSwitch( true );
}
ForcePNBrake = false;
DynamicBrakeTest = 5;
DBT_ReleasingTime = ElapsedTime - DBT_ReleasingTime;
DBT_VelocityFinish = vel;
}
break;
}
default: {
break;
}
}
}
void
TController::control_tractive_and_braking_force() {
@@ -7701,7 +7901,7 @@ void TController::control_tractive_force() {
auto const velocity { DirectionalVel() };
// jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz...
if( ( AccDesired > EU07_AI_NOACCELERATION ) // don't add power if not asked for actual speed-up
&& (( AbsAccS < AccDesired /* - 0.05 */ ) || (mvOccupied->SpeedCtrlUnit.IsActive && velocity < mvOccupied->SpeedCtrlUnit.FullPowerVelocity))
&& (( AbsAccS < AccDesired - std::min( 0.05, 0.01 * iDriverFailCount ) ) || (mvOccupied->SpeedCtrlUnit.IsActive && velocity < mvOccupied->SpeedCtrlUnit.FullPowerVelocity))
&& ( false == TestFlag( iDrivigFlags, movePress ) ) ) {
// ...jeśli prędkość w kierunku czoła jest mniejsza od dozwolonej o margines...
if( velocity < (
@@ -7780,7 +7980,7 @@ void TController::control_braking_force() {
}
}
if( is_emu() ) {
if( is_emu() && ( !ForcePNBrake ) ) {
// właściwie, to warunek powinien być na działający EP
// Ra: to dobrze hamuje EP w EZT
auto const accthreshold { (
@@ -7896,7 +8096,7 @@ void TController::control_releaser() {
if( ( mvOccupied->Vel < 1.0 ) && ( fActionTime < 0.0 ) ) { return; }
// TODO: combine all releaser handling in single decision tree instead of having bits all over the place
// TODO: replace handle and system conditions with flag indicating releaser presence
if( mvOccupied->BrakeSystem != TBrakeSystem::Pneumatic ) { return; }
if( BrakeSystem != TBrakeSystem::Pneumatic ) { return; }
auto const hasreleaser {
( false == ( is_dmu() || is_emu() ) ) // TODO: a more refined test than rejecting these types wholesale
@@ -7964,7 +8164,7 @@ void TController::control_main_pipe() {
}
// napełnianie uderzeniowe
if( mvOccupied->BrakeSystem != TBrakeSystem::Pneumatic ) { return; }
if( BrakeSystem != TBrakeSystem::Pneumatic ) { return; }
if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P )

View File

@@ -17,7 +17,9 @@ http://mozilla.org/MPL/2.0/.
#include "mtable.h"
#include "translation.h"
auto const EU07_AI_ACCELERATION = 0.05;
auto const EU07_AI_NOACCELERATION = -0.05;
auto const EU07_AI_BRAKINGTESTACCELERATION = -0.06;
auto const EU07_AI_NOMOVEMENT = 0.05; // standstill velocity threshold
auto const EU07_AI_MOVEMENT = 1.0; // deliberate movement velocity threshold
auto const EU07_AI_SPEEDLIMITEXTENDSBEYONDSCANRANGE = 10000.0;
@@ -61,7 +63,7 @@ enum TMovementStatus
moveVisibility = 0x10000, // jazda na widoczność po przejechaniu S1 na SBL
moveDoorOpened = 0x20000, // drzwi zostały otwarte - doliczyć czas na zamknięcie
movePushPull = 0x40000, // zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku
moveSemaphorFound = 0x80000, // na drodze skanowania został znaleziony semafor
moveSignalFound = 0x80000, // na drodze skanowania został znaleziony semafor
moveStopPointFound = 0x100000 // stop point detected ahead
/*
moveSemaphorWasElapsed = 0x100000, // minięty został semafor
@@ -250,6 +252,7 @@ public:
return ( ( mvControlling->EngineType == TEngineType::DieselElectric )
|| ( mvControlling->EngineType == TEngineType::DieselEngine ) );
}
TBrakeSystem consist_brake_system() const;
private:
void Activation(); // umieszczenie obsady w odpowiednim członie
void ControllingSet(); // znajduje człon do sterowania
@@ -327,6 +330,7 @@ private:
void adjust_desired_speed_for_limits();
void adjust_desired_speed_for_target_speed( double const Range );
void adjust_desired_speed_for_current_speed();
void adjust_desired_speed_for_braking_test();
void control_tractive_and_braking_force();
void control_releaser();
void control_main_pipe();
@@ -431,6 +435,16 @@ private:
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
double BrakeChargingCooldown{}; // prevents the ai from trying to charge the train brake too frequently
TBrakeSystem BrakeSystem = TBrakeSystem::Individual; //type of main brake
bool ForcePNBrake = false; //is it necessary to use PN brake instead of EP brake
int DynamicBrakeTest = 0; //is it necessary to make brake test while driving
double DBT_VelocityBrake = 0;
double DBT_VelocityRelease = 0;
double DBT_VelocityFinish = 0;
double DBT_BrakingTime = 0;
double DBT_ReleasingTime = 0;
double DBT_MidPointAcc = 0;
int StaticBrakeTest = 0; //is it necessary to make brake test while standing
double LastReactionTime = 0.0;
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations

View File

@@ -2093,6 +2093,28 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
MoverParameters->dizel_HeatSet( Global.AirTemperature );
}
} // temperature
else if( ( ActPar.size() >= 2 )
&& ( ActPar.front() == 'L' ) ) {
// load
ActPar.erase( 0, 1 );
// immediately followed by max load override
// TBD: make it instead an optional sub-parameter?
{
auto const indexstart { 0 };
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
MoverParameters->MaxLoad = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
ActPar.erase( 0, indexend );
}
while( false == ActPar.empty() ) {
switch( ActPar.front() ) {
default: {
// unrecognized key
ActPar.erase( 0, 1 );
break;
}
}
}
} // load
/* else if (ActPar.substr(0, 1) == "") // tu mozna wpisac inny prefiks i inne rzeczy
{
// jakies inne prefiksy

View File

@@ -1193,6 +1193,7 @@ public:
int IminLo = 0; int IminHi = 0; /*prady przelacznika automatycznego rozruchu, uzywane tez przez ai_driver*/
int ImaxLo = 0; // maksymalny prad niskiego rozruchu
int ImaxHi = 0; // maksymalny prad wysokiego rozruchu
bool MotorOverloadRelayHighThreshold { false };
double nmax = 0.0; /*maksymalna dop. ilosc obrotow /s*/
double InitialCtrlDelay = 0.0; double CtrlDelay = 0.0; /* -//- -//- miedzy kolejnymi poz.*/
double CtrlDownDelay = 0.0; /* -//- -//- przy schodzeniu z poz.*/ /*hunter-101012*/
@@ -1675,6 +1676,7 @@ public:
bool DecBrakeLevel();
bool ChangeCab(int direction);
bool CurrentSwitch(bool const State);
bool IsMotorOverloadRelayHighThresholdOn() const;
void UpdateBatteryVoltage(double dt);
double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu
double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu - wersja zoptymalizowana
@@ -1841,7 +1843,7 @@ public:
bool CutOffEngine(void); //odlaczenie udszkodzonych silnikow
/*funkcje automatycznego rozruchu np EN57*/
bool MaxCurrentSwitch(bool State); //przelacznik pradu wysokiego rozruchu
bool MaxCurrentSwitch(bool State, range_t const Notify = range_t::consist ); //przelacznik pradu wysokiego rozruchu
bool MinCurrentSwitch(bool State); //przelacznik pradu automatycznego rozruchu
bool AutoRelaySwitch(bool State); //przelacznik automatycznego rozruchu
bool AutoRelayCheck();//symulacja automatycznego rozruchu

View File

@@ -674,6 +674,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
@@ -1419,6 +1425,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() ) {
@@ -2233,14 +2256,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;
@@ -3957,7 +3978,7 @@ bool TMoverParameters::SwitchEPBrake(int state)
if ((BrakeHandle == TBrakeHandle::St113) && (CabOccupied != 0))
{
if (state > 0)
temp = Handle->GetCP(); // TODO: przetlumaczyc
temp = Handle->GetEP(); // TODO: przetlumaczyc
else
temp = 0;
Hamulec->SetEPS(temp);
@@ -4519,7 +4540,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
&& (DirActive != 0)
&& (EpFuse)) // tu powinien byc jeszcze bezpiecznik EP i baterie -
// temp = (Handle as TFVel6).GetCP
temp = Handle->GetCP();
temp = Handle->GetEP();
else
temp = 0.0;
@@ -6571,33 +6592,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)))
{
auto const initialstate { MotorOverloadRelayHighThreshold };
Imax = ImaxHi;
MCS = true;
if (CabActive != 0)
SendCtrlToNext("MaxCurrentSwitch", 1, CabActive);
}
if (!State)
MotorOverloadRelayHighThreshold = State;
if (Imax == ImaxHi)
if (!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
{
Imax = ImaxLo;
MCS = true;
if (CabActive != 0)
SendCtrlToNext("MaxCurrentSwitch", 0, CabActive);
}
}
return MCS;
if( Notify != range_t::local ) {
SendCtrlToNext(
"MaxCurrentSwitch",
( State ? 1 : 0 ),
CabActive,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return State != initialstate;
}
// *************************************************************************************************
@@ -6739,19 +6750,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 )
@@ -11994,10 +12010,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);

View File

@@ -2282,6 +2282,11 @@ double TDriverHandle::GetCP()
return 0;
}
double TDriverHandle::GetEP()
{
return 0;
}
double TDriverHandle::GetSound(int i)
{
return 0;
@@ -2814,8 +2819,8 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
void TMHZ_K5P::Init(double Press)
{
CP = Press;
Time = true;
TimeEP = true;
Time = true;
TimeEP = true;
}
void TMHZ_K5P::SetReductor(double nAdj)
@@ -3133,9 +3138,11 @@ double TSt113::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
double ActFlowSpeed;
int BCP;
CP = PP;
BCP = lround(i_bcp);
EPS = BEP_K[BCP+1];
EPS = BEP_K[BCP];
if (BCP > 0)
BCP = BCP - 1;
@@ -3169,7 +3176,12 @@ double TSt113::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
double TSt113::GetCP()
{
return EPS;
return CP;
}
double TSt113::GetEP()
{
return EPS;
}
double TSt113::GetPos(int i)
@@ -3301,6 +3313,8 @@ double TFVel6::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
double dpMainValve;
double ActFlowSpeed;
CP = PP;
LimPP = Min0R(5 * int(i_bcp < 3.5), HP);
if ((i_bcp >= 3.5) && ((i_bcp < 4.3) || (i_bcp > 5.5)))
ActFlowSpeed = 0;
@@ -3334,7 +3348,12 @@ double TFVel6::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
double TFVel6::GetCP()
{
return EPS;
return CP;
}
double TFVel6::GetEP()
{
return EPS;
}
double TFVel6::GetPos(int i)
@@ -3366,6 +3385,8 @@ double TFVE408::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
double dpMainValve;
double ActFlowSpeed;
CP = PP;
LimPP = Min0R(5 * int(i_bcp < 6.5), HP);
if ((i_bcp >= 6.5) && ((i_bcp < 7.5) || (i_bcp > 9.5)))
ActFlowSpeed = 0;
@@ -3398,6 +3419,11 @@ double TFVE408::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
}
double TFVE408::GetCP()
{
return CP;
}
double TFVE408::GetEP()
{
return EPS;
}

View File

@@ -541,6 +541,7 @@ class TDriverHandle {
virtual double GetPF(double i_bcp, double PP, double HP, double dt, double ep);
virtual void Init(double Press);
virtual double GetCP();
virtual double GetEP();
virtual void SetReductor(double nAdj); //korekcja pozycji reduktora cisnienia
virtual double GetSound(int i); //pobranie glosnosci wybranego dzwieku
virtual double GetPos(int i); //pobranie numeru pozycji o zadanym kodzie (funkcji)
@@ -617,7 +618,7 @@ class TMHZ_EN57 : public TDriverHandle {
double GetSound(int i)/*override*/;
double GetPos(int i)/*override*/;
double GetCP()/*override*/;
double GetEP(double pos);
double GetEP(double pos);
void SetParams(bool AO, bool MO, double OverP, double, double OMP, double OPD);
inline TMHZ_EN57(void) :
TDriverHandle()
@@ -762,10 +763,11 @@ class TSt113 : public TH14K1 {
static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2];
static double const BEP_K[/*?*/ /*-1..5*/ (5) - (-1) + 1];
static double const pos_table[11]; // = {-1, 5, -1, 0, 2, 3, 4, 5, 0, 0, 1};
double CP = 0;
public:
double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/;
double GetCP()/*override*/;
double GetEP()/*override*/;
double GetPos(int i)/*override*/;
void Init(double Press)/*override*/;
@@ -830,10 +832,12 @@ class TFVel6 : public TDriverHandle {
private:
double EPS = 0.0;
static double const pos_table[ 11 ]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1};
double CP = 0.0;
public:
double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/;
double GetCP()/*override*/;
double GetEP()/*override*/;
double GetPos(int i)/*override*/;
double GetSound(int i)/*override*/;
void Init(double Press)/*override*/;
@@ -848,10 +852,12 @@ class TFVE408 : public TDriverHandle {
private:
double EPS = 0.0;
static double const pos_table[11]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1};
double CP = 0.0;
public:
double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/;
double GetCP()/*override*/;
double GetEP()/*override*/;
double GetPos(int i)/*override*/;
double GetSound(int i)/*override*/;
void Init(double Press)/*override*/;

View File

@@ -3823,7 +3823,7 @@ void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( true == Train->mvControlled->ShuntModeAllow ?
( false == Train->mvControlled->ShuntMode ) :
( Train->mvControlled->Imax < Train->mvControlled->ImaxHi ) ) ) {
( false == Train->mvControlled->MotorOverloadRelayHighThreshold ) ) ) {
// turn on
OnCommand_motoroverloadrelaythresholdsethigh( Train, Command );
}
@@ -3838,10 +3838,9 @@ void TTrain::OnCommand_motoroverloadrelaythresholdsetlow( TTrain *Train, command
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( true == Train->mvControlled->CurrentSwitch( false ) ) {
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( 0.0, Train->dsbSwitch );
}
Train->mvControlled->CurrentSwitch( false );
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( Train->mvControlled->MotorOverloadRelayHighThreshold ? 1 : 0, Train->dsbSwitch );
}
}
@@ -3849,10 +3848,9 @@ void TTrain::OnCommand_motoroverloadrelaythresholdsethigh( TTrain *Train, comman
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( true == Train->mvControlled->CurrentSwitch( true ) ) {
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( 1.0, Train->dsbSwitch );
}
Train->mvControlled->CurrentSwitch( true );
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( Train->mvControlled->MotorOverloadRelayHighThreshold ? 1 : 0, Train->dsbSwitch );
}
}
@@ -7223,6 +7221,14 @@ bool TTrain::Update( double const Deltatime )
ggBrakeProfileG.Update();
ggBrakeProfileR.Update();
ggBrakeOperationModeCtrl.Update();
ggMaxCurrentCtrl.UpdateValue(
( true == mvControlled->ShuntModeAllow ?
( true == mvControlled->ShuntMode ?
1.f :
0.f ) :
( mvControlled->MotorOverloadRelayHighThreshold ?
1.f :
0.f ) ) );
ggMaxCurrentCtrl.Update();
// NBMX wrzesien 2003 - drzwi
ggDoorLeftPermitButton.Update( lowvoltagepower );
@@ -8873,7 +8879,7 @@ void TTrain::set_cab_controls( int const Cab ) {
( true == mvControlled->ShuntMode ?
1.f :
0.f ) :
( mvControlled->Imax == mvControlled->ImaxHi ?
( mvControlled->MotorOverloadRelayHighThreshold ?
1.f :
0.f ) ) );
// lights

View File

@@ -783,7 +783,7 @@ TController::cue_action( locale::string const Action, float const Actionparamete
case locale::string::driver_hint_trainbrakeapply: {
if( AIControllFlag ) {
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach powino zostać wyłączone)
if( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
if( ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) && ( false == ForcePNBrake ) ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_EPB ) );
}
else {

View File

@@ -1171,7 +1171,11 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
"Brakes:\n highest pressure: " + to_string( mechanik.fReady, 2 ) + ( mechanik.Ready ? " (all brakes released)" : "" )
+ "\n activation threshold: " + to_string( mechanik.fAccThreshold, 2 )
+ ", delays: " + to_string( mechanik.fBrake_a0[ 0 ], 2 ) + " + " + to_string( mechanik.fBrake_a1[ 0 ], 2 )
+ "\n virtual brake position: " + to_string( mechanik.BrakeCtrlPosition, 2 );
+ "\n virtual brake position: " + to_string( mechanik.BrakeCtrlPosition, 2 )
+ "\n test stage: " + to_string( mechanik.DynamicBrakeTest )
+ ", applied at: " + to_string( mechanik.DBT_VelocityBrake, 0 )
+ ", release at: " + to_string( mechanik.DBT_VelocityRelease, 0 )
+ ", done at: " + to_string( mechanik.DBT_VelocityFinish, 0 );
Output.emplace_back( textline, Global.UITextColor );
@@ -1179,7 +1183,7 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
std::vector<std::string> const drivingflagnames {
"StopCloser", "StopPoint", "Active", "Press", "Connect", "Primary", "Late", "StopHere",
"StartHorn", "StartHornNow", "StartHornDone", "Oerlikons", "IncSpeed", "TrackEnd", "SwitchFound", "GuardSignal",
"Visibility", "DoorOpened", "PushPull", "SemaphorFound", "StopPointFound" /*"SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound"*/ };
"Visibility", "DoorOpened", "PushPull", "SignalFound", "StopPointFound" /*"SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound"*/ };
textline = "Driving flags:";
for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) {

View File

@@ -90,7 +90,14 @@ std::string Now();
double CompareTime( double t1h, double t1m, double t2h, double t2m );
/*funkcje logiczne*/
inline bool TestFlag( int const Flag, int const Value ) { return ( ( Flag & Value ) == Value ); }
inline
bool TestFlag( int const Flag, int const Value ) {
return ( ( Flag & Value ) == Value );
}
inline
bool TestFlagAny( int const Flag, int const Value ) {
return ( ( Flag & Value ) != 0 );
}
bool SetFlag( int &Flag, int const Value);
bool ClearFlag(int &Flag, int const Value);
@@ -117,8 +124,8 @@ std::string to_string(double Value, int precision, int width);
std::string to_hex_str( int const Value, int const width = 4 );
std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width );
inline std::string to_string(bool Value) {
inline
std::string to_string(bool Value) {
return ( Value == true ? "true" : "false" );
}