From f06f997946f4b719445f07574021c8cf5fd532f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 20 Aug 2017 20:22:04 +0200 Subject: [PATCH 1/2] AI: Better acceleration with ElectricSeriesMotor - motor current is set acording to ahdesion and fuse limit --- Driver.cpp | 139 +++++++++++++++++++++++++++++++++++------------------ Driver.h | 1 + 2 files changed, 94 insertions(+), 46 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 7442464d..42d3c222 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1720,7 +1720,41 @@ void TController::AutoRewident() fAccThreshold = -fBrake_a0[BrakeAccTableSize] - 1 * fBrake_a1[BrakeAccTableSize]; fBrakeReaction = 1.00 + fLength*0.005; } -}; +} + +double TController::ESMVelocity(bool Main) +{ + double fCurrentCoeff = 0.9; + double fFrictionCoeff = 0.85; + double ESMVel = 9999; + int MCPN = mvControlling->MainCtrlActualPos; + int SCPN = mvControlling->ScndCtrlActualPos; + if (Main) + MCPN += 1; + else + SCPN += 1; + if ((mvControlling->RList[MCPN].ScndAct < 255)&&(mvControlling->ScndCtrlActualPos==0)) + SCPN = mvControlling->RList[MCPN].ScndAct; + double FrictionMax = mvControlling->Mass*9.81*mvControlling->Adhesive(mvControlling->RunningTrack.friction)*fFrictionCoeff; + double IF = mvControlling->Imax; + double MS = 0; + double Fmax = 0; + for (int i = 0; i < 5; i++) + { + MS = mvControlling->MomentumF(IF, IF, SCPN); + Fmax = MS * mvControlling->RList[MCPN].Bn*mvControlling->RList[MCPN].Mn * 2 / mvControlling->WheelDiameter * mvControlling->Transmision.Ratio; + IF = 0.5*IF*(1 + FrictionMax/Fmax); + } + IF = std::min(IF, mvControlling->Imax*fCurrentCoeff); + double R = mvControlling->RList[MCPN].R + mvControlling->CircuitRes + mvControlling->RList[MCPN].Mn*mvControlling->WindingRes; + double pole = mvControlling->MotorParam[SCPN].fi * + std::max(abs(IF) / (abs(IF) + mvControlling->MotorParam[SCPN].Isat) - mvControlling->MotorParam[SCPN].fi0, 0.0); + double Us = abs(mvControlling->Voltage) - IF*R; + double ns = std::max(0.0, Us / (pole*mvControlling->RList[MCPN].Mn)); + ESMVel = ns * mvControlling->WheelDiameter*M_PI*3.6/mvControlling->Transmision.Ratio; + return ESMVel; +} +; int TController::CheckDirection() { @@ -2499,51 +2533,64 @@ 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)) - if (fabs(mvControlling->Im) < - (fReady < 0.4 ? mvControlling->Imin : mvControlling->IminLo)) - { // Ra: wywalał nadmiarowy, bo Im może być ujemne; jak nie odhamowany, to nie - // przesadzać z prądem - if ((mvOccupied->Vel <= 30) || - (mvControlling->Imax > mvControlling->ImaxLo) || - (fVoltage + fVoltage < - mvControlling->EnginePowerSource.CollectorParameters.MinV + - mvControlling->EnginePowerSource.CollectorParameters.MaxV)) - { // bocznik na szeregowej przy ciezkich bruttach albo przy wysokim rozruchu - // pod górę albo przy niskim napięciu - if (mvControlling->MainCtrlPos ? - mvControlling->RList[mvControlling->MainCtrlPos].R > 0.0 : - true) // oporowa - { - OK = (mvControlling->DelayCtrlFlag ? - true : - mvControlling->IncMainCtrl(1)); // kręcimy nastawnik jazdy - if ((OK) && - (mvControlling->MainCtrlPos == - 1)) // czekaj na 1 pozycji, zanim się nie włączą liniowe - iDrivigFlags |= moveIncSpeed; - else - iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi czekania - } - else // jeśli bezoporowa (z wyjątekiem 0) - OK = false; // to dać bocznik - } - else - { // przekroczone 30km/h, można wejść na jazdę równoległą - if (mvControlling->ScndCtrlPos) // jeśli ustawiony bocznik - if (mvControlling->MainCtrlPos < - mvControlling->MainCtrlPosNo - 1) // a nie jest ostatnia pozycja - mvControlling->DecScndCtrl(2); // to bocznik na zero po chamsku - // (ktoś miał to poprawić...) - OK = mvControlling->IncMainCtrl(1); - } - if ((mvControlling->MainCtrlPos > 2) && - (mvControlling->Im == 0)) // brak prądu na dalszych pozycjach - Need_TryAgain = true; // nie załączona lokomotywa albo wywalił - // nadmiarowy - else if (!OK) // nie da się wrzucić kolejnej pozycji - OK = mvControlling->IncScndCtrl(1); // to dać bocznik - } + if (Ready || (iDrivigFlags & movePress)) + { + bool scndctrl = ((mvOccupied->Vel <= 30) || + (mvControlling->Imax > mvControlling->ImaxLo) || + (fVoltage + fVoltage < + mvControlling->EnginePowerSource.CollectorParameters.MinV + + mvControlling->EnginePowerSource.CollectorParameters.MaxV) || + (mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo)); + scndctrl = ((scndctrl) && (mvControlling->MainCtrlPos > 1) && (mvControlling->RList[mvControlling->MainCtrlActualPos].R < 0.01)&& (mvControlling->ScndCtrlPos != mvControlling->ScndCtrlPosNo)); + double Vs = 99999; + if((mvControlling->MainCtrlPos != mvControlling->MainCtrlPosNo)||(mvControlling->ScndCtrlPos!=mvControlling->ScndCtrlPosNo)) + Vs = ESMVelocity(!scndctrl); + + if ((fabs(mvControlling->Im) < + (fReady < 0.4 ? mvControlling->Imin : mvControlling->IminLo))||(mvControlling->Vel>Vs)) + { // Ra: wywalał nadmiarowy, bo Im może być ujemne; jak nie odhamowany, to nie + // przesadzać z prądem + if ((mvOccupied->Vel <= 30) || + (mvControlling->Imax > mvControlling->ImaxLo) || + (fVoltage + fVoltage < + mvControlling->EnginePowerSource.CollectorParameters.MinV + + mvControlling->EnginePowerSource.CollectorParameters.MaxV)) + { // bocznik na szeregowej przy ciezkich bruttach albo przy wysokim rozruchu + // pod górę albo przy niskim napięciu + if (mvControlling->MainCtrlPos ? + mvControlling->RList[mvControlling->MainCtrlPos].R > 0.0 : + true) // oporowa + { + OK = (mvControlling->DelayCtrlFlag ? + true : + mvControlling->IncMainCtrl(1)); // kręcimy nastawnik jazdy + if ((OK) && + (mvControlling->MainCtrlPos == + 1)) // czekaj na 1 pozycji, zanim się nie włączą liniowe + iDrivigFlags |= moveIncSpeed; + else + iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi czekania + } + else // jeśli bezoporowa (z wyjątekiem 0) + OK = false; // to dać bocznik + } + else + { // przekroczone 30km/h, można wejść na jazdę równoległą + if (mvControlling->ScndCtrlPos) // jeśli ustawiony bocznik + if (mvControlling->MainCtrlPos < + mvControlling->MainCtrlPosNo - 1) // a nie jest ostatnia pozycja + mvControlling->DecScndCtrl(2); // to bocznik na zero po chamsku + // (ktoś miał to poprawić...) + OK = mvControlling->IncMainCtrl(1); + } + if ((mvControlling->MainCtrlPos > 2) && + (mvControlling->Im == 0)) // brak prądu na dalszych pozycjach + Need_TryAgain = true; // nie załączona lokomotywa albo wywalił + // nadmiarowy + else if (!OK) // nie da się wrzucić kolejnej pozycji + OK = mvControlling->IncScndCtrl(1); // to dać bocznik + } + } mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania break; case Dumb: diff --git a/Driver.h b/Driver.h index c21eb050..dc89a672 100644 --- a/Driver.h +++ b/Driver.h @@ -314,6 +314,7 @@ class TController void Activation(); // umieszczenie obsady w odpowiednim członie void ControllingSet(); // znajduje człon do sterowania void AutoRewident(); // ustawia hamulce w składzie + double ESMVelocity(bool Main); public: Mtable::TTrainParameters *Timetable() { From a0f705292af03e2fca5e980a63feb65512116770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 5 Sep 2017 20:14:58 +0200 Subject: [PATCH 2/2] New formula for adhesion, fixed some bugs in calculation of wheels' rotation --- Driver.cpp | 2 +- McZapkie/Mover.cpp | 52 ++++++++++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 42d3c222..12af005a 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -4821,7 +4821,7 @@ bool TController::UpdateSituation(double dt) else mvControlling->AntiSlippingButton(); ++iDriverFailCount; - mvControlling->SlippingWheels = false; // flaga już wykorzystana + //mvControlling->SlippingWheels = false; // flaga już wykorzystana } if (iDriverFailCount > maxdriverfails) { diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 1a371675..ba9b03f1 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3648,6 +3648,7 @@ double TMoverParameters::ComputeMass(void) void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) { int b; + double Fwheels = 0.0; if (PhysicActivation) { @@ -3707,19 +3708,35 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) else FTrain = 0; Fb = BrakeForce(RunningTrack); + Fwheels = FTrain - Fb * Sign(V); if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test - && ( std::max( std::abs( FTrain ), Fb ) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) // poslizg + && ( std::abs(Fwheels) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) // poslizg { SlippingWheels = true; } if( true == SlippingWheels ) { // TrainForce:=TrainForce-Fb; - nrot = ComputeRotatingWheel((FTrain - Fb * Sign(V) - FStand) / NAxles - + double temp_nrot = ComputeRotatingWheel(Fwheels - Sign(nrot * M_PI * WheelDiameter - V) * - Adhesive(RunningTrack.friction) * TotalMass, + Adhesive(RunningTrack.friction) * TotalMassxg, dt, nrot); - FTrain = Sign(FTrain) * TotalMassxg * Adhesive(RunningTrack.friction); - Fb = std::min(Fb, TotalMassxg * Adhesive(RunningTrack.friction)); + Fwheels = Sign(nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction); + if (Fwheels*Sign(V)>0) + { + FTrain = Fwheels - Fb; + } + else + { + Fb = FTrain - Fwheels; + } + if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0) + { + SlippingWheels = false; + temp_nrot = V / M_PI / WheelDiameter; + } + + + nrot = temp_nrot; } // else SlippingWheels:=false; // FStand:=0; @@ -3728,7 +3745,7 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) (Couplers[b].CouplerType<>Articulated)*/ { // doliczenie sił z innych pojazdów Couplers[b].CForce = CouplerForce(b, dt); - FTrain += Couplers[b].CForce; + FTrain += Couplers[b].CForce; } else Couplers[b].CForce = 0; @@ -3862,16 +3879,6 @@ double TMoverParameters::BrakeForce(const TTrackParam &Track) } else UnitBrakeForce = K * 1000.0; - if (((double)NBpA * UnitBrakeForce > TotalMassxg * Adhesive(RunningTrack.friction) / NAxles) && - (abs(V) > 0.001)) - // poslizg - { - // Fb = Adhesive(Track.friction) * Mass * g; - SlippingWheels = true; - } - //{ else - // begin - //{ SlippingWheels:=false;} // if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then // Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os} // else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder @@ -3907,7 +3914,10 @@ double TMoverParameters::FrictionForce(double R, int TDamage) // ************************************************************************************************* double TMoverParameters::Adhesive(double staticfriction) { - double adhesion; + double adhesion = 0.0; + const double adh_factor = 0.25; //współczynnik określający, jak bardzo spada tarcie przy poślizgu + const double slipfactor = 0.33; //współczynnik określający, jak szybko spada tarcie przy poślizgu + const double sandfactor = 1.25; //współczynnik określający, jak mocno pomaga piasek /* // ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS? // w kazdym razie zaciemni kod na pewno :) @@ -3930,6 +3940,7 @@ double TMoverParameters::Adhesive(double staticfriction) // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 return adhesion; */ + /* //wersja druga if( true == SlippingWheels ) { if( true == SandDose ) { adhesion = 0.48; } @@ -3940,7 +3951,12 @@ double TMoverParameters::Adhesive(double staticfriction) if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); } else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); } } - adhesion *= ( 11.0 - 2 * Random() ) / 10.0; + adhesion *= ( 11.0 - 2 * Random() ) / 10.0; */ + //wersja3 by youBy - uwzględnia naturalne mikropoślizgi i wpływ piasecznicy, usuwa losowość z pojazdu + double Vwheels = nrot * M_PI * WheelDiameter; // predkosc liniowa koła wynikająca z obrotowej + double deltaV = V - Vwheels; //poślizg - różnica prędkości w punkcie styku koła i szyny + deltaV = std::max(0.0, std::abs(deltaV) - 0.25); //mikropoślizgi do ok. 0,25 m/s nie zrywają przyczepności + adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose? sandfactor : 1) - (1 - adh_factor)*(deltaV / (deltaV + slipfactor))); return adhesion; }