diff --git a/Driver.cpp b/Driver.cpp index 72a1d6c4..7900fa96 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -46,6 +46,45 @@ ProjectEventOnTrack( TEvent const *Event, TTrack const *Track, double const Dire ( 1.0 - nearestpoint ) * segment->GetLength() ); // measure from point2 }; +double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double start_dist, int iter = 0, bool back = false) +{ + if( track == nullptr ) { return start_dist; } + + auto const segment = track->CurrentSegment(); + vector3 const pos_event = event->PositionGet(); + double len1, len2; + double sd = scan_dir; + double seg_len = scan_dir > 0 ? 0.0 : 1.0; + double const 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)).LengthSquared(); + do + { + len1 = len2; + seg_len += scan_dir > 0 ? dzielnik : -dzielnik; + len2 = (pos_event - segment->FastGetPoint(seg_len)).LengthSquared(); + 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); + } +}; + /* Moduł obsługujący sterowanie pojazdami (składami pociągów, samochodami). @@ -491,10 +530,16 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) WriteLog("Speed table for " + OwnerName() + " found new event, " + pEvent->asName); } auto &newspeedpoint = sSpeedTable[iLast]; +/* if( newspeedpoint.Set( pEvent, fCurrentDistance + ProjectEventOnTrack( pEvent, pTrack, fLastDir ), OrderCurrentGet() ) ) { +*/ + 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; @@ -3622,7 +3667,7 @@ TController::UpdateSituation(double dt) { // towards coupler 0 if( ( mvOccupied->V * iDirection < 0.0 ) || ( ( rearvehicle->NextConnected != nullptr ) - && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == ctrain_virtual ) ) ) { + && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == coupling::faux ) ) ) { // scan behind if we're moving backward, or if we had something connected there and are moving away rearvehicle->ABuScanObjects( ( pVehicle->DirectionGet() == rearvehicle->DirectionGet() ? @@ -3640,7 +3685,7 @@ TController::UpdateSituation(double dt) { // towards coupler 1 if( ( mvOccupied->V * iDirection < 0.0 ) || ( ( rearvehicle->PrevConnected != nullptr ) - && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == ctrain_virtual ) ) ) { + && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == coupling::faux ) ) ) { // scan behind if we're moving backward, or if we had something connected there and are moving away rearvehicle->ABuScanObjects( ( pVehicle->DirectionGet() == rearvehicle->DirectionGet() ? @@ -3656,6 +3701,8 @@ TController::UpdateSituation(double dt) { } } + + // tu bedzie logika sterowania if (AIControllFlag) { @@ -3903,6 +3950,11 @@ TController::UpdateSituation(double dt) { // NOTE: this will affect also multi-unit vehicles TBD: is this what we want? fMinProximityDist *= 2.0; fMaxProximityDist *= 2.0; + if( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) { + // additional safety margin for cargo consists + fMinProximityDist *= 2.0; + fMaxProximityDist *= 2.0; + } } fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania // margines prędkości powodujący załączenie napędu @@ -4207,7 +4259,7 @@ TController::UpdateSituation(double dt) { 0 : 1 ); // sprzęg z przodu składu if( ( coupler->Connected ) - && ( coupler->CouplingFlag == 0 ) ) { + && ( coupler->CouplingFlag == coupling::faux ) ) { // mamy coś z przodu podłączone sprzęgiem wirtualnym // wyliczanie optymalnego przyspieszenia do jazdy na widoczność ActualProximityDist = std::min( @@ -4515,24 +4567,16 @@ TController::UpdateSituation(double dt) { // zapobieganie poslizgowi u nas if (mvControlling->SlippingWheels) { - if (!mvControlling->DecScndCtrl(2)) // bocznik na zero - mvControlling->DecMainCtrl(1); -/* - if (mvOccupied->BrakeCtrlPos == - mvOccupied->BrakeCtrlPosNo) // jeśli ostatnia pozycja hamowania - //yB: ten warunek wyżej nie ma sensu - mvOccupied->DecBrakeLevel(); // to cofnij hamulec - DecBrake(); // to cofnij hamulec - else - mvControlling->AntiSlippingButton(); -*/ - DecBrake(); // to cofnij hamulec + if( false == mvControlling->DecScndCtrl( 2 ) ) { + // bocznik na zero + mvControlling->DecMainCtrl( 1 ); + } + DecBrake(); // cofnij hamulec mvControlling->AntiSlippingButton(); ++iDriverFailCount; - mvControlling->SlippingWheels = false; // flaga już wykorzystana } - if (iDriverFailCount > maxdriverfails) - { + if (iDriverFailCount > maxdriverfails) { + Psyche = Easyman; if (iDriverFailCount > maxdriverfails * 2) SetDriverPsyche(); diff --git a/DynObj.cpp b/DynObj.cpp index e61caee8..8ee6f237 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -1128,7 +1128,7 @@ void TDynamicObject::ABuCheckMyTrack() // Ra: w poniższej funkcji jest problem ze sprzęgami TDynamicObject * -TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Track, int const Direction, int const Mycoupler ) +TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ) { // Zwraca wskaźnik najbliższego obiektu znajdującego się // na torze w określonym kierunku, ale tylko wtedy, kiedy // obiekty mogą się zderzyć, tzn. nie mijają się. @@ -1170,7 +1170,15 @@ TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Trac for( auto dynamic : Track->Dynamics ) { if( dynamic == this ) { continue; } // szukający się nie liczy - +/* + if( ( ( dynamic == PrevConnected ) && ( MoverParameters->Couplers[ TMoverParameters::side::front ].CouplingFlag != coupling::faux ) ) + || ( ( dynamic == NextConnected ) && ( MoverParameters->Couplers[ TMoverParameters::side::rear ].CouplingFlag != coupling::faux ) ) ){ + // stop-gap check to prevent 'detection' of attached vehicles + // which seems to be a side-effect of inaccurate location calculation in 'simple' mode? + // TODO: investigate actual cause + continue; + } +*/ if( Direction > 0 ) { // jeśli szukanie w kierunku Point2 objectposition = ( dynamic->RaTranslationGet() ) - myposition; // odległogłość tamtego od szukającego @@ -1329,16 +1337,23 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) // ScanDir - określa kierunek poszukiwania zależnie od zwrotu prędkości // pojazdu // ScanDir=1 - od strony Coupler0, ScanDir=-1 - od strony Coupler1 - int initialdirection = Direction; // zapamiętanie kierunku poszukiwań na torze początkowym, względem sprzęgów - TTrackFollower *firstaxle = (initialdirection > 0 ? &Axle0 : &Axle1); // można by to trzymać w trainset - TTrack *track = firstaxle->GetTrack(); // tor na którym "stoi" skrajny wózek + auto const initialdirection = Direction; // zapamiętanie kierunku poszukiwań na torze początkowym, względem sprzęgów +/* + TTrackFollower const *firstaxle = (initialdirection > 0 ? &Axle0 : &Axle1); // można by to trzymać w trainset + TTrack const *track = firstaxle->GetTrack(); // tor na którym "stoi" skrajny wózek // (może być inny niż tor pojazdu) if( firstaxle->GetDirection() < 0 ) { // czy oś jest ustawiona w stronę Point1? Direction = -Direction; // jeśli tak, to kierunek szukania będzie przeciwny } - // (teraz względem - // toru) +*/ + TTrack const *track = RaTrackGet(); + if( RaDirectionGet() < 0 ) { + // czy oś jest ustawiona w stronę Point1? + Direction = -Direction; + } + + // (teraz względem toru) int const mycoupler = ( initialdirection < 0 ? 1 : 0 ); // numer sprzęgu do podłączenia w obiekcie szukajacym int foundcoupler { -1 }; // numer sprzęgu w znalezionym obiekcie (znaleziony wypełni) double distance = 0; // przeskanowana odleglość; odległość do zawalidrogi @@ -1348,9 +1363,9 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) // jeśli nie ma na tym samym, szukamy po okolicy szukanie najblizszego toru z jakims obiektem // praktycznie przeklejone z TraceRoute()... if (Direction >= 0) // uwzględniamy kawalek przeanalizowanego wcześniej toru - distance = track->Length() - firstaxle->GetTranslation(); // odległość osi od Point2 toru + distance = track->Length() - RaTranslationGet(); // odległość osi od Point2 toru else - distance = firstaxle->GetTranslation(); // odległość osi od Point1 toru + distance = RaTranslationGet(); // odległość osi od Point1 toru while (distance < Distance) { if (Direction > 0) { @@ -1456,6 +1471,14 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) // nic nie znalezione, to nie ma przeszkód fTrackBlock = 10000.0; } + +#ifdef EU07_DEBUG_COLLISIONS + // debug collider scans + if( ( PrevConnected != nullptr ) + && ( PrevConnected == NextConnected ) ) { + ErrorLog( "Bad coupling: " + asName + " has the same vehicle detected attached to both couplers" ); + } +#endif } //----------ABu: koniec skanowania pojazdow diff --git a/DynObj.h b/DynObj.h index bbf7b2d5..c8369855 100644 --- a/DynObj.h +++ b/DynObj.h @@ -359,7 +359,7 @@ public: // modele składowe pojazdu void ABuScanObjects(int ScanDir, double ScanDist); protected: - TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Track, int const Direction, int const Mycoupler ); + TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ); void ABuCheckMyTrack(); public: diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 77090dd5..b4882ed4 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1093,6 +1093,7 @@ void TMoverParameters::CollisionDetect(int CouplerN, double dt) coupler.Connected->Couplers[0].CouplingFlag = 0; break; } + WriteLog( "Bad driving: " + Name + " broke a coupler" ); } } } @@ -1267,11 +1268,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap AccN = g * Shape.dHrail / TrackW; // szarpanie - if (FuzzyLogic((10.0 + Track.DamageFlag) * Mass * Vel / Vmax, 500000.0, - p_accn)) // Ra: czemu tu masa bez ładunku? - AccV = sqrt((1.0 + Track.DamageFlag) * Random(floor(50.0 * Mass / 1000000.0)) * Vel / - (Vmax * (10.0 + (Track.QualityFlag & 31)))); +#ifdef EU07_USE_FUZZYLOGIC + if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) { + // Ra: czemu tu masa bez ładunku? + AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0) + } else +#endif AccV = AccV / 2.0; if (AccV > 1.0) @@ -1437,12 +1440,13 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape // else AccN:=g*Shape.dHrail/TrackW; // szarpanie} - if (FuzzyLogic((10.0 + Track.DamageFlag) * Mass * Vel / Vmax, 500000.0, p_accn)) - { - AccV = sqrt((1.0 + Track.DamageFlag) * Random(floor(50.0 * Mass / 1000000.0)) * Vel / - (Vmax * (10.0 + (Track.QualityFlag & 31)))); // Trunc na floor, czy dobrze? +#ifdef EU07_USE_FUZZYLOGIC + if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) { + // Ra: czemu tu masa bez ładunku? + AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0) } else +#endif AccV = AccV / 2.0; if (AccV > 1.0) diff --git a/Segment.cpp b/Segment.cpp index 393c4911..24efc10e 100644 --- a/Segment.cpp +++ b/Segment.cpp @@ -350,7 +350,7 @@ Math3D::vector3 TSegment::FastGetPoint(double const t) const { // return (bCurve?Interpolate(t,Point1,CPointOut,CPointIn,Point2):((1.0-t)*Point1+(t)*Point2)); return ( - ( ( true == bCurve ) || ( iSegCount == 1 ) ) ? + ( ( true == bCurve ) || ( iSegCount != 1 ) ) ? RaInterpolate( t ) : interpolate( Point1, Point2, t ) ); } diff --git a/Track.h b/Track.h index 6398b5d0..323bfb69 100644 --- a/Track.h +++ b/Track.h @@ -197,14 +197,14 @@ public: void ConnectPrevNext(TTrack *pNewPrev, int typ); void ConnectNextPrev(TTrack *pNewNext, int typ); void ConnectNextNext(TTrack *pNewNext, int typ); - inline double Length() { + inline double Length() const { return Segment->GetLength(); }; inline std::shared_ptr CurrentSegment() const { return Segment; }; - inline TTrack * CurrentNext() { - return (trNext); }; - inline TTrack * CurrentPrev() { - return (trPrev); }; + inline TTrack *CurrentNext() const { + return trNext; }; + inline TTrack *CurrentPrev() const { + return trPrev; }; TTrack * Neightbour(int s, double &d); bool SetConnections(int i); bool Switch(int i, double t = -1.0, double d = -1.0); diff --git a/TrkFoll.h b/TrkFoll.h index 88b18e48..f92b1708 100644 --- a/TrkFoll.h +++ b/TrkFoll.h @@ -47,7 +47,7 @@ class TTrackFollower { return fDirection; }; // zwrot na torze - inline double GetTranslation() + inline double GetTranslation() const { return fCurrentDistance; }; // ABu-030403 diff --git a/World.cpp b/World.cpp index 6cb4dc7f..2a3e8302 100644 --- a/World.cpp +++ b/World.cpp @@ -1053,17 +1053,19 @@ bool TWorld::Update() // this means at count > 20 simulation and render are going to desync. is that right? // NOTE: experimentally changing this to prevent the desync. // TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps - Ground.Update(dt / updatecount, updatecount); // tu zrobić tylko coklatkową aktualizację przesunięć + for( int updateidx = 0; updateidx < updatecount; ++updateidx ) { + Ground.Update( dt / updatecount, 1 ); // tu zrobić tylko coklatkową aktualizację przesunięć + } // yB dodał przyspieszacz fizyki if( (true == DebugModeFlag) && (true == Global::bActive) // nie przyspieszać, gdy jedzie w tle :) && ( glfwGetKey( window, GLFW_KEY_PAUSE ) == GLFW_PRESS ) ) { - Ground.Update( dt, updatecount ); - Ground.Update( dt, updatecount ); - Ground.Update( dt, updatecount ); - Ground.Update( dt, updatecount ); // 5 razy + Ground.Update( dt, 1 ); + Ground.Update( dt, 1 ); + Ground.Update( dt, 1 ); + Ground.Update( dt, 1 ); // 5 razy } // secondary fixed step simulation time routines diff --git a/version.h b/version.h index dadb643a..998e22bf 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 903 +#define VERSION_MINOR 905 #define VERSION_REVISION 0