From 5d7206b3693d39804517d425f0f0317f37b645b9 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sat, 2 Sep 2017 17:18:26 +0200 Subject: [PATCH] scan table improvements from refs/remotes/firleju/mover_in_c++ --- Driver.cpp | 355 +++++++++++++++++++++++++++++------------------------ Driver.h | 28 ++++- DynObj.cpp | 2 + mtable.cpp | 27 ++++ mtable.h | 1 + version.h | 2 +- 6 files changed, 252 insertions(+), 163 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 25f89d9d..85c35407 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -106,10 +106,57 @@ std::string StopReasonTable[] = { "Error", // stopError //z powodu błędu w obliczeniu drogi hamowania }; +double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double start_dist, int iter = 0, bool back = false) +{ + std::shared_ptr segment = track->CurrentSegment(); + vector3 pos_event = event->PositionGet(); + double len1, len2; + double sd = scan_dir; + double seg_len = scan_dir > 0 ? 0.0 : 1.0; + double dzielnik = 1.0 / segment->GetLength();// rozdzielczosc mniej wiecej 1m + int krok = 0; // krok obliczeniowy do sprawdzania czy odwracamy + len2 = (pos_event - segment->FastGetPoint(seg_len)).Length(); + do + { + len1 = len2; + seg_len += scan_dir > 0 ? dzielnik : -dzielnik; + len2 = (pos_event - segment->FastGetPoint(seg_len)).Length(); + krok++; + } while ((len1 > len2) && (seg_len >= dzielnik && (seg_len <= (1 - dzielnik)))); + //trzeba sprawdzić czy seg_len nie osiągnął skrajnych wartości, bo wtedy + // trzeba sprawdzić tor obok + if (1 == krok) + sd = -sd; // jeśli tylko jeden krok tzn, że event przy poprzednim sprawdzaym torze + if (((seg_len <= dzielnik) || (seg_len > (1 - dzielnik))) && (iter < 3)) + { // przejście na inny tor + track = track->Neightbour(int(sd), sd); + start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength(); + return GetDistanceToEvent(track, event, sd, start_dist, ++iter, 1 == krok ? true : false); + } + else + { // obliczenie mojego toru + seg_len -= scan_dir > 0 ? dzielnik : -dzielnik; //trzeba wrócić do pozycji len1 + seg_len = scan_dir < 0 ? 1 - seg_len : seg_len; + seg_len = back ? 1 - seg_len : seg_len; // odwracamy jeśli idzie do tyłu + start_dist -= back ? segment->GetLength() : 0; + return start_dist + (segment->GetLength() * seg_len); + } +}; + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- +TSpeedPos::TSpeedPos(TTrack *track, double dist, int flag) +{ + Set(track, dist, flag); +}; + +TSpeedPos::TSpeedPos(TEvent *event, double dist, TOrders order) +{ + Set(event, dist, order); +}; + void TSpeedPos::Clear() { iFlags = 0; // brak flag to brak reakcji @@ -187,64 +234,10 @@ void TSpeedPos::CommandCheck() } }; -bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len ) -{ // przeliczenie odległości od punktu (*p), w kierunku (*dir), zaczynając od pojazdu - // dla kolejnych pozycji podawane są współrzędne poprzedniego obiektu w (*p) - vector3 v = vPos - *p; // wektor od poprzedniego obiektu (albo pojazdu) do punktu zmiany - fDist = v.Length(); // długość wektora to odległość pomiędzy czołem a sygnałem albo początkiem toru - if (len == 0.0) - { // jeżeli liczymy względem pojazdu - double angle; - if( dir ) { - angle = - glm::dot( - glm::normalize( glm::make_vec3( &v.x ) ), // towards target - glm::normalize( glm::make_vec3( &dir->x ) ) ); // orientation at scan point - } - else { - angle = fDist; - } - if (angle < 0.0) // iloczyn skalarny jest ujemny, gdy punkt jest z tyłu - { // jeśli coś jest z tyłu, to dokładna odległość nie ma już większego znaczenia - fDist = -fDist; // potrzebne do badania wyjechania składem poza ograniczenie - if (iFlags & spElapsed) { - // jeśli minięty (musi być minięty również przez końcówkę składu) - // NOTE: empty branch, why? - } - else - { - // minięty - będziemy liczyć odległość względem przeciwnego końca - // toru (nadal może być z przodu i ograniczać) - iFlags ^= spElapsed; - if ((iFlags & (spEnd | spTrack | spEnabled)) == (spTrack | spEnabled)) { - // tylko jeśli (istotny) tor, bo eventy są punktowe - if (trTrack) { - // może być NULL, jeśli koniec toru (????) - vPos = - (iFlags & spReverse) ? - trTrack->CurrentSegment()->FastGetPoint_1() : // drugi koniec istotny - trTrack->CurrentSegment()->FastGetPoint_0(); - } - } - } - } - else { - if( fDist < 50.0 ) { - // old sceneries use trick of placing 'helper' semaphores underground, which can lead to vehicles running over them instead of stopping in front of them - // to account for it at short distances we redo distance calculation on 2d plane - fDist = glm::length( glm::vec3( v.x, 0.0, v.z ) ); - } - } - } - - if (fDist > 0.0) // nie może być 0.0, a przypadkiem mogło by się trafić i było by źle - if ((iFlags & spElapsed) == 0) // 32 ustawione, gdy obiekt już został minięty - { // jeśli obiekt nie został minięty, można od niego zliczać narastająco (inaczej może być - // problem z wektorem kierunku) - len = fDist = len + fDist; // zliczanie dlugości narastająco - *p = vPos; // nowy punkt odniesienia - *dir = Normalize(v); // nowy wektor kierunku od poprzedniego obiektu do aktualnego - } +bool TSpeedPos::Update() +{ + if( fDist < 0.0 ) + iFlags |= spElapsed; // trzeba zazanaczyć, że minięty if (iFlags & spTrack) // road/track { if (trTrack) { @@ -307,12 +300,6 @@ std::string TSpeedPos::TableText() { // o ile pozycja istotna return "Flags:" + to_hex_str(iFlags, 8) + ", Dist:" + to_string(fDist, 1, 6) + ", Vel:" + (fVelNext == -1.0 ? " - " : to_string(static_cast(fVelNext), 0, 3)) + ", Name:" + GetName(); - //if (iFlags & spTrack) // jeśli tor - // return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + - // ", Vel=" + AnsiString(fVelNext) + ", Track=" + trTrack->NameGet(); - //else if (iFlags & spEvent) // jeśli event - // return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) + - // ", Vel=" + AnsiString(fVelNext) + ", Event=" + evEvent->asName; } return "Empty"; } @@ -376,11 +363,6 @@ void TSpeedPos::Set(TTrack *track, double dist, int flag) fVelNext = (trTrack->iCategoryFlag & 1) ? 0.0 : 20.0; // jeśli koniec, to pociąg stój, a samochód zwolnij -/* - vPos = (((iFlags & spReverse) != 0) != ((iFlags & spEnd) != 0)) ? - trTrack->CurrentSegment()->FastGetPoint_1() : - trTrack->CurrentSegment()->FastGetPoint_0(); -*/ vPos = ( iFlags & spReverse ) ? trTrack->CurrentSegment()->FastGetPoint_1() : @@ -455,16 +437,21 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) pTrack = pVehicle->RaTrackGet(); // odcinek, na którym stoi fTrackLength = pVehicle->RaTranslationGet(); // pozycja na tym torze (odległość od Point1) fLastDir = pVehicle->DirectionGet() * pVehicle->RaDirectionGet(); // ustalenie kierunku skanowania na torze - if( fLastDir > 0.0 ) { + double odl_czola_od_wozka = (pVehicle->AxlePositionGet() - pVehicle->RearPosition()).Length(); + if( fLastDir < 0.0 ) { // jeśli w kierunku Point2 toru fTrackLength = pTrack->Length() - fTrackLength; // przeskanowana zostanie odległość do Point2 } + fTrackLength -= odl_czola_od_wozka; + fCurrentDistance = -fLength - fTrackLength; // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu fLastVel = pTrack->VelocityGet(); // aktualna prędkość sSpeedTable.clear(); iLast = -1; tLast = nullptr; //żaden nie sprawdzony SemNextIndex = -1; SemNextStopIndex = -1; + fTrackLength = pTrack->Length(); //skasowanie zmian w zmiennej żeby poprawnie liczyło w dalszych krokach + MoveDistanceReset(); // AI startuje 1s po zaczęciu jazdy i mógł już coś przejechać } else { if( iTableDirection == 0 ) { return; } @@ -494,21 +481,14 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) } } } + auto const &lastspeedpoint = sSpeedTable[ iLast ]; pTrack = lastspeedpoint.trTrack; assert( pTrack != nullptr ); // flaga ustawiona, gdy Point2 toru jest blizej - fLastDir = ( - TestFlag( lastspeedpoint.iFlags, spReverse ) ? - -1.0 : - 1.0 ); - // aktualna odleglosc do jego Point1 - fCurrentDistance = lastspeedpoint.fDist; - // nie doliczac dlugosci gdy: miniety początek lub jazda do konca toru - fTrackLength = ( - ( ( lastspeedpoint.iFlags & ( spElapsed | spEnd ) ) != 0 ) ? - 0.0 : - pTrack->Length() ); + fLastDir = lastspeedpoint.iFlags & spReverse ? -1.0 : 1.0; + fCurrentDistance = lastspeedpoint.fDist; // aktualna odleglosc do jego Point1 + fTrackLength = pTrack->Length(); } if( iTableDirection == 0 ) { @@ -516,11 +496,6 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) return; } - if( fCurrentDistance >= fDistance ) { - // all done - return; - } - while (fCurrentDistance < fDistance) { if (pTrack != tLast) // ostatni zapisany w tabelce nie był jeszcze sprawdzony @@ -532,70 +507,69 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) if( ( pEvent = CheckTrackEvent( fLastDir, pTrack ) ) != nullptr ) // jeśli jest semafor na tym torze { // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne if (TableNotFound(pEvent)) // jeśli nie ma - if( TableAddNew() ) - { - if( Global::iWriteLogEnabled & 8 ) { - WriteLog( "Speed table for " + OwnerName() + " found new event, " + pEvent->asName ); - } - auto &newspeedpoint = sSpeedTable[ iLast ]; - if( newspeedpoint.Set( pEvent, fCurrentDistance, OrderCurrentGet() ) ) { + { + TableAddNew(); // zawsze jest true - fDistance = fCurrentDistance; // jeśli sygnał stop, to nie ma potrzeby dalej skanować - SemNextStopIndex = iLast; - if( SemNextIndex == -1 ) { - SemNextIndex = iLast; - } - if( Global::iWriteLogEnabled & 8 ) { - WriteLog( "(stop signal from " - + ( SemNextStopIndex != -1 ? sSpeedTable[SemNextStopIndex].GetName() : "unknown semaphor" ) - + ")" ); - } + if (Global::iWriteLogEnabled & 8) { + WriteLog("Speed table for " + OwnerName() + " found new event, " + pEvent->asName); + } + auto &newspeedpoint = sSpeedTable[iLast]; + if (newspeedpoint.Set(pEvent, GetDistanceToEvent(pTrack, pEvent, fLastDir, fCurrentDistance), OrderCurrentGet())) { + + fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować + SemNextStopIndex = iLast; + if (SemNextIndex == -1) { + SemNextIndex = iLast; } - else { - if( ( true == newspeedpoint.IsProperSemaphor( OrderCurrentGet() ) ) - && ( SemNextIndex == -1 ) ) { - SemNextIndex = iLast; // sprawdzamy czy pierwszy na drodze - } - if( Global::iWriteLogEnabled & 8 ) { - WriteLog( "(forward signal for " - + ( SemNextIndex != -1 ? sSpeedTable[SemNextIndex].GetName() : "unknown semaphor" ) - + ")" ); - } + if (Global::iWriteLogEnabled & 8) { + WriteLog("(stop signal from " + + (SemNextStopIndex != -1 ? sSpeedTable[SemNextStopIndex].GetName() : "unknown semaphor") + + ")"); } } + else { + if ((true == newspeedpoint.IsProperSemaphor(OrderCurrentGet())) + && (SemNextIndex == -1)) { + SemNextIndex = iLast; // sprawdzamy czy pierwszy na drodze + } + if (Global::iWriteLogEnabled & 8) { + WriteLog("(forward signal for " + + (SemNextIndex != -1 ? sSpeedTable[SemNextIndex].GetName() : "unknown semaphor") + + ")"); + } + } + } } // event dodajemy najpierw, żeby móc sprawdzić, czy tor został dodany po odczytaniu prędkości następnego if( ( pTrack->VelocityGet() == 0.0 ) // zatrzymanie || ( pTrack->iAction ) // jeśli tor ma własności istotne dla skanowania - || ( pTrack->VelocityGet() != fLastVel ) ) { // następuje zmiana prędkości - // odcinek dodajemy do tabelki, gdy jest istotny dla ruchu - if (TableAddNew()) - { // teraz dodatkowo zapamiętanie wybranego segmentu dla skrzyżowania - sSpeedTable[ iLast ].Set( - pTrack, fCurrentDistance, - ( fLastDir < 0 ? - spEnabled | spReverse : - spEnabled ) ); // dodanie odcinka do tabelki z flagą kierunku wejścia - if (pTrack->eType == tt_Cross) { - // na skrzyżowaniach trzeba wybrać segment, po którym pojedzie pojazd - // dopiero tutaj jest ustalany kierunek segmentu na skrzyżowaniu - sSpeedTable[iLast].iFlags |= - ( ( pTrack->CrossSegment( - ( fLastDir < 0 ? - tLast->iPrevDirection : - tLast->iNextDirection ), - iRouteWanted ) & 0xf ) << 28 ); // ostatnie 4 bity pola flag - sSpeedTable[iLast].iFlags &= ~spReverse; // usunięcie flagi kierunku, bo może być błędna - if( sSpeedTable[ iLast ].iFlags < 0 ) { - sSpeedTable[ iLast ].iFlags |= spReverse; // ustawienie flagi kierunku na podstawie wybranego segmentu - } - if( int( fLastDir ) * sSpeedTable[ iLast ].iFlags < 0 ) { - fLastDir = -fLastDir; - } - if( AIControllFlag ) { - // dla AI na razie losujemy kierunek na kolejnym skrzyżowaniu - iRouteWanted = 1 + Random( 3 ); - } + || ( pTrack->VelocityGet() != fLastVel ) ) // następuje zmiana prędkości + { // odcinek dodajemy do tabelki, gdy jest istotny dla ruchu + TableAddNew(); + sSpeedTable[ iLast ].Set( + pTrack, fCurrentDistance, + ( fLastDir < 0 ? + spEnabled | spReverse : + spEnabled ) ); // dodanie odcinka do tabelki z flagą kierunku wejścia + if (pTrack->eType == tt_Cross) { + // na skrzyżowaniach trzeba wybrać segment, po którym pojedzie pojazd + // dopiero tutaj jest ustalany kierunek segmentu na skrzyżowaniu + sSpeedTable[iLast].iFlags |= + ((pTrack->CrossSegment( + (fLastDir < 0 ? + tLast->iPrevDirection : + tLast->iNextDirection), + iRouteWanted) & 0xf) << 28); // ostatnie 4 bity pola flag + sSpeedTable[iLast].iFlags &= ~spReverse; // usunięcie flagi kierunku, bo może być błędna + if (sSpeedTable[iLast].iFlags < 0) { + sSpeedTable[iLast].iFlags |= spReverse; // ustawienie flagi kierunku na podstawie wybranego segmentu + } + if (int(fLastDir) * sSpeedTable[iLast].iFlags < 0) { + fLastDir = -fLastDir; + } + if (AIControllFlag) { + // dla AI na razie losujemy kierunek na kolejnym skrzyżowaniu + iRouteWanted = 1 + Random(3); } } } @@ -626,14 +600,20 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) if (pTrack != nullptr ) { // jeśli kolejny istnieje if( tLast != nullptr ) { + + if( ( tLast->VelocityGet() > 0 ) + && ( ( tLast->VelocityGet() < pTrack->VelocityGet() ) + || ( pTrack->VelocityGet() < 0 ) ) ) { +/* if( ( pTrack->VelocityGet() < 0 ? tLast->VelocityGet() > 0 : pTrack->VelocityGet() > tLast->VelocityGet() ) ) { // jeśli kolejny ma większą prędkość niż poprzedni, to zapamiętać poprzedni (do czasu wyjechania) + if( ( ( ( iLast != -1 ) && ( TestFlag( sSpeedTable[ iLast ].iFlags, spEnabled | spTrack ) ) ) ? - ( sSpeedTable[ iLast ].trTrack != tLast ) : - true ) ) { + ( sSpeedTable[ iLast ].trTrack != tLast ) : + true ) ) { // jeśli nie był dodany do tabelki if( TableAddNew() ) { // zapisanie toru z ograniczeniem prędkości @@ -646,6 +626,24 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) spEnabled | spReverse ); } } +*/ + if( ( iLast != -1 ) + && ( sSpeedTable[ iLast ].trTrack == tLast ) ) { + // if the track is already in the table we only need to mark it as relevant + sSpeedTable[ iLast ].iFlags |= spEnabled; + } + else { + // otherwise add it + TableAddNew(); + sSpeedTable[ iLast ].Set( + tLast, + fCurrentDistance - fTrackLength, // by now the current distance points to beginning of next track + ( fLastDir > 0 ? + pTrack->iPrevDirection : + pTrack->iNextDirection ) ? + spEnabled : + spEnabled | spReverse ); + } } } // zwiększenie skanowanej odległości tylko jeśli istnieje dalszy tor @@ -690,32 +688,39 @@ void TController::TableCheck(double fDistance) if( iTableDirection != iDirection ) { // jak zmiana kierunku, to skanujemy od końca składu TableTraceRoute( fDistance, pVehicles[ 1 ] ); + TableSort(); } else if (iTableDirection) { // trzeba sprawdzić, czy coś się zmieniło - vector3 dir = pVehicles[0]->VectorFront() * pVehicles[0]->DirectionGet(); // wektor kierunku jazdy - vector3 pos = pVehicles[0]->HeadPosition(); // zaczynamy od pozycji pojazdu - double len = 0.0; // odległość będziemy zliczać narastająco + for (auto &sp : sSpeedTable) + { + sp.UpdateDistance(MoveDistanceGet()); // aktualizacja odległości dla wszystkich pozycji tabeli + } + MoveDistanceReset(); // kasowanie odległości po aktualizacji tabelki for( int i = 0; i < iLast; ++i ) { // aktualizacja rekordów z wyjątkiem ostatniego if (sSpeedTable[i].iFlags & spEnabled) // jeśli pozycja istotna { - if(sSpeedTable[i].Update( &pos, &dir, len )) + if (sSpeedTable[i].Update()) { if( Global::iWriteLogEnabled & 8 ) { WriteLog( "Speed table for " + OwnerName() + " detected switch change at " + sSpeedTable[ i ].trTrack->NameGet() + " (generating fresh trace)" ); } - // NOTE: dirty trick to perform scan from the beginning - // a workaround for current routines not preserving properly scan distance if started from the middle - // and the scan extending far beyond specified limit as result - iTableDirection = -iDirection; + // usuwamy wszystko za tym torem + while (sSpeedTable.back().trTrack != sSpeedTable[i].trTrack) + { // usuwamy wszystko dopóki nie trafimy na tą zwrotnicę + sSpeedTable.pop_back(); + --iLast; + } + tLast = sSpeedTable[ i ].trTrack; TableTraceRoute( fDistance, pVehicles[ 1 ] ); + TableSort(); // nie kontynuujemy pętli, trzeba doskanować ciąg dalszy break; } if (sSpeedTable[i].iFlags & spTrack) // jeśli odcinek { - if (sSpeedTable[i].fDist + sSpeedTable[i].trTrack->Length() < -fLength) // a skład wyjechał całą długością poza + if( sSpeedTable[ i ].fDist + sSpeedTable[ i ].trTrack->Length() < -fLength ) // a skład wyjechał całą długością poza { // degradacja pozycji sSpeedTable[i].iFlags &= ~spEnabled; // nie liczy się } @@ -743,10 +748,11 @@ void TController::TableCheck(double fDistance) } } } - sSpeedTable[iLast].Update( &pos, &dir, len ); // aktualizacja ostatniego + sSpeedTable[iLast].Update(); // aktualizacja ostatniego // WriteLog("TableCheck: Upate last track. Dist=" + AnsiString(sSpeedTable[iLast].fDist)); if( sSpeedTable[ iLast ].fDist < fDistance ) { TableTraceRoute( fDistance, pVehicles[ 1 ] ); // doskanowanie dalszego odcinka + TableSort(); } // garbage collection TablePurger(); @@ -777,7 +783,14 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them if ( ToLower(sSpeedTable[i].evEvent->CommandGet()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 ) { // jeśli nazwa nie jest zgodna - if( sSpeedTable[ i ].fDist < -fLength ) { + if (sSpeedTable[i].fDist < 300.0 && sSpeedTable[i].fDist > 0) // tylko jeśli W4 jest blisko, przy dwóch może zaczać szaleć + { + // porównuje do następnej stacji, więc trzeba przewinąć do poprzedniej + // nastepnie ustawić następną na aktualną tak żeby prawidłowo ją obsłużył w następnym kroku + TrainParams->RewindTimeTable(sSpeedTable[i].evEvent->CommandGet()); + asNextStop = TrainParams->NextStop(); + } + else if( sSpeedTable[ i ].fDist < -fLength ) { // jeśli został przejechany sSpeedTable[ i ].iFlags = 0; // to można usunąć (nie mogą być usuwane w skanowaniu) } @@ -1324,7 +1337,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN (OrderCurrentGet() & Obey_train)) VelSignalLast = -1.0; // jeśli mieliśmy ograniczenie z semafora i nie ma przed nami - if (VelSignalLast >= 0.0) //analiza spisanych z tabelki ograniczeń i nadpisanie aktualnego + //analiza spisanych z tabelki ograniczeń i nadpisanie aktualnego + if (VelSignalLast >= 0.0) fVelDes = Min0R(fVelDes, VelSignalLast); if (VelLimitLast >= 0.0) fVelDes = Min0R(fVelDes, VelLimitLast); @@ -1340,7 +1354,7 @@ float TController::braking_distance_multiplier( float const Targetvelocity ) { if( Targetvelocity > 65.f ) { return 1.f; } - if( Targetvelocity < 5.f ) { return 1.f; } + if( Targetvelocity < 5.f ) { return 1.f; } // stretch the braking distance up to 3 times; the lower the speed, the greater the stretch return interpolate( 3.f, 1.f, ( Targetvelocity - 5.f ) / 60.f ); } @@ -1404,6 +1418,29 @@ void TController::TablePurger() iLast = sSpeedTable.size() - 1; }; +void TController::TableSort() +{ + TSpeedPos sp_temp = TSpeedPos(); // uzywany do przenoszenia + for (std::size_t i = 0; i < (iLast - 1) && iLast > 0; ++i) + { // pętla tylko do dwóch pozycji od końca bo ostatniej nie modyfikujemy + if (sSpeedTable[i].fDist > sSpeedTable[i + 1].fDist) + { // jesli pozycja wcześniejsza jest dalej to źle + sp_temp = sSpeedTable[i + 1]; + sSpeedTable[i + 1] = sSpeedTable[i]; // zamiana + sSpeedTable[i] = sp_temp; + // jeszcze sprawdzenie czy pozycja nie była indeksowana dla eventów + if (SemNextIndex == i) + ++SemNextIndex; + else if (SemNextIndex == i + 1) + --SemNextIndex; + if (SemNextStopIndex == i) + ++SemNextStopIndex; + else if (SemNextStopIndex == i + 1) + --SemNextStopIndex; + } + } +} + //--------------------------------------------------------------------------- TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche, bool primary) :// czy ma aktywnie prowadzić? @@ -2376,7 +2413,7 @@ bool TController::IncBrake() } else { if( mvOccupied->BrakeCtrlPos + 1 == mvOccupied->BrakeCtrlPosNo ) { - if (AccDesired < -0.75) // hamowanie nagle + if (AccDesired < -1.5) // hamowanie nagle OK = mvOccupied->BrakeLevelAdd(1.0); else OK = false; @@ -4740,7 +4777,7 @@ TController::UpdateSituation(double dt) { || ( ( AccDesired < fAccGravity - 0.1 ) && ( AbsAccS > AccDesired + fBrake_a1[ 0 ] ) ) ) { // u góry ustawia się hamowanie na fAccThreshold if( ( fBrakeTime < 0.0 ) - || ( AccDesired < fAccGravity - 0.75 ) + || ( AccDesired < fAccGravity - 0.5 ) || ( mvOccupied->BrakeCtrlPos <= 0 ) ) { // jeśli upłynął czas reakcji hamulca, chyba że nagłe albo luzował if( true == IncBrake() ) { diff --git a/Driver.h b/Driver.h index ea68da69..dfb24ec8 100644 --- a/Driver.h +++ b/Driver.h @@ -143,8 +143,16 @@ class TSpeedPos void CommandCheck(); public: + TSpeedPos(TTrack *track, double dist, int flag); + TSpeedPos(TEvent *event, double dist, TOrders order); + TSpeedPos() = default; void Clear(); - bool Update(vector3 *p, vector3 *dir, double &len ); + bool Update(); + // aktualizuje odległość we wpisie + inline + void + UpdateDistance( double dist ) { + fDist -= dist; } bool Set(TEvent *e, double d, TOrders order = Wait_for_orders); void Set(TTrack *t, double d, int f); std::string TableText(); @@ -174,7 +182,8 @@ class TController TEvent *eSignSkip = nullptr; // można pominąć ten SBL po zatrzymaniu std::size_t SemNextIndex{ std::size_t(-1) }; std::size_t SemNextStopIndex{ std::size_t( -1 ) }; - private: // parametry aktualnego składu + double dMoveLen = 0.0; // odległość przejechana od ostatniego sprawdzenia tabelki +private: // parametry aktualnego składu double fLength = 0.0; // długość składu (do wyciągania z ograniczeń) double fMass = 0.0; // całkowita masa do liczenia stycznej składowej grawitacji double fAccGravity = 0.0; // przyspieszenie składowej stycznej grawitacji @@ -372,7 +381,20 @@ class TController float braking_distance_multiplier( float const Targetvelocity ); void TablePurger(); -public: + void TableSort(); + inline double MoveDistanceGet() + { + return dMoveLen; + } + inline void MoveDistanceReset() + { + dMoveLen = 0.0; + } + public: + inline void MoveDistanceAdd(double distance) + { + dMoveLen += distance * iDirection; //jak jedzie do tyłu to trzeba uwzględniać, że distance jest ujemna + } std::size_t TableSize() const { return sSpeedTable.size(); } void TableClear(); int TableDirection() { return iTableDirection; } diff --git a/DynObj.cpp b/DynObj.cpp index 3c570da5..f2926f88 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2939,6 +2939,8 @@ bool TDynamicObject::Update(double dt, double dt1) MoverParameters->AccN *= -ABuGetDirection(); */ // if (dDOMoveLen!=0.0) //Ra: nie może być, bo blokuje Event0 + if( Mechanik ) + Mechanik->MoveDistanceAdd( dDOMoveLen ); // dodanie aktualnego przemieszczenia Move(dDOMoveLen); if (!bEnabled) // usuwane pojazdy nie mają toru { // pojazd do usunięcia diff --git a/mtable.cpp b/mtable.cpp index ea9b2a6c..34faea9f 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -104,6 +104,33 @@ bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &New return OK; /*czy jest nastepna stacja*/ } +void Mtable::TTrainParameters::RewindTimeTable(std::string actualStationName) +{ + //actualStationName = ToLower(actualStationName); // na małe znaki + if (int s = actualStationName.find("PassengerStopPoint:") != std::string::npos) + { + actualStationName = ToLower(actualStationName.substr(s + 19)); + } + for (int i = 1; i <= StationCount; i++) + { // przechodzimy po całej tabelce i sprawdzamy nazwy stacji (bez pierwszej) + if (ToLower(TimeTable[i].StationName) == actualStationName) + { // nazwa stacji zgodna + // więc ustawiamy na poprzednią, żeby w następnym kroku poprawnie obsłużyć + StationIndex = i - 1; + if (StationIndex < + StationCount) // Ra: "<", bo dodaje 1 przy przejściu do następnej stacji + { // jeśli nie ostatnia stacja + NextStationName = TimeTable[StationIndex + 1].StationName; // zapamiętanie nazwy + TTVmax = TimeTable[StationIndex + 1] + .vmax; // Ra: nowa prędkość rozkładowa na kolejnym odcinku + } + else // gdy ostatnia stacja + NextStationName = ""; // nie ma następnej stacji + break; // znaleźliśmy więc kończymy + } + } +} + void TTrainParameters::StationIndexInc() { // przejście do następnej pozycji StationIndex<=StationCount ++StationIndex; diff --git a/mtable.h b/mtable.h index 958a4864..f5471f81 100644 --- a/mtable.h +++ b/mtable.h @@ -76,6 +76,7 @@ class TTrainParameters bool IsTimeToGo(double hh, double mm); bool UpdateMTable(double hh, double mm, std::string const &NewName); bool UpdateMTable( simulation_time const &Time, std::string const &NewName ); + void RewindTimeTable( std::string actualStationName ); TTrainParameters( std::string const &NewTrainName ); void NewName(std::string const &NewTrainName); void UpdateVelocity(int StationCount, double vActual); diff --git a/version.h b/version.h index 5b91b3dc..7043a400 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 831 +#define VERSION_MINOR 902 #define VERSION_REVISION 0