mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 00:49:19 +02:00
Merge pull request #88 from jakubg1/dev
Simplify internal derailing logic, improve warning signals before closing doors in certain EMUs
This commit is contained in:
@@ -122,7 +122,18 @@ static int const dtrain_loaddestroyed = 32;/*dla wagonow*/
|
||||
static int const dtrain_axle = 64;
|
||||
static int const dtrain_out = 128; /*wykolejenie*/
|
||||
static int const dtrain_pantograph = 256; /*polamanie pantografu*/
|
||||
/*wagi prawdopodobienstwa dla funkcji FuzzyLogic*/
|
||||
|
||||
/*przyczyny wykolejenia*/
|
||||
enum DerailReason {
|
||||
NONE = 0,
|
||||
END_OF_TRACK = 1, // Ra: powód wykolejenia: brak szyn
|
||||
TOO_HIGH_SPEED = 2, // Ra: powód wykolejenia: przewrócony na łuku
|
||||
GAUGE_MISMATCH = 3, // Ra: powód wykolejenia: za szeroki tor
|
||||
WRONG_TRACK_TYPE = 4, // Ra: powód wykolejenia: nieodpowiednia trajektoria
|
||||
COLLISION = 5, // powód wykolejenia: zderzenie z innym pojazdem
|
||||
};
|
||||
|
||||
/*wagi prawdopodobienstwa dla funkcji FuzzyLogic*/
|
||||
#define p_elengproblem (1e-02)
|
||||
#define p_elengdamage (1e-01)
|
||||
#define p_coupldmg (2e-03)
|
||||
@@ -1590,7 +1601,6 @@ class TMoverParameters
|
||||
|
||||
int DamageFlag = 0; // kombinacja bitowa stalych dtrain_* }
|
||||
int EngDmgFlag = 0; // kombinacja bitowa stalych usterek}
|
||||
int DerailReason = 0; // przyczyna wykolejenia
|
||||
|
||||
// EndSignalsFlag: byte; {ABu 060205: zmiany - koncowki: 1/16 - swiatla prz/tyl, 2/31 - blachy prz/tyl}
|
||||
// HeadSignalsFlag: byte; {ABu 060205: zmiany - swiatla: 1/2/4 - przod, 16/32/63 - tyl}
|
||||
@@ -1832,7 +1842,7 @@ public:
|
||||
int DettachStatus(int ConnectNo);
|
||||
bool Dettach(int ConnectNo);
|
||||
void damage_coupler( int const End );
|
||||
void derail( int const Reason );
|
||||
void Derail(DerailReason Reason);
|
||||
bool DirectionForward();
|
||||
bool DirectionBackward( void );/*! kierunek ruchu*/
|
||||
bool EIMDirectionChangeAllow( void ) const;
|
||||
|
||||
@@ -1252,10 +1252,10 @@ void TMoverParameters::CollisionDetect(int const End, double const dt)
|
||||
}
|
||||
|
||||
if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) {
|
||||
derail( 5 );
|
||||
Derail(COLLISION);
|
||||
}
|
||||
if( velocitydifference > safevelocitylimit * ( othervehicle->TotalMass / TotalMass ) ) {
|
||||
othervehicle->derail( 5 );
|
||||
othervehicle->Derail(COLLISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1318,24 +1318,31 @@ TMoverParameters::damage_coupler( int const End ) {
|
||||
WriteLog( "Bad driving: " + Name + " broke a coupler" );
|
||||
}
|
||||
|
||||
void
|
||||
TMoverParameters::derail( int const Reason ) {
|
||||
|
||||
void TMoverParameters::Derail( DerailReason const Reason ) {
|
||||
if( SetFlag( DamageFlag, dtrain_out ) ) {
|
||||
|
||||
DerailReason = Reason; // TODO: enum derail causes
|
||||
EventFlag = true;
|
||||
MainSwitch( false, range_t::local );
|
||||
|
||||
AccS *= 0.65;
|
||||
V *= 0.65;
|
||||
RunningShape.R = 0;
|
||||
if( Vel < 5.0 ) {
|
||||
// HACK: prevent permanent axle spin in static vehicle after a collision
|
||||
nrot = 0.0;
|
||||
SlippingWheels = false;
|
||||
}
|
||||
|
||||
WriteLog( "Bad driving: " + Name + " derailed" );
|
||||
// Print a message in the log.
|
||||
if (Reason == END_OF_TRACK)
|
||||
ErrorLog("Bad driving: " + Name + " derailed due to end of track");
|
||||
else if (Reason == TOO_HIGH_SPEED)
|
||||
ErrorLog("Bad driving: " + Name + " derailed due to too high speed");
|
||||
else if (Reason == GAUGE_MISMATCH)
|
||||
ErrorLog("Bad dynamic: " + Name + " derailed due to track width"); // błąd w scenerii
|
||||
else if (Reason == WRONG_TRACK_TYPE)
|
||||
ErrorLog("Bad dynamic: " + Name + " derailed due to wrong track type"); // błąd w scenerii
|
||||
else if (Reason == COLLISION)
|
||||
WriteLog("Bad driving: " + Name + " derailed"); // This reason also generates its own message in `TMoverParameters::CollisionDetect()`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1436,42 +1443,17 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
|
||||
// wykolejanie na luku oraz z braku szyn
|
||||
if (TestFlag(CategoryFlag, 1))
|
||||
{
|
||||
if (FuzzyLogic((AccN / g) * (1.0 + 0.1 * (Track.DamageFlag && dtrack_freerail)),
|
||||
TrackW / Dim.H, 1) ||
|
||||
TestFlag(Track.DamageFlag, dtrack_norail))
|
||||
if (SetFlag(DamageFlag, dtrain_out))
|
||||
{
|
||||
EventFlag = true;
|
||||
MainSwitch( false, range_t::local );
|
||||
RunningShape.R = 0;
|
||||
if (TestFlag(Track.DamageFlag, dtrack_norail))
|
||||
DerailReason = 1; // Ra: powód wykolejenia: brak szyn
|
||||
else
|
||||
DerailReason = 2; // Ra: powód wykolejenia: przewrócony na łuku
|
||||
}
|
||||
if (TestFlag(Track.DamageFlag, dtrack_norail))
|
||||
Derail(END_OF_TRACK);
|
||||
if (FuzzyLogic((AccN / g) * (1.0 + 0.1 * (Track.DamageFlag & dtrack_freerail)), TrackW / Dim.H, 1))
|
||||
Derail(TOO_HIGH_SPEED);
|
||||
// wykolejanie na poszerzeniu toru
|
||||
if (FuzzyLogic(abs(Track.Width - TrackW), TrackW / 10.0, 1))
|
||||
if (SetFlag(DamageFlag, dtrain_out))
|
||||
{
|
||||
EventFlag = true;
|
||||
MainSwitch( false, range_t::local );
|
||||
RunningShape.R = 0;
|
||||
DerailReason = 3; // Ra: powód wykolejenia: za szeroki tor
|
||||
}
|
||||
Derail(GAUGE_MISMATCH);
|
||||
}
|
||||
// wykolejanie wkutek niezgodnosci kategorii toru i pojazdu
|
||||
if (!TestFlag(RunningTrack.CategoryFlag, CategoryFlag))
|
||||
if (SetFlag(DamageFlag, dtrain_out))
|
||||
{
|
||||
EventFlag = true;
|
||||
MainSwitch( false, range_t::local );
|
||||
DerailReason = 4; // Ra: powód wykolejenia: nieodpowiednia trajektoria
|
||||
}
|
||||
if( ( true == TestFlag( DamageFlag, dtrain_out ) )
|
||||
&& ( Vel < 1.0 ) ) {
|
||||
V = 0.0;
|
||||
AccS = 0.0;
|
||||
}
|
||||
Derail(WRONG_TRACK_TYPE);
|
||||
|
||||
// dL:=(V+AccS*dt/2)*dt;
|
||||
// przyrost dlugosci czyli przesuniecie
|
||||
|
||||
@@ -1138,9 +1138,12 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
|
||||
"Current order: [" + std::to_string( mechanik.OrderPos ) + "] "
|
||||
+ mechanik.Order2Str( mechanik.OrderCurrentGet() );
|
||||
|
||||
if( mechanik.fStopTime < 0.0 ) {
|
||||
textline += "\n stop time: " + to_string( std::abs( mechanik.fStopTime ), 1 );
|
||||
}
|
||||
if( mechanik.fStopTime < 0.0 ) {
|
||||
textline += "\n stop time: " + to_string( std::abs( mechanik.fStopTime ), 1 );
|
||||
}
|
||||
if( mechanik.fActionTime < 0.0 ) {
|
||||
textline += "\n action time: " + to_string( std::abs( mechanik.fActionTime ), 1 );
|
||||
}
|
||||
|
||||
Output.emplace_back( textline, Global.UITextColor );
|
||||
|
||||
@@ -1231,7 +1234,8 @@ 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", "SignalFound", "StopPointFound" /*"SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound"*/ };
|
||||
"Visibility", "DoorOpened", "PushPull", "SignalFound", "StopPointFound", "GuardOpenDoor", "DepartureWarned"
|
||||
/*"SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound"*/ };
|
||||
|
||||
textline = "Driving flags:";
|
||||
for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) {
|
||||
|
||||
@@ -4359,62 +4359,61 @@ void TController::Doors( bool const Open, int const Side ) {
|
||||
if( ( false == doors_permit_active() )
|
||||
&& ( false == doors_open() ) ) {
|
||||
iDrivigFlags &= ~moveDoorOpened;
|
||||
iDrivigFlags &= ~moveDepartureWarned;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mvOccupied->Doors.has_warning && !TestFlag(iDrivigFlags, moveDepartureWarned))
|
||||
{
|
||||
if (!mvOccupied->DepartureSignal)
|
||||
{
|
||||
// Not warned yet, not warning yet - start the warning signal.
|
||||
cue_action( driver_hint::departuresignalon ); // załącenie bzyczka
|
||||
fActionTime = Random( -0.3, -0.8 ); // 0.3-0.8 second buzzer
|
||||
return;
|
||||
}
|
||||
// Not warned yet, warning now - stop the warning signal and mark it as done.
|
||||
cue_action( driver_hint::departuresignaloff );
|
||||
fActionTime = Random( 0.0, -0.2 ); // Wait just a bit more before departing
|
||||
iDrivigFlags |= moveDepartureWarned;
|
||||
return;
|
||||
}
|
||||
|
||||
if( true == doors_open() ) {
|
||||
if( ( true == mvOccupied->Doors.has_warning )
|
||||
&& ( false == mvOccupied->DepartureSignal )
|
||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||
cue_action( driver_hint::departuresignalon ); // załącenie bzyczka
|
||||
fActionTime = -1.5 - 0.1 * Random( 10 ); // 1.5-2.5 second wait
|
||||
// consist-wide remote signals to close doors
|
||||
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) {
|
||||
cue_action( driver_hint::doorrightclose );
|
||||
cue_action( driver_hint::doorleftclose );
|
||||
}
|
||||
}
|
||||
if( true == doors_permit_active() ) {
|
||||
cue_action( driver_hint::doorrightpermitoff );
|
||||
cue_action( driver_hint::doorleftpermitoff );
|
||||
}
|
||||
// if applicable close manually-operated doors in vehicles which may ignore remote signals
|
||||
{
|
||||
const auto *vehicle = pVehicles[ end::front ]; // pojazd na czole składu
|
||||
while( vehicle != nullptr ) {
|
||||
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||
auto const ismanualdoor {
|
||||
( vehicle->MoverParameters->Doors.auto_velocity == -1.f )
|
||||
&& ( ( vehicle->MoverParameters->Doors.close_control == control_t::passenger )
|
||||
|| ( vehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) };
|
||||
|
||||
if( ( false == AIControllFlag ) || ( fActionTime > -0.5 ) ) {
|
||||
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
|
||||
if( true == doors_open() ) {
|
||||
// consist-wide remote signals to close doors
|
||||
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) {
|
||||
cue_action( driver_hint::doorrightclose );
|
||||
cue_action( driver_hint::doorleftclose );
|
||||
if( ( true == ismanualdoor )
|
||||
&& ( ( vehicle->LoadExchangeTime() == 0.f )
|
||||
|| ( vehicle->MoverParameters->Vel > EU07_AI_MOVEMENT ) ) ) {
|
||||
vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local );
|
||||
vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
|
||||
}
|
||||
}
|
||||
if( true == doors_permit_active() ) {
|
||||
cue_action( driver_hint::doorrightpermitoff );
|
||||
cue_action( driver_hint::doorleftpermitoff );
|
||||
}
|
||||
// if applicable close manually-operated doors in vehicles which may ignore remote signals
|
||||
{
|
||||
auto *vehicle = pVehicles[ end::front ]; // pojazd na czole składu
|
||||
while( vehicle != nullptr ) {
|
||||
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||
auto const ismanualdoor {
|
||||
( vehicle->MoverParameters->Doors.auto_velocity == -1.f )
|
||||
&& ( ( vehicle->MoverParameters->Doors.close_control == control_t::passenger )
|
||||
|| ( vehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) };
|
||||
|
||||
if( ( true == ismanualdoor )
|
||||
&& ( ( vehicle->LoadExchangeTime() == 0.f )
|
||||
|| ( vehicle->MoverParameters->Vel > EU07_AI_MOVEMENT ) ) ) {
|
||||
vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local );
|
||||
vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
|
||||
}
|
||||
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
||||
}
|
||||
}
|
||||
fActionTime = -2.0 - 0.1 * Random( 15 ); // 2.0-3.5 sec wait, +potentially 0.5 remaining
|
||||
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
|
||||
|
||||
if( ( true == mvOccupied->DepartureSignal )
|
||||
&& ( Random( 100 ) < Random( 100 ) ) ) {
|
||||
// potentially turn off the warning before actual departure
|
||||
// TBD, TODO: dedicated buzzer duration counter?
|
||||
cue_action( driver_hint::departuresignaloff );
|
||||
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
||||
}
|
||||
}
|
||||
fActionTime = Random( -1.0, -3.5 ); // 1.0-3.5 sec wait
|
||||
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
|
||||
iDrivigFlags &= ~moveDepartureWarned;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ enum TMovementStatus
|
||||
movePushPull = 0x40000, // zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku
|
||||
moveSignalFound = 0x80000, // na drodze skanowania został znaleziony semafor
|
||||
moveStopPointFound = 0x100000, // stop point detected ahead
|
||||
moveGuardOpenDoor = 0x200000 // time for opening a door before departure
|
||||
moveGuardOpenDoor = 0x200000, // time for opening a door before departure
|
||||
moveDepartureWarned = 0x400000 // driver has already warned about the doors being closed (only for manual warning - i.e. EN57-ish)
|
||||
/*
|
||||
moveSemaphorWasElapsed = 0x100000, // minięty został semafor
|
||||
moveTrainInsideStation = 0x200000, // pociąg między semaforem a rozjazdami lub następnym semaforem
|
||||
|
||||
@@ -4265,27 +4265,6 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
MoverParameters->InactiveCabPantsCheck = false;
|
||||
}
|
||||
|
||||
|
||||
if (MoverParameters->DerailReason > 0)
|
||||
{
|
||||
switch (MoverParameters->DerailReason)
|
||||
{
|
||||
case 1:
|
||||
ErrorLog("Bad driving: " + asName + " derailed due to end of track");
|
||||
break;
|
||||
case 2:
|
||||
ErrorLog("Bad driving: " + asName + " derailed due to too high speed");
|
||||
break;
|
||||
case 3:
|
||||
ErrorLog("Bad dynamic: " + asName + " derailed due to track width");
|
||||
break; // błąd w scenerii
|
||||
case 4:
|
||||
ErrorLog("Bad dynamic: " + asName + " derailed due to wrong track type");
|
||||
break; // błąd w scenerii
|
||||
}
|
||||
MoverParameters->DerailReason = 0; //żeby tylko raz
|
||||
}
|
||||
|
||||
if( MoverParameters->LoadStatus ) {
|
||||
LoadUpdate(); // zmiana modelu ładunku
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user