From f6fa8ee09b597c38d036298cb0862ccd116e425d Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Thu, 14 Sep 2017 00:29:55 +0200 Subject: [PATCH] build 170913. improved AI driving on slopes, consist collision distance in whois event, cab render fix --- Driver.cpp | 54 +++++++++++++++++++++++++++++++----------- Driver.h | 67 ++++++++++++++++++---------------------------------- Ground.cpp | 20 +++++++++------- Train.cpp | 2 +- World.cpp | 4 ++++ renderer.cpp | 2 ++ version.h | 2 +- 7 files changed, 83 insertions(+), 68 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index bf99e184..48f71618 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1355,7 +1355,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // modifies brake distance for low target speeds, to ease braking rate in such situations float -TController::braking_distance_multiplier( float const Targetvelocity ) { +TController::braking_distance_multiplier( float const Targetvelocity ) const { if( Targetvelocity > 65.f ) { return 1.f; } if( Targetvelocity < 5.f ) { return 1.f; } @@ -3989,6 +3989,11 @@ TController::UpdateSituation(double dt) { // bottom margin raised to 2 km/h to give the AI more leeway at low speed limits fVelPlus = clamp( std::ceil( 0.05 * VelDesired ), 2.0, 5.0 ); } + if( mvOccupied->BrakeDelayFlag == bdelay_G ) { + // increase distances for cargo trains to take into account slower reaction to brakes + fMinProximityDist += 10.0; + fMaxProximityDist += 10.0; + } } else { // samochod (sokista też) @@ -4299,6 +4304,12 @@ TController::UpdateSituation(double dt) { if( vehicle->fTrackBlock <= fMinProximityDist ) { VelDesired = 0.0; } + + if( ( mvOccupied->CategoryFlag & 1 ) + && ( OrderCurrentGet() & Obey_train ) ) { + // trains which move normally should try to stop at safe margin + ActualProximityDist -= fDriverDist; + } } } else { @@ -4449,8 +4460,8 @@ TController::UpdateSituation(double dt) { // przeciwnie do zadanego kierunku jazdy //(AccDesired) porównujemy z (fAccGravity) albo (AbsAccS) if( ( VelNext >= 0.0 ) - && ( ActualProximityDist <= routescanrange ) - && ( vel >= VelNext ) ) { + && ( ActualProximityDist <= routescanrange ) + && ( vel >= VelNext ) ) { // gdy zbliża się i jest za szybki do nowej prędkości, albo stoi na zatrzymaniu if (vel > 0.0) { // jeśli jedzie @@ -4561,13 +4572,14 @@ TController::UpdateSituation(double dt) { // jesli jedzie za szybko do AKTUALNEGO if( VelDesired == 0.0 ) { // jesli stoj, to hamuj, ale i tak juz za pozno :) - AccDesired = std::min( AccDesired, -0.9 ); // hamuj solidnie + AccDesired = std::min( AccDesired, -0.85 ); // hamuj solidnie } else { - // slow down, not full stop - if( vel > ( VelDesired + fVelPlus ) ) { + // try to estimate increase of current velocity before engaged brakes start working + // if it looks like we'll exceed maximum allowed speed start thinking about slight slowing down + if( ( vel + vel * ( 1.0 - fBrake_a0[ 0 ] ) * AbsAccS ) > ( VelDesired + fVelPlus ) ) { // hamuj tak średnio - AccDesired = std::min( AccDesired, -fBrake_a0[ 0 ] * 0.5 ); + AccDesired = std::min( AccDesired, -0.25 ); } else { // o 5 km/h to olej (zacznij luzować) @@ -4581,6 +4593,8 @@ TController::UpdateSituation(double dt) { // last step sanity check, until the whole calculation is straightened out AccDesired = std::min( AccDesired, AccPreferred ); + // also take into account impact of gravity + AccDesired = clamp( AccDesired - fAccGravity, -0.9, 0.9 ); @@ -4637,15 +4651,20 @@ TController::UpdateSituation(double dt) { } // NOTE: as a stop-gap measure the routine is limited to trains only while car calculations seem off if( mvControlling->CategoryFlag == 1 ) { - if( -AccDesired * BrakeAccFactor() < ( - ( ( fReady > 0.4 ) || ( VelNext > vel - 40.0 ) ) ? - fBrake_a0[ 0 ] * 0.8 : - -fAccThreshold ) - / braking_distance_multiplier( VelNext ) ) { - AccDesired = std::max( -0.06, AccDesired ); + if( vel < VelDesired ) { + // don't adjust acceleration when going above current goal speed + if( -AccDesired * BrakeAccFactor() < ( + ( ( fReady > 0.4 ) + || ( VelNext > vel - 40.0 ) ) ? + fBrake_a0[ 0 ] * 0.8 : + -fAccThreshold ) + / braking_distance_multiplier( VelNext ) ) { + AccDesired = std::max( -0.06, AccDesired ); + } } else { - ReactionTime = 0.25; // i orientuj się szybciej, jeśli hamujesz + // i orientuj się szybciej, jeśli hamujesz + ReactionTime = 0.25; } } if (mvOccupied->BrakeSystem == Pneumatic) // napełnianie uderzeniowe @@ -5510,6 +5529,13 @@ bool TController::IsStop() return TrainParams->IsStop(); }; +// returns most recently calculated distance to potential obstacle ahead +double +TController::TrackBlock() const { + + return pVehicles[ TMoverParameters::side::front ]->fTrackBlock; +} + void TController::MoveTo(TDynamicObject *to) { // przesunięcie AI do innego pojazdu (przy zmianie kabiny) // mvOccupied->CabDeactivisation(); //wyłączenie kabiny w opuszczanym diff --git a/Driver.h b/Driver.h index 12c91d2a..c552dfa8 100644 --- a/Driver.h +++ b/Driver.h @@ -186,8 +186,8 @@ class TController 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 +public: double fAccGravity = 0.0; // przyspieszenie składowej stycznej grawitacji - public: TEvent *eSignNext = nullptr; // sygnał zmieniający prędkość, do pokazania na [F2] std::string asNextStop; // nazwa następnego punktu zatrzymania wg rozkładu int iStationStart = 0; // numer pierwszej stacji pokazywanej na podglądzie rozkładu @@ -245,25 +245,20 @@ private: double AccPreferred = 0.0; // preferowane przyspieszenie (wg psychiki kierującego, zmniejszana przy wykryciu kolizji) double AccDesired = AccPreferred; // przyspieszenie, jakie ma utrzymywać (<0:nie przyspieszaj,<-0.1:hamuj) double VelDesired = 0.0; // predkość, z jaką ma jechać, wynikająca z analizy tableki; <=VelSignal - double fAccDesiredAv = 0.0; // uśrednione przyspieszenie z kolejnych przebłysków świadomości, żeby - // ograniczyć migotanie - public: + double fAccDesiredAv = 0.0; // uśrednione przyspieszenie z kolejnych przebłysków świadomości, żeby ograniczyć migotanie double VelforDriver = -1.0; // prędkość, używana przy zmianie kierunku (ograniczenie przy nieznajmości szlaku?) double VelSignal = 0.0; // ograniczenie prędkości z kompilacji znaków i sygnałów // normalnie na początku ma stać, no chyba że jedzie double VelLimit = -1.0; // predkość zadawana przez event jednokierunkowego ograniczenia prędkości // -1: brak ograniczenia prędkości - public: double VelSignalLast = -1.0; // prędkość zadana na ostatnim semaforze // ostatni semafor też bez ograniczenia double VelSignalNext = 0.0; // prędkość zadana na następnym semaforze double VelLimitLast = -1.0; // prędkość zadana przez ograniczenie // ostatnie ograniczenie bez ograniczenia double VelRoad = -1.0; // aktualna prędkość drogowa (ze znaku W27) (PutValues albo komendą) // prędkość drogowa bez ograniczenia - public: double VelNext = 120.0; // prędkość, jaka ma być po przejechaniu długości ProximityDist private: double fProximityDist = 0.0; // odleglosc podawana w SetProximityVelocity(); >0:przeliczać do punktu, <0:podana wartość double FirstSemaphorDist = 10000.0; // odległość do pierwszego znalezionego semafora public: - double - ActualProximityDist = 1.0; // odległość brana pod uwagę przy wyliczaniu prędkości i przyspieszenia + double ActualProximityDist = 1.0; // odległość brana pod uwagę przy wyliczaniu prędkości i przyspieszenia private: vector3 vCommandLocation; // polozenie wskaznika, sygnalizatora lub innego obiektu do ktorego // odnosi sie komenda @@ -297,7 +292,7 @@ private: double fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku) double WaitingTime = 0.0; // zliczany czas oczekiwania do samoistnego ruszenia double WaitingExpireTime = 31.0; // tyle ma czekać, zanim się ruszy // maksymlany czas oczekiwania do samoistnego ruszenia - // TEvent* eSignLast; //ostatnio znaleziony sygnał, o ile nie minięty + private: //---//---//---//---// koniec zmiennych, poniżej metody //---//---//---//---// void SetDriverPsyche(); bool PrepareEngine(); @@ -314,23 +309,16 @@ private: void AutoRewident(); // ustawia hamulce w składzie double ESMVelocity(bool Main); public: - Mtable::TTrainParameters *Timetable() - { - return TrainParams; - }; + Mtable::TTrainParameters *Timetable() { + return TrainParams; }; void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason = stopComm); bool PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const vector3 *NewLocation, TStopReason reason = stopComm); void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę // procedury dotyczace rozkazow dla maszynisty - void SetVelocity(double NewVel, double NewVelNext, - TStopReason r = stopNone); // uaktualnia informacje o prędkości -/* - bool SetProximityVelocity( - double NewDist, - double NewVelNext); // uaktualnia informacje o prędkości przy nastepnym semaforze -*/ + // uaktualnia informacje o prędkości + void SetVelocity(double NewVel, double NewVelNext, TStopReason r = stopNone); public: void JumpToNextOrder(); void JumpToFirstOrder(); @@ -349,9 +337,7 @@ private: void OrdersInit(double fVel); void OrdersClear(); void OrdersDump(); - TController(bool AI, TDynamicObject *NewControll, bool InitPsyche, - bool primary = true // czy ma aktywnie prowadzić? - ); + TController( bool AI, TDynamicObject *NewControll, bool InitPsyche, bool primary = true ); std::string OrderCurrent(); void WaitingSet(double Seconds); @@ -360,33 +346,24 @@ private: void DirectionForward(bool forward); int OrderDirectionChange(int newdir, TMoverParameters *Vehicle); void Lights(int head, int rear); -// double Distance(vector3 &p1, vector3 &n, vector3 &p2); - - private: // Ra: metody obsługujące skanowanie toru + // Ra: metody obsługujące skanowanie toru TEvent *CheckTrackEvent(TTrack *Track, double const fDirection ) const; -// bool TableCheckEvent(TEvent *e); bool TableAddNew(); bool TableNotFound(TEvent const *Event) const; -// TEvent *TableCheckTrackEvent(double fDirection, TTrack *Track); void TableTraceRoute(double fDistance, TDynamicObject *pVehicle = nullptr); void TableCheck(double fDistance); TCommandType TableUpdate(double &fVelDes, double &fDist, double &fNext, double &fAcc); // modifies brake distance for low target speeds, to ease braking rate in such situations float - braking_distance_multiplier( float const Targetvelocity ); + braking_distance_multiplier( float const Targetvelocity ) const; void TablePurger(); void TableSort(); - inline double MoveDistanceGet() - { - return dMoveLen; - } - inline void MoveDistanceReset() - { - dMoveLen = 0.0; - } + inline double MoveDistanceGet() const { + return dMoveLen; } + inline void MoveDistanceReset() { + dMoveLen = 0.0; } public: - inline void MoveDistanceAdd(double distance) - { + 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(); } @@ -396,8 +373,7 @@ private: private: // Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu bool BackwardTrackBusy(TTrack *Track); TEvent *CheckTrackEventBackward(double fDirection, TTrack *Track); - TTrack *BackwardTraceRoute(double &fDistance, double &fDirection, TTrack *Track, - TEvent *&Event); + TTrack *BackwardTraceRoute(double &fDistance, double &fDirection, TTrack *Track, TEvent *&Event); void SetProximityVelocity(double dist, double vel, const vector3 *pos); TCommandType BackwardScan(); @@ -417,13 +393,16 @@ private: return ( ( iDrivigFlags & movePrimary ) != 0 ); }; inline int DrivigFlags() const { - return iDrivigFlags; - }; + return iDrivigFlags; }; + // returns most recently calculated distance to potential obstacle ahead + double + TrackBlock() const; void MoveTo(TDynamicObject *to); void DirectionInitial(); std::string TableText(std::size_t const Index); int CrossRoute(TTrack *tr); void RouteSwitch(int d); std::string OwnerName() const; - TMoverParameters const *Controlling() const { return mvControlling; } + TMoverParameters const *Controlling() const { + return mvControlling; } }; diff --git a/Ground.cpp b/Ground.cpp index 36173b84..ca36f1fb 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -2426,7 +2426,7 @@ bool TGround::InitEvents() Current->Params[9].asTrack = tmp->pTrack; if (!Current->Params[9].asTrack) { - ErrorLog("Bad event: Track \"" + cellastext + "\" does not exist in \"" + Current->asName + "\""); + ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find track \"" + cellastext + "\"" ); Current->iFlags &= ~(conditional_trackoccupied | conditional_trackfree); // zerowanie flag } } @@ -2437,7 +2437,7 @@ bool TGround::InitEvents() Current->Params[9].asMemCell = tmp->MemCell; if (!Current->Params[9].asMemCell) { - ErrorLog("Bad event: MemCell \"" + cellastext + "\" does not exist in \"" + Current->asName + "\""); + ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find memory cell \"" + cellastext + "\"" ); Current->iFlags &= ~(conditional_memstring | conditional_memval1 | conditional_memval2); } } @@ -2448,13 +2448,13 @@ bool TGround::InitEvents() cellastext = Current->Params[ i ].asText; SafeDeleteArray(Current->Params[i].asText); Current->Params[i].asEvent = FindEvent(cellastext); - if( !Current->Params[ i ].asEvent ) { // Ra: tylko w logu informacja o braku + if( !Current->Params[ i ].asEvent ) { + // Ra: tylko w logu informacja o braku if( ( Current->Params[ i ].asText == NULL ) || ( std::string( Current->Params[ i ].asText ).substr( 0, 5 ) != "none_" ) ) { - WriteLog( "Event \"" + cellastext + "\" does not exist" ); - ErrorLog( "Missed event: " + cellastext + " in multiple " + Current->asName ); + ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find event \"" + cellastext + "\"" ); } - } + } } } break; @@ -3401,18 +3401,22 @@ bool TGround::CheckQuery() owner != nullptr ? owner->fReady : -1.0 ); + auto const collisiondistance = ( + owner != nullptr ? + owner->TrackBlock() : + -1.0 ); tmpEvent->Params[ 9 ].asMemCell->UpdateValues( tmpEvent->Activator->MoverParameters->TypeName, // typ pojazdu consistbrakelevel, - 0, // na razie nic + collisiondistance, tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) ); WriteLog( "whois request (" + to_string( tmpEvent->iFlags ) + ") " + "[name: " + tmpEvent->Activator->MoverParameters->TypeName + "], " + "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], " - + "[]" ); + + "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" ); } else { // jeśli parametry ładunku diff --git a/Train.cpp b/Train.cpp index 8610ebce..89fd9182 100644 --- a/Train.cpp +++ b/Train.cpp @@ -2497,7 +2497,7 @@ void TTrain::OnCommand_instrumentlighttoggle( TTrain *Train, command_data const // TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels if( Train->ggInstrumentLightButton.SubModel == nullptr ) { if( Command.action == GLFW_PRESS ) { - WriteLog( "Universal3 switch is missing, or wasn't defined" ); + WriteLog( "Instrument light switch is missing, or wasn't defined" ); } return; } diff --git a/World.cpp b/World.cpp index 8aa6ee88..658205e1 100644 --- a/World.cpp +++ b/World.cpp @@ -1433,6 +1433,10 @@ TWorld::Update_UI() { + ", Fr: " + to_string( tmp->MoverParameters->RunningTrack.friction, 2 ) + ( tmp->MoverParameters->SlippingWheels ? " (!)" : "" ); + if( tmp->Mechanik ) { + uitextline2 += "; Ag: " + to_string( tmp->Mechanik->fAccGravity, 2 ); + } + uitextline2 += "; TC:" + to_string( tmp->MoverParameters->TotalCurrent, 0 ); diff --git a/renderer.cpp b/renderer.cpp index 46f896e9..3ca7eadc 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -22,6 +22,8 @@ http://mozilla.org/MPL/2.0/. #include "logs.h" #include "usefull.h" +#define EU07_NEW_CAB_RENDERCODE + opengl_renderer GfxRenderer; extern TWorld World; diff --git a/version.h b/version.h index 50d73e58..b11e1ac6 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 911 +#define VERSION_MINOR 913 #define VERSION_REVISION 0